Completed
Pull Request — master (#4)
by thomas
03:55
created

TrustStoreLoader   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 96.77%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 5
dl 0
loc 96
ccs 30
cts 31
cp 0.9677
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A fromSystem() 0 14 4
A fromComposerBundle() 0 4 1
A fromFile() 0 18 4
B fromDirectory() 0 22 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Bip70\X509;
6
7
use Composer\CaBundle\CaBundle;
8
use Sop\CryptoEncoding\PEM;
9
use Sop\CryptoEncoding\PEMBundle;
10
use X509\Certificate\Certificate;
11
use X509\Certificate\CertificateBundle;
12
13
class TrustStoreLoader
14
{
15
    /**
16
     * Loads the currently installed ca-certificates file.
17
     * The approach taken by composer/ca-bundle is to attempt
18
     * to load certificates if openssl-like envvars and
19
     * config values are set.
20
     *
21
     * If $allowFallback is false, and the bundled composer
22
     * ca file is returned, an exception will be thrown.
23
     *
24
     * @see CaBundle::getSystemCaRootBundlePath()
25
     * @param bool $allowFallback
26
     * @return CertificateBundle
27
     */
28 5
    public static function fromSystem(bool $allowFallback = true): CertificateBundle
29
    {
30 5
        $rootBundlePath = CaBundle::getSystemCaRootBundlePath();
31
32 5
        if (!$allowFallback && CaBundle::getBundledCaBundlePath() === $rootBundlePath) {
33 1
            throw new \RuntimeException("Fallback to composer ca-bundle is disabled - you should install the ca-certificates package");
34
        }
35
36 4
        if (is_dir($rootBundlePath)) {
37 1
            return self::fromDirectory($rootBundlePath);
38
        } else {
39 3
            return self::fromFile($rootBundlePath);
40
        }
41
    }
42
43
    /**
44
     * Loads a trust store completely controlled by what is
45
     * included in the `composer/ca-bundle` package.
46
     * @return CertificateBundle
47
     */
48 1
    public static function fromComposerBundle(): CertificateBundle
49
    {
50 1
        return self::fromFile(CaBundle::getBundledCaBundlePath());
51
    }
52
53
    /**
54
     * Load a trust store from a pem bundle file (can contain
55
     * multiple certificates)
56
     *
57
     * @param string $file
58
     * @return CertificateBundle
59
     */
60 6
    public static function fromFile(string $file): CertificateBundle
61
    {
62 6
        $pemBundle = PEMBundle::fromFile($file);
63 6
        $certificates = [];
64 6
        foreach ($pemBundle as $pem) {
65
            try {
66 6
                $certificate = Certificate::fromPEM($pem);
67 6
                $certificates[] = $certificate;
68 6
            } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
69
            }
70
        }
71
72 6
        if (count($certificates) < 1) {
73
            throw new \RuntimeException("No certificates in file");
74
        }
75
76 6
        return new CertificateBundle(...$certificates);
77
    }
78
79
    /**
80
     * Load a trust store from a pem bundle file (can contain
81
     * multiple certificates)
82
     *
83
     * @param string $dir
84
     * @return CertificateBundle
85
     */
86 4
    public static function fromDirectory(string $dir): CertificateBundle
87
    {
88 4
        if (!is_dir($dir)) {
89 1
            throw new \RuntimeException("Invalid path passed to fromDirectory, is not a directory");
90
        }
91
92 3
        $certificates = [];
93 3
        foreach (glob("$dir/*.pem") as $pemFile) {
94
            try {
95 2
                $pem = PEM::fromFile($pemFile);
96 2
                $certificate = Certificate::fromPEM($pem);
97 2
                $certificates[] = $certificate;
98 2
            } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
99
            }
100
        }
101
102 3
        if (count($certificates) < 1) {
103 1
            throw new \RuntimeException("No PEM files in directory");
104
        }
105
106 2
        return new CertificateBundle(...$certificates);
107
    }
108
}
109