2019-09-03 11:03:32 -07:00
< ? php
namespace App\Console\Commands ;
use App\Models\Asset ;
2021-06-10 13:15:52 -07:00
use App\Models\CustomField ;
2019-09-03 11:03:32 -07:00
use App\Models\Setting ;
2021-06-10 13:15:52 -07:00
use Artisan ;
use Illuminate\Console\Command ;
use Illuminate\Encryption\Encrypter ;
2019-09-03 11:03:32 -07:00
class RotateAppKey extends Command
{
/**
* The name and signature of the console command .
*
* @ var string
*/
protected $signature = 'snipeit:rotate-key' ;
/**
* The console command description .
*
* @ var string
*/
protected $description = 'Command description' ;
/**
* Create a new command instance .
*
* @ return void
*/
public function __construct ()
{
parent :: __construct ();
}
/**
* Execute the console command .
*
* @ return mixed
*/
public function handle ()
{
2021-06-10 13:15:52 -07:00
if ( $this -> confirm ( " \n **************************************************** \n THIS WILL MODIFY YOUR APP_KEY AND DE-CRYPT YOUR ENCRYPTED CUSTOM FIELDS AND \n RE-ENCRYPT THEM WITH A NEWLY GENERATED KEY. \n \n There is NO undo. \n \n Make SURE you have a database backup and a backup of your .env generated BEFORE running this command. \n \n If you do not save the newly generated APP_KEY to your .env in this process, \n your encrypted data will no longer be decryptable. \n \n Are you SURE you wish to continue, and have confirmed you have a database backup and an .env backup? " )) {
2019-09-03 11:03:32 -07:00
// Get the existing app_key and ciphers
// We put them in a variable since we clear the cache partway through here.
$old_app_key = config ( 'app.key' );
$cipher = config ( 'app.cipher' );
// Generate a new one
Artisan :: call ( 'key:generate' , [ '--show' => true ]);
$new_app_key = Artisan :: output ();
// Clear the config cache
Artisan :: call ( 'config:clear' );
$this -> warn ( 'Your app cipher is: ' . $cipher );
$this -> warn ( 'Your old APP_KEY is: ' . $old_app_key );
$this -> warn ( 'Your new APP_KEY is: ' . $new_app_key );
// Write the new app key to the .env file
$this -> writeNewEnvironmentFileWith ( $new_app_key );
// Manually create an old encrypter instance using the old app key
// and also create a new encrypter instance so we can re-crypt the field
// using the newly generated app key
$oldEncrypter = new Encrypter ( base64_decode ( substr ( $old_app_key , 7 )), $cipher );
$newEncrypter = new Encrypter ( base64_decode ( substr ( $new_app_key , 7 )), $cipher );
$fields = CustomField :: where ( 'field_encrypted' , '1' ) -> get ();
foreach ( $fields as $field ) {
$assets = Asset :: whereNotNull ( $field -> db_column ) -> get ();
foreach ( $assets as $asset ) {
$asset -> { $field -> db_column } = $oldEncrypter -> decrypt ( $asset -> { $field -> db_column });
2021-06-10 13:15:52 -07:00
$this -> line ( 'DECRYPTED: ' . $field -> db_column );
2019-09-03 11:03:32 -07:00
$asset -> { $field -> db_column } = $newEncrypter -> encrypt ( $asset -> { $field -> db_column });
$this -> line ( 'ENCRYPTED: ' . $field -> db_column );
$asset -> save ();
}
}
// Handle the LDAP password if one is provided
$setting = Setting :: first ();
2021-06-10 13:15:52 -07:00
if ( $setting -> ldap_pword != '' ) {
$setting -> ldap_pword = $oldEncrypter -> decrypt ( $setting -> ldap_pword );
$setting -> ldap_pword = $newEncrypter -> encrypt ( $setting -> ldap_pword );
2019-09-03 11:03:32 -07:00
$setting -> save ();
$this -> warn ( 'LDAP password has been re-encrypted.' );
}
} else {
$this -> info ( 'This operation has been canceled. No changes have been made.' );
}
}
/**
* Write a new environment file with the given key .
*
* @ param string $key
* @ return void
*/
protected function writeNewEnvironmentFileWith ( $key )
{
file_put_contents ( $this -> laravel -> environmentFilePath (), preg_replace (
$this -> keyReplacementPattern (),
'APP_KEY=' . $key ,
file_get_contents ( $this -> laravel -> environmentFilePath ())
));
}
/**
* Get a regex pattern that will match env APP_KEY with any random key .
*
* @ return string
*/
protected function keyReplacementPattern ()
{
$escaped = preg_quote ( '=' . $this -> laravel [ 'config' ][ 'app.key' ], '/' );
2021-06-10 13:15:52 -07:00
2019-09-03 11:03:32 -07:00
return " /^APP_KEY { $escaped } /m " ;
}
}