Skip to content

Commit 62b413a

Browse files
AC-10686: [PCI] SRI enabled on payment pages
1 parent fc503d1 commit 62b413a

File tree

7 files changed

+128
-27
lines changed

7 files changed

+128
-27
lines changed

app/code/Magento/Csp/Block/Sri/Hashes.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Csp\Block\Sri;
77

8+
use Magento\Framework\UrlInterface;
89
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\View\Element\Template;
1011
use Magento\Framework\Exception\LocalizedException;
@@ -65,8 +66,14 @@ public function getSerialized(): string
6566
$this->_appState->getAreaCode()
6667
);
6768

69+
$baseUrl = $this->_urlBuilder->getBaseUrl(
70+
["_type" => UrlInterface::URL_TYPE_STATIC]
71+
);
72+
6873
foreach ($integrityRepository->getAll() as $integrity) {
69-
$result[$integrity->getUrl()] = $integrity->getHash();
74+
$url = $baseUrl . $integrity->getPath();
75+
76+
$result[$url] = $integrity->getHash();
7077
}
7178

7279
return $this->serializer->serialize($result);

app/code/Magento/Csp/Model/SubresourceIntegrity.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
class SubresourceIntegrity extends \Magento\Framework\DataObject
1414
{
1515
/**
16-
* Gets an integrity URL.
16+
* Gets an integrity Path.
1717
*
1818
* @return string|null
1919
*/
20-
public function getUrl(): ?string
20+
public function getPath(): ?string
2121
{
22-
return $this->getData("url");
22+
return $this->getData("path");
2323
}
2424

2525
/**

app/code/Magento/Csp/Model/SubresourceIntegrityRepository.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,24 @@ public function __construct(
6666
}
6767

6868
/**
69-
* Gets an Integrity object by URL.
69+
* Gets an Integrity object by path.
7070
*
71-
* @param string $url
71+
* @param string $path
7272
*
7373
* @return SubresourceIntegrity|null
7474
*/
75-
public function getByUrl(string $url): ?SubresourceIntegrity
75+
public function getByPath(string $path): ?SubresourceIntegrity
7676
{
7777
$data = $this->getData();
7878

79-
if (isset($data[$url])) {
79+
if (isset($data[$path])) {
8080
return $this->integrityFactory->create(
81-
["data" => $data[$url]]
81+
[
82+
"data" => [
83+
"path" => $path,
84+
"hash" => $data[$path]
85+
]
86+
]
8287
);
8388
}
8489

@@ -94,10 +99,13 @@ public function getAll(): array
9499
{
95100
$result = [];
96101

97-
foreach ($this->getData() as $integrity) {
102+
foreach ($this->getData() as $path => $hash) {
98103
$result[] = $this->integrityFactory->create(
99104
[
100-
"data" => $integrity
105+
"data" => [
106+
"path" => $path,
107+
"hash" => $hash
108+
]
101109
]
102110
);
103111
}
@@ -116,10 +124,7 @@ public function save(SubresourceIntegrity $integrity): bool
116124
{
117125
$data = $this->getData();
118126

119-
$data[$integrity->getUrl()] = [
120-
"url" => $integrity->getUrl(),
121-
"hash" => $integrity->getHash()
122-
];
127+
$data[$integrity->getPath()] = $integrity->getHash();
123128

124129
$this->data = $data;
125130

@@ -130,6 +135,20 @@ public function save(SubresourceIntegrity $integrity): bool
130135
);
131136
}
132137

138+
/**
139+
* Deletes all Integrity objects.
140+
*
141+
* @return bool
142+
*/
143+
public function deleteAll(): bool
144+
{
145+
$this->data = null;
146+
147+
return $this->cache->remove(
148+
$this->getCacheKey()
149+
);
150+
}
151+
133152
/**
134153
* Loads integrity data from a storage.
135154
*

app/code/Magento/Csp/Plugin/AddDefaultPropertiesToGroupPlugin.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Magento\Framework\App\State;
1111
use Magento\Framework\View\Asset\AssetInterface;
12+
use Magento\Framework\View\Asset\LocalInterface;
1213
use Magento\Framework\View\Asset\GroupedCollection;
1314
use Magento\Csp\Model\SubresourceIntegrityRepositoryPool;
1415

@@ -53,15 +54,17 @@ public function beforeGetFilteredProperties(
5354
AssetInterface $asset,
5455
array $properties = []
5556
): array {
56-
$integrityRepository = $this->integrityRepositoryPool->get(
57-
$this->state->getAreaCode()
58-
);
57+
if ($asset instanceof LocalInterface) {
58+
$integrityRepository = $this->integrityRepositoryPool->get(
59+
$this->state->getAreaCode()
60+
);
5961

60-
$integrity = $integrityRepository->getByUrl($asset->getUrl());
62+
$integrity = $integrityRepository->getByPath($asset->getPath());
6163

62-
if ($integrity && $integrity->getHash()) {
63-
$properties['attributes']['integrity'] = $integrity->getHash();
64-
$properties['attributes']['crossorigin'] = 'anonymous';
64+
if ($integrity && $integrity->getHash()) {
65+
$properties['attributes']['integrity'] = $integrity->getHash();
66+
$properties['attributes']['crossorigin'] = 'anonymous';
67+
}
6568
}
6669

6770
return [$asset, $properties];

app/code/Magento/Csp/Plugin/GenerateAssetIntegrity.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,12 @@ private function generateIntegrity(LocalInterface $asset): void
121121
'hash' => $this->hashGenerator->generate(
122122
$asset->getContent()
123123
),
124-
'url' => $asset->getUrl()
124+
'path' => $asset->getPath()
125125
]
126126
]
127127
);
128128

129-
$area = explode(
130-
"/",
131-
parse_url($asset->getUrl(), PHP_URL_PATH)
132-
)[3];
129+
$area = explode("/", $asset->getPath())[0];
133130

134131
$this->integrityRepositoryPool->get($area)
135132
->save($integrity);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Csp\Plugin;
9+
10+
use Magento\Framework\App\Area;
11+
use Magento\Deploy\Console\DeployStaticOptions;
12+
use Magento\Deploy\Service\DeployStaticContent;
13+
use Magento\Csp\Model\SubresourceIntegrityRepositoryPool;
14+
15+
/**
16+
* Plugin that removes existing integrity hashes for all assets.
17+
*/
18+
class RemoveAllAssetIntegrityHashes
19+
{
20+
/**
21+
* @var SubresourceIntegrityRepositoryPool
22+
*/
23+
private SubresourceIntegrityRepositoryPool $integrityRepositoryPool;
24+
25+
/**
26+
* @param SubresourceIntegrityRepositoryPool $integrityRepositoryPool
27+
*/
28+
public function __construct(
29+
SubresourceIntegrityRepositoryPool $integrityRepositoryPool
30+
) {
31+
$this->integrityRepositoryPool = $integrityRepositoryPool;
32+
}
33+
34+
/**
35+
* Removes existing integrity hashes for all assets
36+
* before static content deploy.
37+
*
38+
* @param DeployStaticContent $subject
39+
* @param array $options
40+
*
41+
* @return void
42+
*
43+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
44+
*/
45+
public function beforeDeploy(
46+
DeployStaticContent $subject,
47+
array $options
48+
): void {
49+
if (PHP_SAPI == 'cli' && !$this->isRefreshContentVersionOnly($options)) {
50+
foreach ([Area::AREA_FRONTEND, Area::AREA_ADMINHTML] as $area) {
51+
$this->integrityRepositoryPool->get($area)
52+
->deleteAll();
53+
}
54+
}
55+
}
56+
57+
/**
58+
* Checks if only version refresh is requested.
59+
*
60+
* @param array $options
61+
*
62+
* @return bool
63+
*/
64+
private function isRefreshContentVersionOnly(array $options): bool
65+
{
66+
return isset($options[DeployStaticOptions::REFRESH_CONTENT_VERSION_ONLY])
67+
&& $options[DeployStaticOptions::REFRESH_CONTENT_VERSION_ONLY];
68+
}
69+
}

app/code/Magento/Csp/etc/di.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@
114114
<type name="Magento\Framework\View\Asset\GroupedCollection">
115115
<plugin name="addDefaultPropertiesToGroup" type="Magento\Csp\Plugin\AddDefaultPropertiesToGroupPlugin" />
116116
</type>
117+
<type name="Magento\Deploy\Service\DeployStaticContent">
118+
<plugin name="removeAllAssetIntegrityHashes" type="Magento\Csp\Plugin\RemoveAllAssetIntegrityHashes" />
119+
</type>
120+
<type name="Magento\Framework\App\View\Asset\Publisher">
121+
<plugin name="addResourceIntegrityAfterAssetPublish" type="Magento\Csp\Plugin\GenerateAssetIntegrity"/>
122+
</type>
117123
<type name="Magento\RequireJs\Model\FileManager">
118124
<plugin name="addResourceIntegrityAfterAssetCreate" type="Magento\Csp\Plugin\GenerateAssetIntegrity"/>
119125
</type>

0 commit comments

Comments
 (0)