Skip to content

Commit efe9ca5

Browse files
authored
feat: add info about Security updates for installed version (#247)
1 parent 4a0136f commit efe9ca5

1 file changed

Lines changed: 165 additions & 29 deletions

File tree

src/Components/Health/Checker/HealthChecker/SwagSecurityChecker.php

Lines changed: 165 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,35 +30,8 @@ public function collect(HealthCollection $collection): void
3030
{
3131
$this->refreshPlugins($this->connection);
3232

33-
try {
34-
if (!$this->hasSecurityAdvisories()) {
35-
return;
36-
}
37-
} catch (\Throwable) {
38-
$collection->add(
39-
SettingsResult::error(
40-
'security-update',
41-
'Cannot check security.json from shopware-static-data',
42-
'not accessible',
43-
'accessible',
44-
'https://raw.githubusercontent.com/FriendsOfShopware/shopware-static-data/main/data/security.json'
45-
)
46-
);
47-
}
48-
49-
if ($this->swagSecurityInstalled()) {
50-
return;
51-
}
52-
53-
$collection->add(
54-
SettingsResult::error(
55-
'security-update',
56-
'Security update',
57-
'Shopware outdated',
58-
'Update Shopware to the latest version or install recent version of the plugin SwagPlatformSecurity',
59-
'https://store.shopware.com/en/swag136939272659f/shopware-6-security-plugin.html'
60-
)
61-
);
33+
$this->determineSecurityIssue($collection);
34+
$this->determineEolSupport($collection);
6235
}
6336

6437
private function refreshPlugins(Connection $connection): void
@@ -110,4 +83,167 @@ private function swagSecurityInstalled(): bool
11083

11184
return !empty($result);
11285
}
86+
87+
private function determineSecurityIssue(HealthCollection $collection): void
88+
{
89+
try {
90+
if (!$this->hasSecurityAdvisories()) {
91+
return;
92+
}
93+
} catch (\Throwable) {
94+
$collection->add(
95+
SettingsResult::error(
96+
'security-update',
97+
'Cannot check security.json from shopware-static-data',
98+
'not accessible',
99+
'accessible',
100+
'https://raw.githubusercontent.com/FriendsOfShopware/shopware-static-data/main/data/security.json'
101+
)
102+
);
103+
}
104+
105+
if ($this->swagSecurityInstalled()) {
106+
return;
107+
}
108+
109+
$collection->add(
110+
SettingsResult::error(
111+
'security-update',
112+
'Security update',
113+
'Shopware outdated',
114+
'Update Shopware to the latest version or install recent version of the plugin SwagPlatformSecurity',
115+
'https://store.shopware.com/en/swag136939272659f/shopware-6-security-plugin.html'
116+
)
117+
);
118+
}
119+
120+
private function determineEolSupport(HealthCollection $collection): void
121+
{
122+
123+
$id = 'security-eol-shopware';
124+
$snippet = 'Security updates';
125+
126+
try {
127+
$releaseSupport = $this->getReleasesSupport();
128+
} catch (\Throwable) {
129+
$collection->add(
130+
SettingsResult::error(
131+
$id,
132+
$snippet,
133+
'releases.json not accessible',
134+
'accessible',
135+
'https://raw.githubusercontent.com/shopware/shopware/trunk/releases.json'
136+
)
137+
);
138+
139+
return;
140+
}
141+
142+
$recommended = 'Please update to a more recent version and minimum LTS version ' . ($releaseSupport['extended_eol_version'] ?? 'unknown') . '.';
143+
144+
if (empty($releaseSupport['security_eol'])) {
145+
$collection->add(
146+
SettingsResult::error(
147+
$id,
148+
$snippet,
149+
'unknown, possibly ended security support',
150+
$recommended
151+
)
152+
);
153+
154+
return;
155+
}
156+
157+
$securityEol = new \DateTime($releaseSupport['security_eol']);
158+
159+
if ($securityEol < (new \DateTime())) {
160+
$collection->add(
161+
SettingsResult::error(
162+
$id,
163+
$snippet,
164+
'ended security support on ' . $releaseSupport['security_eol'],
165+
$recommended
166+
)
167+
);
168+
169+
return;
170+
}
171+
172+
if ($securityEol < (new \DateTime())->modify('+6 month')) {
173+
$collection->add(
174+
SettingsResult::warning(
175+
$id,
176+
$snippet,
177+
'less than six months (' . $releaseSupport['security_eol'] . ')',
178+
$recommended
179+
)
180+
);
181+
182+
return;
183+
}
184+
185+
if ($securityEol < (new \DateTime())->modify('+1 year')) {
186+
$collection->add(
187+
SettingsResult::info(
188+
$id,
189+
$snippet,
190+
'less than one year (' . $releaseSupport['security_eol'] . ')',
191+
$recommended
192+
)
193+
);
194+
195+
return;
196+
}
197+
198+
$collection->add(
199+
SettingsResult::ok(
200+
$id,
201+
$snippet,
202+
'until ' . $releaseSupport['security_eol']
203+
)
204+
);
205+
}
206+
207+
/**
208+
* @return array{version?: string, release_date?: string, extended_eol?: string|false, security_eol?: string, extended_eol_version?: string}
209+
*/
210+
private function getReleasesSupport(): array
211+
{
212+
$cacheKey = \sprintf('shopware-releases-support-%s', $this->shopwareVersion);
213+
214+
return $this->cacheObject->get($cacheKey, function (ItemInterface $cacheItem) {
215+
$releasesJson = file_get_contents('https://raw.githubusercontent.com/shopware/shopware/trunk/releases.json');
216+
if ($releasesJson === false) {
217+
throw new \RuntimeException('Could not fetch releases.json');
218+
}
219+
220+
$data = \json_decode(trim($releasesJson), true, 512, JSON_THROW_ON_ERROR);
221+
222+
if (!\is_array($data)) {
223+
throw new \RuntimeException('Could not read releases.json');
224+
}
225+
226+
$cacheItem->expiresAfter(3600 * 24 * 14);
227+
228+
$result = [];
229+
230+
foreach ($data as $entry) {
231+
if (empty($entry['version'])) {
232+
continue;
233+
}
234+
235+
if (!empty($entry['extended_eol'])
236+
&& version_compare($entry['version'], ($result['extended_eol_version'] ?? ''), '>')) {
237+
$result['extended_eol_version'] = $entry['version'];
238+
}
239+
240+
if (version_compare($entry['version'], ($result['version'] ?? ''), '>')
241+
&& version_compare($entry['version'], $this->shopwareVersion, '<=')) {
242+
$result = [...$result, ...$entry];
243+
}
244+
}
245+
246+
return $result;
247+
});
248+
}
113249
}

0 commit comments

Comments
 (0)