omar j
omar j

Reputation: 541

Set config variables dynamically in laravel for encrypted keys

I have a complicated requirement to encrypt all secret keys (pwds) that appear in the laravel config. No secret info can be stored in plaintext! The varaibles need to be pulled in and decrypted at runtime. I would like them to be available via Config class, ie Config::get().

Does anyone have any idea how to achieve this?

Upvotes: 1

Views: 2064

Answers (1)

omar j
omar j

Reputation: 541

Ok, I came up with a solution but it would be interesting if anyone has anything better. My approach was to:

1) Generate a secret key on the server and store it in plaintext as a global variable. As i'm using apache i did this in my apache config:

SetEnv APPLICATION_KEY "a-randonly-generated-32-char-key"

This key will be used to encrypt/decrypt all sensitive pwds/keys that we use.

2) Write an artisan command to encrypt sensitive values and store them in the configuration. Laravel does not allow you to do this easily so i used a 3rd party package (https://github.com/Phil-F/Setting) to do this. The package allows you to write config vars to json. They can then be retrieved by the app at runtime.

The artisan command accepts the key 'name' and 'value' as arguments and calls:

$encryptedValue = Crypt::encrypt($value);

Then stores the value in the json config (using calls to the package class 'Setting'):

Setting::set($name, $encryptedValue );

3) We can then remove sensitive config variables. For instance, if i have a config var normally retrieved using Config::get('mail.password') then i remove this from the mail.php config file and i call artisan passing in 'mail.password' and 'the-password-value'. By default the package stores the json at /app/storage/meta/setting.json. You should see your encrypted variables here.

4) Now we need to pull these variables in and decrypt them at runtime. To do this i added code to the 'before' filter (see /app/filters.php). Here i synchronise the secret variables with the usual (static) laravel ones. For tidiness i store the names of the encrypted keys as an array in /config/app.php, eg

'encrypted_keys' => array('mail.password', 'services.mandrill.secret'),

Then to synchronize:

$encryptedKeys = Config::get('app.encrypted_keys');
foreach ($encryptedKeys as $encryptedKey) {
    // Get encrypted key from json and decrypt it
    $encryptedValue = Crypt::decrypt(Setting::get($encryptedKey));

    // Store it in the config (note: its not visible in the config file itself)
    Config::set($encryptedKey, $encryptedValue);
}

This synchronization makes the sensitive data that we've pulled in available using Config::get() and makes it much more compatible with existing code. Alternatively you'd have to go around replacing it Config::get() with Setting::get() everywhere you want to use those variables.

Hope this helps someone ... took me a while to work it all out!

Upvotes: 1

Related Questions