1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace SimpleSAML\Module\metarefresh; |
||
6 | |||
7 | use Exception; |
||
8 | use SimpleSAML\Configuration; |
||
9 | use SimpleSAML\Logger; |
||
10 | use SimpleSAML\Metadata\MetaDataStorageSource; |
||
11 | |||
12 | class MetaRefresh |
||
13 | { |
||
14 | /** |
||
15 | * @var \SimpleSAML\Configuration |
||
16 | */ |
||
17 | private Configuration $config; |
||
18 | |||
19 | /** |
||
20 | * @var \SimpleSAML\Configuration |
||
21 | */ |
||
22 | private Configuration $modconfig; |
||
23 | |||
24 | /** |
||
25 | * @param \SimpleSAML\Configuration $config The configuration to use by the module. |
||
26 | * @param \SimpleSAML\Configuration $modconfig The module-specific configuration to use by the module. |
||
27 | */ |
||
28 | public function __construct(Configuration $config, Configuration $modconfig) |
||
29 | { |
||
30 | $this->config = $config; |
||
31 | $this->modconfig = $modconfig; |
||
32 | } |
||
33 | |||
34 | /** |
||
35 | * @param string|null $crontag Only refresh sets which allow this crontag |
||
36 | */ |
||
37 | public function runRefresh(?string $crontag = null): void |
||
38 | { |
||
39 | $sets = $this->modconfig->getArray('sets'); |
||
40 | /** @var string $datadir */ |
||
41 | $datadir = $this->config->getPathValue('datadir', 'data/'); |
||
42 | $stateFile = $datadir . 'metarefresh-state.php'; |
||
43 | |||
44 | foreach ($sets as $setkey => $set) { |
||
45 | $set = Configuration::loadFromArray($set); |
||
46 | |||
47 | // Only process sets where cron matches the current cron tag |
||
48 | $cronTags = $set->getArray('cron'); |
||
49 | if ($crontag !== null && !in_array($crontag, $cronTags, true)) { |
||
50 | Logger::debug('[metarefresh]: Skipping set [' . $setkey . '], not allowed for cron tag ' . $crontag); |
||
51 | continue; |
||
52 | } |
||
53 | |||
54 | Logger::info('[metarefresh]: Executing set [' . $setkey . ']'); |
||
55 | |||
56 | $expireAfter = $set->getOptionalInteger('expireAfter', null); |
||
57 | if ($expireAfter !== null) { |
||
58 | $expire = time() + $expireAfter; |
||
59 | } else { |
||
60 | $expire = null; |
||
61 | } |
||
62 | |||
63 | $outputDir = $set->getString('outputDir'); |
||
64 | $outputDir = $this->config->resolvePath($outputDir); |
||
65 | if ($outputDir === null) { |
||
66 | throw new Exception("Invalid outputDir specified."); |
||
67 | } |
||
68 | |||
69 | $outputFormat = $set->getOptionalValueValidate('outputFormat', ['flatfile', 'serialize', 'pdo'], 'flatfile'); |
||
70 | |||
71 | $oldMetadataSrc = MetaDataStorageSource::getSource([ |
||
72 | 'type' => $outputFormat, |
||
73 | 'directory' => $outputDir, |
||
74 | ]); |
||
75 | |||
76 | $metaloader = new MetaLoader($expire, $stateFile, $oldMetadataSrc); |
||
77 | |||
78 | // Get global blacklist, whitelist, attributewhitelist and caching info |
||
79 | $blacklist = $this->modconfig->getOptionalArray('blacklist', []); |
||
80 | $whitelist = $this->modconfig->getOptionalArray('whitelist', []); |
||
81 | $attributewhitelist = $this->modconfig->getOptionalArray('attributewhitelist', []); |
||
82 | $conditionalGET = $this->modconfig->getOptionalBoolean('conditionalGET', false); |
||
83 | |||
84 | // get global type filters |
||
85 | $available_types = [ |
||
86 | 'saml20-idp-remote', |
||
87 | 'saml20-sp-remote', |
||
88 | 'attributeauthority-remote', |
||
89 | ]; |
||
90 | $set_types = $set->getOptionalArray('types', $available_types); |
||
91 | |||
92 | foreach ($set->getArray('sources') as $source) { |
||
93 | // filter metadata by type of entity |
||
94 | if (isset($source['types'])) { |
||
95 | $metaloader->setTypes($source['types']); |
||
96 | } else { |
||
97 | $metaloader->setTypes($set_types); |
||
98 | } |
||
99 | |||
100 | // Merge global and src specific blacklists |
||
101 | if (isset($source['blacklist'])) { |
||
102 | $source['blacklist'] = array_unique(array_merge($source['blacklist'], $blacklist)); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
103 | } else { |
||
104 | $source['blacklist'] = $blacklist; |
||
105 | } |
||
106 | |||
107 | // Merge global and src specific whitelists |
||
108 | if (isset($source['whitelist'])) { |
||
109 | $source['whitelist'] = array_unique(array_merge($source['whitelist'], $whitelist)); |
||
110 | } else { |
||
111 | $source['whitelist'] = $whitelist; |
||
112 | } |
||
113 | |||
114 | # Merge global and src specific attributewhitelists: cannot use array_unique for multi-dim. |
||
115 | if (isset($source['attributewhitelist'])) { |
||
116 | $source['attributewhitelist'] = array_merge($source['attributewhitelist'], $attributewhitelist); |
||
117 | } else { |
||
118 | $source['attributewhitelist'] = $attributewhitelist; |
||
119 | } |
||
120 | |||
121 | // Let src specific conditionalGET override global one |
||
122 | if (!isset($source['conditionalGET'])) { |
||
123 | $source['conditionalGET'] = $conditionalGET; |
||
124 | } |
||
125 | |||
126 | Logger::debug('[metarefresh]: In set [' . $setkey . '] loading source [' . $source['src'] . ']'); |
||
127 | $metaloader->loadSource($source); |
||
128 | } |
||
129 | |||
130 | // Write state information back to disk |
||
131 | $metaloader->writeState(); |
||
132 | |||
133 | switch ($outputFormat) { |
||
134 | case 'flatfile': |
||
135 | $metaloader->writeMetadataFiles($outputDir); |
||
136 | break; |
||
137 | case 'serialize': |
||
138 | $metaloader->writeMetadataSerialize($outputDir); |
||
139 | break; |
||
140 | case 'pdo': |
||
141 | $metaloader->writeMetadataPdo($this->config); |
||
142 | break; |
||
143 | } |
||
144 | |||
145 | if ($set->hasValue('arp')) { |
||
146 | $arpconfig = Configuration::loadFromArray($set->getValue('arp')); |
||
147 | $metaloader->writeARPfile($arpconfig); |
||
148 | } |
||
149 | } |
||
150 | } |
||
151 | } |
||
152 |