2017-08-21 22:30:56 -07:00
< ? php
namespace App\Console\Commands ;
use App\LegacyEncrypter\McryptEncrypter ;
use App\Models\Asset ;
2019-03-13 20:12:03 -07:00
use App\Models\CustomField ;
use App\Models\Setting ;
use Illuminate\Console\Command ;
2017-08-21 22:30:56 -07:00
use Illuminate\Support\Facades\Storage ;
class RecryptFromMcrypt extends Command
{
/**
* The name and signature of the console command .
*
* @ var string
*/
2017-10-20 17:21:21 -07:00
protected $signature = ' snipeit : legacy - recrypt
{ -- force : Force a re - crypt of encrypted data from MCRYPT . } ' ;
2017-08-21 22:30:56 -07:00
/**
* The console command description .
*
* @ var string
*/
protected $description = 'This command allows upgrading users to de-encrypt their deprecated mcrypt encrypted fields and re-encrypt them using the current OpenSSL encryption.' ;
/**
* Create a new command instance .
*
* @ return void
*/
public function __construct ()
{
parent :: __construct ();
}
/**
* Execute the console command .
*
* @ return mixed
*/
public function handle ()
{
// Check and see if they have a legacy app key listed in their .env
// If not, we can try to use the current APP_KEY if looks like it's old
$legacy_key = env ( 'LEGACY_APP_KEY' );
2017-09-14 16:43:41 -07:00
$key_parts = explode ( ':' , $legacy_key );
2017-11-03 16:27:03 -07:00
$legacy_cipher = env ( 'LEGACY_CIPHER' , 'rijndael-256' );
2021-06-10 13:15:52 -07:00
$errors = [];
2017-08-21 22:30:56 -07:00
2021-06-10 13:15:52 -07:00
if ( ! $legacy_key ) {
2017-08-21 22:30:56 -07:00
$this -> error ( 'ERROR: You do not have a LEGACY_APP_KEY set in your .env file. Please locate your old APP_KEY and ADD a line to your .env file like: LEGACY_APP_KEY=YOUR_OLD_APP_KEY' );
2021-06-10 13:15:52 -07:00
2017-08-21 22:30:56 -07:00
return false ;
}
2017-09-14 16:43:41 -07:00
// Do some basic legacy app key length checks
2017-08-21 22:30:56 -07:00
if ( strlen ( $legacy_key ) == 32 ) {
2017-09-14 16:43:41 -07:00
$legacy_length_check = true ;
2021-06-10 13:15:52 -07:00
} elseif ( array_key_exists ( '1' , $key_parts ) && ( strlen ( $key_parts [ 1 ]) == 44 )) {
$legacy_key = base64_decode ( $key_parts [ 1 ], true );
2017-09-14 16:43:41 -07:00
$legacy_length_check = true ;
} else {
$legacy_length_check = false ;
}
// Check that the app key is 32 characters
if ( $legacy_length_check === true ) {
$this -> comment ( 'INFO: Your LEGACY_APP_KEY looks correct. Okay to continue.' );
2017-08-21 22:30:56 -07:00
} else {
2017-09-14 16:43:41 -07:00
$this -> error ( 'ERROR: Your LEGACY_APP_KEY is not the correct length (32 characters or base64 followed by 44 characters for later versions). Please locate your old APP_KEY and use that as your LEGACY_APP_KEY in your .env file to continue.' );
2021-06-10 13:15:52 -07:00
2017-08-21 22:30:56 -07:00
return false ;
}
$this -> error ( '================================!!!! WARNING !!!!================================' );
$this -> error ( '================================!!!! WARNING !!!!================================' );
$this -> comment ( " This tool will attempt to decrypt your old Snipe-IT (mcrypt, now deprecated) encrypted data and re-encrypt it using OpenSSL. \n \n You should only continue if you have backed up any and all old APP_KEYs and have backed up your data. " );
2017-10-20 17:21:21 -07:00
$force = ( $this -> option ( 'force' )) ? true : false ;
2021-06-10 13:15:52 -07:00
if ( $force || ( $this -> confirm ( 'Are you SURE you wish to continue?' ))) {
2017-08-21 22:30:56 -07:00
$backup_file = 'backups/env-backups/' . 'app_key-' . date ( 'Y-m-d-gis' );
try {
Storage :: disk ( 'local' ) -> put ( $backup_file , 'APP_KEY: ' . config ( 'app.key' ));
Storage :: disk ( 'local' ) -> append ( $backup_file , 'LEGACY_APP_KEY: ' . $legacy_key );
} catch ( \Exception $e ) {
$this -> info ( 'WARNING: Could not backup app keys' );
}
2021-06-10 13:15:52 -07:00
if ( $legacy_cipher ) {
$mcrypter = new McryptEncrypter ( $legacy_key , $legacy_cipher );
} else {
2017-10-18 05:43:54 -07:00
$mcrypter = new McryptEncrypter ( $legacy_key );
}
2017-08-21 22:30:56 -07:00
$settings = Setting :: getSettings ();
2021-06-10 13:15:52 -07:00
if ( $settings -> ldap_pword == '' ) {
2017-08-21 22:30:56 -07:00
$this -> comment ( 'INFO: No LDAP password found. Skipping... ' );
2017-10-18 08:15:23 -07:00
} else {
$decrypted_ldap_pword = $mcrypter -> decrypt ( $settings -> ldap_pword );
2024-05-29 04:38:15 -07:00
$settings -> ldap_pword = Crypt :: encrypt ( $decrypted_ldap_pword );
2017-10-18 08:15:23 -07:00
$settings -> save ();
2017-08-21 22:30:56 -07:00
}
2017-10-18 05:43:54 -07:00
/** @var CustomField[] $custom_fields */
2021-06-10 13:15:52 -07:00
$custom_fields = CustomField :: where ( 'field_encrypted' , '=' , 1 ) -> get ();
2017-08-21 22:30:56 -07:00
$this -> comment ( 'INFO: Retrieving encrypted custom fields...' );
$query = Asset :: withTrashed ();
foreach ( $custom_fields as $custom_field ) {
2021-06-10 13:15:52 -07:00
$this -> comment ( 'FIELD TO RECRYPT: ' . $custom_field -> name . ' (' . $custom_field -> db_column . ')' );
2017-08-21 22:30:56 -07:00
$query -> orWhereNotNull ( $custom_field -> db_column );
}
// Get all assets with a value in any of the fields that were encrypted
2017-10-18 05:43:54 -07:00
/** @var Asset[] $assets */
2017-08-21 22:30:56 -07:00
$assets = $query -> get ();
$bar = $this -> output -> createProgressBar ( count ( $assets ));
foreach ( $assets as $asset ) {
foreach ( $custom_fields as $encrypted_field ) {
2017-10-18 05:43:54 -07:00
$columnName = $encrypted_field -> db_column ;
2017-08-21 22:30:56 -07:00
// Make sure the value isn't null
2021-06-10 13:15:52 -07:00
if ( $asset -> { $columnName } != '' ) {
2017-08-21 22:30:56 -07:00
// Try to decrypt the payload using the legacy app key
try {
2017-10-18 05:43:54 -07:00
$decrypted_field = $mcrypter -> decrypt ( $asset -> { $columnName });
2024-05-29 04:38:15 -07:00
$asset -> { $columnName } = Crypt :: encrypt ( $decrypted_field );
2017-08-21 22:30:56 -07:00
$this -> comment ( $decrypted_field );
} catch ( \Exception $e ) {
$errors [] = ' - ERROR: Could not decrypt field [' . $encrypted_field -> name . ']: ' . $e -> getMessage ();
}
}
}
$asset -> save ();
$bar -> advance ();
}
$bar -> finish ();
if ( count ( $errors ) > 0 ) {
$this -> comment ( " \n \n " );
$this -> error ( " The decrypter encountered some errors: \n " );
foreach ( $errors as $error ) {
$this -> error ( $error );
}
}
}
}
}