1+ diff --git a/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php
2+ new file mode 100644
3+ index 0000000000000..8777f99139edc
4+ --- /dev/null
5+ +++ b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php
6+ @@ -0,0 +1,141 @@
7+ + <?php
8+ + /**
9+ + * Copyright © Magento, Inc. All rights reserved.
10+ + * See COPYING.txt for license details.
11+ + */
12+ +
13+ + declare(strict_types=1);
14+ +
15+ + namespace Magento\EncryptionKey\Console\Command;
16+ +
17+ + use Magento\Framework\App\DeploymentConfig\Writer;
18+ + use Magento\Framework\Config\ConfigOptionsListConstants;
19+ + use Magento\Framework\Config\Data\ConfigData;
20+ + use Magento\Framework\Config\File\ConfigFilePool;
21+ + use Magento\Framework\Console\Cli;
22+ + use Magento\Framework\Exception\FileSystemException;
23+ + use Magento\Framework\Math\Random;
24+ + use Symfony\Component\Console\Command\Command;
25+ + use Symfony\Component\Console\Input\InputInterface;
26+ + use Symfony\Component\Console\Input\InputOption;
27+ + use Symfony\Component\Console\Output\OutputInterface;
28+ + use Magento\Framework\App\CacheInterface;
29+ + use Magento\Framework\Encryption\EncryptorInterface;
30+ +
31+ + /**
32+ + * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
33+ + */
34+ + class UpdateEncryptionKeyCommand extends Command
35+ + {
36+ + /**
37+ + * @var EncryptorInterface
38+ + */
39+ + private EncryptorInterface $encryptor;
40+ +
41+ + /**
42+ + * @var CacheInterface
43+ + */
44+ + private CacheInterface $cache;
45+ +
46+ + /**
47+ + * Configuration writer
48+ + *
49+ + * @var Writer
50+ + */
51+ + private Writer $writer;
52+ +
53+ + /**
54+ + * Random string generator
55+ + *
56+ + * @var Random
57+ + */
58+ + private Random $random;
59+ +
60+ + /**
61+ + * @param EncryptorInterface $encryptor
62+ + * @param CacheInterface $cache
63+ + * @param Writer $writer
64+ + * @param Random $random
65+ + */
66+ + public function __construct(EncryptorInterface $encryptor, CacheInterface $cache, Writer $writer, Random $random)
67+ + {
68+ + $this->encryptor = $encryptor;
69+ + $this->cache = $cache;
70+ + $this->writer = $writer;
71+ + $this->random = $random;
72+ +
73+ + parent::__construct();
74+ + }
75+ +
76+ + /**
77+ + * @inheritDoc
78+ + */
79+ + protected function configure()
80+ + {
81+ + $this->setName('encryption:key:change');
82+ + $this->setDescription('Change the encryption key inside the env.php file.');
83+ + $this->addOption(
84+ + 'key',
85+ + 'k',
86+ + InputOption::VALUE_OPTIONAL,
87+ + 'Key has to be a 32 characters long string. If not provided, a random key will be generated.'
88+ + );
89+ +
90+ + parent::configure();
91+ + }
92+ +
93+ + /**
94+ + * @inheritDoc
95+ + */
96+ + protected function execute(InputInterface $input, OutputInterface $output)
97+ + {
98+ + try {
99+ + $key = $input->getOption('key');
100+ +
101+ + if (!empty($key)) {
102+ + $this->encryptor->validateKey($key);
103+ + }
104+ +
105+ + $this->updateEncryptionKey($key);
106+ + $this->cache->clean();
107+ +
108+ + $output->writeln('<info>Encryption key has been updated successfully.</info>');
109+ +
110+ + return Cli::RETURN_SUCCESS;
111+ + } catch (\Exception $e) {
112+ + $output->writeln('<error>' . $e->getMessage() . '</error>');
113+ + return Cli::RETURN_FAILURE;
114+ + }
115+ + }
116+ +
117+ + /**
118+ + * Update encryption key
119+ + *
120+ + * @param string|null $key
121+ + * @return void
122+ + * @throws FileSystemException
123+ + */
124+ + private function updateEncryptionKey(string $key = null): void
125+ + {
126+ + // prepare new key, encryptor and new configuration segment
127+ + if (!$this->writer->checkIfWritable()) {
128+ + throw new FileSystemException(__('Deployment configuration file is not writable.'));
129+ + }
130+ +
131+ + if (null === $key) {
132+ + // md5() here is not for cryptographic use. It used for generate encryption key itself
133+ + // and do not encrypt any passwords
134+ + // phpcs:ignore Magento2.Security.InsecureFunction
135+ + $key = md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE));
136+ + }
137+ +
138+ + $this->encryptor->setNewKey($key);
139+ +
140+ + $encryptSegment = new ConfigData(ConfigFilePool::APP_ENV);
141+ + $encryptSegment->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $this->encryptor->exportKeys());
142+ +
143+ + $configData = [$encryptSegment->getFileKey() => $encryptSegment->getData()];
144+ +
145+ + $this->writer->saveConfig($configData);
146+ + }
147+ + }
148+ diff --git a/vendor/magento/module-encryption-key/etc/di.xml b/vendor/magento/module-encryption-key/etc/di.xml
149+ index b4e471f4e40ef..495234759a7f8 100644
150+ --- a/vendor/magento/module-encryption-key/etc/di.xml
151+ +++ b/vendor/magento/module-encryption-key/etc/di.xml
152+ @@ -11,4 +11,11 @@
153+ <argument name="structure" xsi:type="object">Magento\Config\Model\Config\Structure\Proxy</argument>
154+ </arguments>
155+ </type>
156+ + <type name="Magento\Framework\Console\CommandList">
157+ + <arguments>
158+ + <argument name="commands" xsi:type="array">
159+ + <item name="encryption_update_key_command" xsi:type="object">Magento\EncryptionKey\Console\Command\UpdateEncryptionKeyCommand</item>
160+ + </argument>
161+ + </arguments>
162+ + </type>
163+ </config>
0 commit comments