KeyLoader::getKeys()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\Certificate;
6
7
use SimpleSAML\SAML2\Certificate\Exception\InvalidCertificateStructureException;
8
use SimpleSAML\SAML2\Certificate\Exception\NoKeysFoundException;
9
use SimpleSAML\SAML2\Certificate\KeyCollection;
10
use SimpleSAML\SAML2\Configuration\CertificateProvider;
11
use SimpleSAML\SAML2\Utilities\File;
12
use SimpleSAML\XMLSecurity\Utils\Certificate;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\XMLSecurity\Utils\Certificate was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Traversable;
14
15
use function count;
16
use function preg_match;
17
use function sprintf;
18
19
/**
20
 * KeyLoader
21
 */
22
class KeyLoader
23
{
24
    /**
25
     * @var \SimpleSAML\SAML2\Certificate\KeyCollection
26
     */
27
    private KeyCollection $loadedKeys;
28
29
30
    /**
31
     * Constructor for KeyLoader.
32
     */
33
    public function __construct()
34
    {
35
        $this->loadedKeys = new KeyCollection();
36
    }
37
38
39
    /**
40
     * Extracts the public keys given by the configuration. Mainly exists for BC purposes.
41
     * Prioritisation order is keys > certData > certificate
42
     *
43
     * @param \SimpleSAML\SAML2\Configuration\CertificateProvider $config
44
     * @return \SimpleSAML\SAML2\Certificate\KeyCollection
45
     */
46
    public static function extractPublicKeys(
47
        CertificateProvider $config,
48
        ?string $usage = null,
49
        bool $required = false,
50
    ): KeyCollection {
51
        $keyLoader = new self();
52
53
        return $keyLoader->loadKeysFromConfiguration($config, $usage, $required);
54
    }
55
56
57
    /**
58
     * @param \SimpleSAML\SAML2\Configuration\CertificateProvider $config
59
     * @return \SimpleSAML\SAML2\Certificate\KeyCollection
60
     */
61
    public function loadKeysFromConfiguration(
62
        CertificateProvider $config,
63
        ?string $usage = null,
64
        bool $required = false,
65
    ): KeyCollection {
66
        $keys = $config->getKeys();
67
        $certificateData = $config->getCertificateData();
68
        $certificateFile = $config->getCertificateFile();
69
70
        if ($keys !== null) {
71
            $this->loadKeys($keys, $usage);
72
        } elseif ($certificateData !== null) {
73
            $this->loadCertificateData($certificateData);
74
        } elseif ($certificateFile !== null) {
75
            $this->loadCertificateFile($certificateFile);
76
        }
77
78
        if ($required && !$this->hasKeys()) {
79
            throw new NoKeysFoundException(
80
                'No keys found in configured metadata, please ensure that either the "keys", "certData" or '
81
                . '"certificate" entries is available.',
82
            );
83
        }
84
85
        return $this->getKeys();
86
    }
87
88
89
    /**
90
     * Loads the keys given, optionally excluding keys when a usage is given and they
91
     * are not configured to be used with the usage given
92
     */
93
    public function loadKeys(array|Traversable $configuredKeys, ?string $usage = null): void
94
    {
95
        foreach ($configuredKeys as $keyData) {
96
            if (isset($keyData['X509Certificate'])) {
97
                $key = new X509($keyData);
98
            } else {
99
                $key = new Key($keyData);
100
            }
101
102
            if ($usage && !$key->canBeUsedFor($usage)) {
103
                continue;
104
            }
105
106
            $this->loadedKeys->add($key);
107
        }
108
    }
109
110
111
    /**
112
     * Attempts to load a key based on the given certificateData
113
     */
114
    public function loadCertificateData(string $certificateData): void
115
    {
116
        $this->loadedKeys->add(X509::createFromCertificateData($certificateData));
117
    }
118
119
120
    /**
121
     * Loads the certificate in the file given
122
     *
123
     * @param string $certificateFile the full path to the cert file.
124
     */
125
    public function loadCertificateFile(string $certificateFile): void
126
    {
127
        $certificate = File::getFileContents($certificateFile);
128
        if (!Certificate::hasValidStructure($certificate)) {
129
            throw new InvalidCertificateStructureException(sprintf(
130
                'Could not find PEM encoded certificate in "%s"',
131
                $certificateFile,
132
            ));
133
        }
134
135
        // capture the certificate contents without the delimiters
136
        preg_match(Certificate::PUBLIC_KEY_PATTERN, $certificate, $matches);
137
        $this->loadedKeys->add(X509::createFromCertificateData($matches[1]));
138
    }
139
140
141
    /**
142
     * @return \SimpleSAML\SAML2\Certificate\KeyCollection
143
     */
144
    public function getKeys(): KeyCollection
145
    {
146
        return $this->loadedKeys;
147
    }
148
149
150
    /**
151
     */
152
    public function hasKeys(): bool
153
    {
154
        return !!count($this->loadedKeys);
155
    }
156
}
157