-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upgrade path after security overhaul #4461
Comments
Checkout |
I'll mention it in upgrade guide. |
I wrote a migration to convert my encrypted columns. I'm sharing it here for those who face the same problem. It requires that you include the old Security helper class, as @samdark suggested. You only need to enter your encryption keys and fill in an array with the names of the tables and their encrypted columns; the code assumes there's also a primary key column in every table called If the process is interrupted, it is safe to run the migration again. Values will only be re-encrypted if both the decryption and encryption lead to a string of more than 0 characters. In my database, empty strings are not encrypted but stored as NULL values in the db; this might be different in your case so change the code accordingly. <?php
use yii\db\Migration;
use yii\db\Query;
use yii\helpers\Security; // temporarily added to the yii\helpers folder
use yii\helpers\Console;
class m140726_144401_securityOverhaul extends Migration
{
public function up()
{
$connection = \Yii::$app->db;
/**
* fill this array with the names of tables and columns
* which include encrypted data.
* The code assumes there's also a column called id
*/
$tables = [
'Table_1' => [
'encrypted_column_1',
'encrypted_column_2',
'encrypted_column_3',
],
'Table_2' => [
'encrypted_column_1',
'encrypted_column_2',
'encrypted_column_3',
],
'Table_3' => [
'encrypted_column_1',
'encrypted_column_2',
'encrypted_column_3',
],
];
foreach ($tables as $tablename => $columns) {
Console::output('=======================');
Console::output('Converting table ' . $tablename);
$count = (new Query())->from($tablename)->count();
$rowcount = 0;
Console::startProgress($rowcount, $count);
$query = (new Query())
->select('id')
->addSelect($columns)
->from($tablename)
->orderBy('id ASC');
foreach ($query->each() as $row) {
$rowcount++;
$changes = [];
foreach ($columns as $columnname) {
if (strlen($row[$columnname]) > 0) {
$cleartext = Security::decrypt($row[$columnname], 'YOUR_OLD_ENCRYPTION_KEY');
if (strlen($cleartext) > 0) {
$changes[$columnname] = Yii::$app->getSecurity()->encryptByKey($cleartext, 'YOUR_NEW_ENCRYPTION_KEY');
}
}
}
if (count($changes) > 0) {
$connection->createCommand()->update($tablename, $changes, 'id = :id', [':id' => $row['id']])->execute();
}
Console::updateProgress($rowcount, $count, str_pad($row['id'], 6));
}
Console::endProgress();
}
}
public function down()
{
echo "m140726_144401_securityOverhaul cannot be reverted.\n";
return false;
}
} |
@samdark you forgot to remove unnecessary |
A more general version of this problem is migration of data from Yii1 apps. For that it seems you can follow Using Yii1 with Yii2 in the Guide to get access to both crypto APIs at the same time. With that you have several options, best of which is to change the Yii1 app to use Might want to say something about this in the Upgrading page of the Guide |
By upgrading to the last dev-master version, the #4458 commit by @samdark broke my code.
I understand that security gets beefed up, and I'd like to upgrade my code to the latest standards, but this means that I need to re-encrypt my existing encrypted columns in the database to the new standard. The upgrade guide contains settings to emulate the legacy encryption which used to work up till now, but have apparently been removed:
What would be the best way to do this transition? I would need to write a migration using both the "old-style" security for decryption and the "new style" security for encryption.
The text was updated successfully, but these errors were encountered: