Skip to content

Commit 93206e0

Browse files
committed
Add CLI Command for Updating CC Number Encryption
Updates the encryption of any values in `sales_order_payment.cc_number_enc` with a cipher version below the latest. The command executes in batches of 1000
1 parent 2a42199 commit 93206e0

File tree

4 files changed

+147
-4
lines changed

4 files changed

+147
-4
lines changed

app/code/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatch.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,15 @@ private function reEncryptSystemConfigurationValues()
8383

8484
$this->scope->setCurrentScope(\Magento\Framework\App\Area::AREA_ADMINHTML);
8585

86-
$paths = $this->structure->getFieldPathsByAttribute(
87-
'backend_model',
88-
\Magento\Config\Model\Config\Backend\Encrypted::class
89-
);
86+
try {
87+
$paths = $this->structure->getFieldPathsByAttribute(
88+
'backend_model',
89+
\Magento\Config\Model\Config\Backend\Encrypted::class
90+
);
91+
} catch (\Exception $e) {
92+
// This is thrown during initial application installation
93+
return;
94+
}
9095

9196
$this->scope->setCurrentScope($currentScope);
9297

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Sales\Console\Command;
10+
11+
use Symfony\Component\Console\Input\InputInterface;
12+
use Symfony\Component\Console\Output\OutputInterface;
13+
use Symfony\Component\Console\Command\Command;
14+
use Magento\Framework\Console\Cli;
15+
16+
/**
17+
* Command for updating encrypted credit card data to the latest cipher
18+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
19+
*/
20+
class EncryptionPaymentDataUpdateCommand extends Command
21+
{
22+
/** Command name */
23+
const NAME = 'encryption:payment-data:update';
24+
25+
/**
26+
* @var \Magento\Sales\Model\ResourceModel\Order\Payment\EncryptionUpdate
27+
*/
28+
private $paymentResource;
29+
30+
/**
31+
* @param \Magento\Sales\Model\ResourceModel\Order\Payment\EncryptionUpdate $paymentResource
32+
*/
33+
public function __construct(
34+
\Magento\Sales\Model\ResourceModel\Order\Payment\EncryptionUpdate $paymentResource
35+
) {
36+
$this->paymentResource = $paymentResource;
37+
parent::__construct();
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
protected function configure()
44+
{
45+
$this->setName(self::NAME)
46+
->setDescription(
47+
'Re-encrypts encrypted credit card data with latest encryption cipher.'
48+
);
49+
parent::configure();
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
protected function execute(InputInterface $input, OutputInterface $output)
56+
{
57+
try {
58+
$this->paymentResource->reEncryptCreditCardNumbers();
59+
} catch (\Exception $e) {
60+
$output->writeln('<error>' . $e->getMessage() . '</error>');
61+
return Cli::RETURN_FAILURE;
62+
}
63+
64+
return Cli::RETURN_SUCCESS;
65+
}
66+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Sales\Model\ResourceModel\Order\Payment;
10+
11+
/**
12+
* Resource for updating encrypted credit card data to the latest cipher
13+
*/
14+
class EncryptionUpdate
15+
{
16+
const LEGACY_PATTERN = '^[[:digit:]]+:[^%s]:.*$';
17+
18+
/**
19+
* @var \Magento\Sales\Model\ResourceModel\Order\Payment
20+
*/
21+
private $paymentResource;
22+
23+
/**
24+
* @var \Magento\Framework\Encryption\Encryptor
25+
*/
26+
private $encryptor;
27+
28+
/**
29+
* @param \Magento\Sales\Model\ResourceModel\Order\Payment $paymentResource
30+
* @param \Magento\Framework\Encryption\Encryptor $encryptor
31+
*/
32+
public function __construct(
33+
\Magento\Sales\Model\ResourceModel\Order\Payment $paymentResource,
34+
\Magento\Framework\Encryption\Encryptor $encryptor
35+
) {
36+
$this->paymentResource = $paymentResource;
37+
$this->encryptor = $encryptor;
38+
}
39+
40+
/**
41+
* Fetch encrypted credit card numbers using legacy ciphers and re-encrypt with latest cipher
42+
* @throws \Magento\Framework\Exception\LocalizedException
43+
*/
44+
public function reEncryptCreditCardNumbers()
45+
{
46+
$connection = $this->paymentResource->getConnection();
47+
$table = $this->paymentResource->getMainTable();
48+
$select = $connection->select()->from($table, ['entity_id', 'cc_number_enc'])
49+
->where(
50+
'cc_number_enc REGEXP ?',
51+
sprintf(self::LEGACY_PATTERN, \Magento\Framework\Encryption\Encryptor::CIPHER_LATEST)
52+
)->limit(1000);
53+
54+
while ($attributeValues = $connection->fetchPairs($select)) {
55+
// save new values
56+
foreach ($attributeValues as $valueId => $value) {
57+
$connection->update(
58+
$table,
59+
['cc_number_enc' => $this->encryptor->encrypt($this->encryptor->decrypt($value))],
60+
['entity_id = ?' => (int)$valueId, 'cc_number_enc = ?' => (string)$value]
61+
);
62+
}
63+
}
64+
}
65+
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,13 @@
974974
<type name="Magento\Sales\Model\ResourceModel\Order\Handler\Address">
975975
<plugin name="addressUpdate" type="Magento\Sales\Model\Order\Invoice\Plugin\AddressUpdate"/>
976976
</type>
977+
<type name="Magento\Framework\Console\CommandListInterface">
978+
<arguments>
979+
<argument name="commands" xsi:type="array">
980+
<item name="encyption_payment_data_update" xsi:type="object">Magento\Sales\Console\Command\EncryptionPaymentDataUpdateCommand</item>
981+
</argument>
982+
</arguments>
983+
</type>
977984
<type name="Magento\Config\Model\Config\TypePool">
978985
<arguments>
979986
<argument name="sensitive" xsi:type="array">

0 commit comments

Comments
 (0)