Skip to content

Commit ff4439c

Browse files
authored
Merge pull request #8763 from magento-cia/AC-10868-2
AC-10686: [PCI] SRI enabled on payment pages.
2 parents 9fd6d58 + 10d0c30 commit ff4439c

File tree

26 files changed

+1500
-8
lines changed

26 files changed

+1500
-8
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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\Block\Sri;
9+
10+
use Magento\Framework\UrlInterface;
11+
use Magento\Deploy\Package\Package;
12+
use Magento\Framework\App\ObjectManager;
13+
use Magento\Framework\View\Element\Template;
14+
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Serialize\SerializerInterface;
16+
use Magento\Framework\View\Element\Template\Context;
17+
use Magento\Csp\Model\SubresourceIntegrityRepositoryPool;
18+
19+
/**
20+
* Block for Subresource Integrity hashes rendering.
21+
*
22+
* @api
23+
*/
24+
class Hashes extends Template
25+
{
26+
/**
27+
* @var SerializerInterface
28+
*/
29+
private SerializerInterface $serializer;
30+
31+
/**
32+
* @var SubresourceIntegrityRepositoryPool
33+
*/
34+
private SubresourceIntegrityRepositoryPool $integrityRepositoryPool;
35+
36+
/**
37+
* @param Context $context
38+
* @param array $data
39+
* @param SubresourceIntegrityRepositoryPool|null $integrityRepositoryPool
40+
* @param SerializerInterface|null $serializer
41+
*/
42+
public function __construct(
43+
Context $context,
44+
array $data = [],
45+
?SubresourceIntegrityRepositoryPool $integrityRepositoryPool = null,
46+
?SerializerInterface $serializer = null
47+
) {
48+
parent::__construct($context, $data);
49+
50+
$this->integrityRepositoryPool = $integrityRepositoryPool ?: ObjectManager::getInstance()
51+
->get(SubresourceIntegrityRepositoryPool::class);
52+
53+
$this->serializer = $serializer ?: ObjectManager::getInstance()
54+
->get(SerializerInterface::class);
55+
}
56+
57+
/**
58+
* Retrieves integrity hashes in serialized format.
59+
*
60+
* @throws LocalizedException
61+
*
62+
* @return string
63+
*/
64+
public function getSerialized(): string
65+
{
66+
$result = [];
67+
68+
$baseUrl = $this->_urlBuilder->getBaseUrl(
69+
["_type" => UrlInterface::URL_TYPE_STATIC]
70+
);
71+
72+
$integrityRepository = $this->integrityRepositoryPool->get(
73+
Package::BASE_AREA
74+
);
75+
76+
foreach ($integrityRepository->getAll() as $integrity) {
77+
$url = $baseUrl . $integrity->getPath();
78+
79+
$result[$url] = $integrity->getHash();
80+
}
81+
82+
$integrityRepository = $this->integrityRepositoryPool->get(
83+
$this->_appState->getAreaCode()
84+
);
85+
86+
foreach ($integrityRepository->getAll() as $integrity) {
87+
$url = $baseUrl . $integrity->getPath();
88+
89+
$result[$url] = $integrity->getHash();
90+
}
91+
92+
return $this->serializer->serialize($result);
93+
}
94+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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\Model\Deploy\Package\Processor\PostProcessor;
9+
10+
use Magento\Framework\Filesystem;
11+
use Magento\Deploy\Package\Package;
12+
use Magento\Csp\Model\SubresourceIntegrityFactory;
13+
use Magento\Framework\App\Filesystem\DirectoryList;
14+
use Magento\Csp\Model\SubresourceIntegrityCollector;
15+
use Magento\Deploy\Package\Processor\ProcessorInterface;
16+
use Magento\Csp\Model\SubresourceIntegrity\HashGenerator;
17+
18+
/**
19+
* Post-processor that generates integrity hashes after static content package deployed.
20+
*/
21+
class Integrity implements ProcessorInterface
22+
{
23+
/**
24+
* @var Filesystem
25+
*/
26+
private Filesystem $filesystem;
27+
28+
/**
29+
* @var HashGenerator
30+
*/
31+
private HashGenerator $hashGenerator;
32+
33+
/**
34+
* @var SubresourceIntegrityFactory
35+
*/
36+
private SubresourceIntegrityFactory $integrityFactory;
37+
38+
/**
39+
* @var SubresourceIntegrityCollector
40+
*/
41+
private SubresourceIntegrityCollector $integrityCollector;
42+
43+
/**
44+
* @param Filesystem $filesystem
45+
* @param HashGenerator $hashGenerator
46+
* @param SubresourceIntegrityFactory $integrityFactory
47+
* @param SubresourceIntegrityCollector $integrityCollector
48+
*/
49+
public function __construct(
50+
Filesystem $filesystem,
51+
HashGenerator $hashGenerator,
52+
SubresourceIntegrityFactory $integrityFactory,
53+
SubresourceIntegrityCollector $integrityCollector
54+
) {
55+
$this->filesystem = $filesystem;
56+
$this->hashGenerator = $hashGenerator;
57+
$this->integrityFactory = $integrityFactory;
58+
$this->integrityCollector = $integrityCollector;
59+
}
60+
61+
/**
62+
* @inheritdoc
63+
*/
64+
public function process(Package $package, array $options): bool
65+
{
66+
$staticDir = $this->filesystem->getDirectoryRead(
67+
DirectoryList::ROOT
68+
);
69+
70+
foreach ($package->getFiles() as $file) {
71+
if ($file->getExtension() == "js") {
72+
$integrity = $this->integrityFactory->create(
73+
[
74+
"data" => [
75+
'hash' => $this->hashGenerator->generate(
76+
$staticDir->readFile($file->getSourcePath())
77+
),
78+
'path' => $file->getDeployedFilePath()
79+
]
80+
]
81+
);
82+
83+
$this->integrityCollector->collect($integrity);
84+
}
85+
}
86+
87+
return true;
88+
}
89+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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\Model\Deploy\Package\Processor\PostProcessor;
9+
10+
use Magento\Deploy\Package\Package;
11+
use Magento\Deploy\Package\PackageFileFactory;
12+
use Magento\Deploy\Service\DeployStaticFile;
13+
use Magento\Framework\App\DeploymentConfig\Writer\PhpFormatter;
14+
use Magento\Framework\App\Filesystem\DirectoryList;
15+
use Magento\Framework\Exception\FileSystemException;
16+
use Magento\Framework\Filesystem;
17+
use Magento\Framework\View\Asset\Minification;
18+
use Magento\Framework\View\Asset\RepositoryMap;
19+
use Magento\Csp\Model\SubresourceIntegrityFactory;
20+
use Magento\Csp\Model\SubresourceIntegrity\HashGenerator;
21+
use Magento\Framework\Filesystem\DriverInterface;
22+
use Magento\Csp\Model\SubresourceIntegrityCollector;
23+
24+
/**
25+
* Class Adds Integrity attribute to requirejs-map.js asset
26+
*
27+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
28+
*/
29+
class Map extends \Magento\Deploy\Package\Processor\PostProcessor\Map
30+
{
31+
32+
/**
33+
* @var HashGenerator
34+
*/
35+
private HashGenerator $hashGenerator;
36+
37+
/**
38+
* @var SubresourceIntegrityCollector
39+
*/
40+
private SubresourceIntegrityCollector $integrityCollector;
41+
42+
/**
43+
* @var SubresourceIntegrityFactory
44+
*/
45+
private SubresourceIntegrityFactory $integrityFactory;
46+
47+
/**
48+
* @var Minification
49+
*/
50+
private Minification $minification;
51+
52+
/**
53+
* @var DriverInterface
54+
*/
55+
private DriverInterface $driver;
56+
57+
/**
58+
* @var FileSystem
59+
*/
60+
private FileSystem $filesystem;
61+
62+
/**
63+
* Constructor
64+
*
65+
* @param DeployStaticFile $deployStaticFile
66+
* @param PhpFormatter $formatter
67+
* @param PackageFileFactory $packageFileFactory
68+
* @param Minification $minification
69+
* @param SubresourceIntegrityFactory $integrityFactory
70+
* @param HashGenerator $hashGenerator
71+
* @param DriverInterface $driver
72+
* @param SubresourceIntegrityCollector $integrityCollector
73+
* @param FileSystem $filesystem
74+
*/
75+
public function __construct(
76+
DeployStaticFile $deployStaticFile,
77+
PhpFormatter $formatter,
78+
PackageFileFactory $packageFileFactory,
79+
Minification $minification,
80+
SubresourceIntegrityFactory $integrityFactory,
81+
HashGenerator $hashGenerator,
82+
DriverInterface $driver,
83+
SubresourceIntegrityCollector $integrityCollector,
84+
Filesystem $filesystem
85+
) {
86+
$this->minification = $minification;
87+
$this->integrityFactory = $integrityFactory;
88+
$this->hashGenerator = $hashGenerator;
89+
$this->driver = $driver;
90+
$this->integrityCollector = $integrityCollector;
91+
$this->filesystem = $filesystem;
92+
parent::__construct($deployStaticFile, $formatter, $packageFileFactory, $minification);
93+
}
94+
95+
/**
96+
* @inheritdoc
97+
*
98+
* @throws FileSystemException
99+
*/
100+
public function process(Package $package, array $options): bool
101+
{
102+
parent::process($package, $options);
103+
$fileName = $this->minification->addMinifiedSign(RepositoryMap::REQUIRE_JS_MAP_NAME);
104+
$path = $package->getPath();
105+
$relativePath = $path . DIRECTORY_SEPARATOR . $fileName;
106+
107+
if ($this->fileExists($relativePath)) {
108+
$dir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
109+
$absolutePath = $dir->getAbsolutePath($relativePath);
110+
$fileContent = $this->driver->fileGetContents($absolutePath);
111+
112+
if ($fileContent) {
113+
$integrity = $this->integrityFactory->create(
114+
[
115+
"data" => [
116+
'hash' => $this->hashGenerator->generate($fileContent),
117+
'path' => $relativePath
118+
]
119+
]
120+
);
121+
$this->integrityCollector->collect($integrity);
122+
}
123+
}
124+
return true;
125+
}
126+
127+
/**
128+
* Check if file exist
129+
*
130+
* @param string $path
131+
* @return bool
132+
* @throws FileSystemException
133+
*/
134+
private function fileExists(string $path): bool
135+
{
136+
$dir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
137+
return $dir->isExist($path);
138+
}
139+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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\Model;
9+
10+
/**
11+
* Subresource Integrity data model.
12+
*/
13+
class SubresourceIntegrity extends \Magento\Framework\DataObject
14+
{
15+
/**
16+
* Gets an integrity Path.
17+
*
18+
* @return string|null
19+
*/
20+
public function getPath(): ?string
21+
{
22+
return $this->getData("path");
23+
}
24+
25+
/**
26+
* Gets an integrity hash.
27+
*
28+
* @return string|null
29+
*/
30+
public function getHash(): ?string
31+
{
32+
return $this->getData("hash");
33+
}
34+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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\Model\SubresourceIntegrity;
9+
10+
/**
11+
* Subresource Integrity hashes generator.
12+
*/
13+
class HashGenerator
14+
{
15+
/**
16+
* CHashing algorithm.
17+
*
18+
* @var string
19+
*/
20+
private const ALGORITHM = 'sha256';
21+
22+
/**
23+
* Computes integrity hash for a given content.
24+
*
25+
* @param string $content
26+
*
27+
* @return string
28+
*/
29+
public function generate(string $content): string
30+
{
31+
$base64Hash = base64_encode(
32+
hash(self::ALGORITHM, $content, true)
33+
);
34+
35+
return self::ALGORITHM . "-{$base64Hash}";
36+
}
37+
}

0 commit comments

Comments
 (0)