Skip to content

Commit

Permalink
feat!: only encrypt secrets (#2)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: with the only values flag now only variables ending with _PASSWORD, _KEY or _SECRET will be encrypted by default. Configurable with the --only flag.
  • Loading branch information
patrickhoogkamer authored Jan 5, 2024
1 parent d06cc43 commit 2c2a67b
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 14 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ eyJpdiI6ImplT2xTaGRzV... # Really long string
But with this package you can make it look like this:

```text
APP_NAME=eyJpdiI6ImplT2xTaGRzV...
APP_ENV=eyJpdiI6ImplT2xTaGRzV...
APP_DEBUG=eyJpdiI6ImplT2xTaGRzV...
APP_NAME="My awesome app"
APP_ENV=local
APP_DEBUG=true
SOME_API_KEY=eyJpdiI6ImplT2xTaGRzV...
```
Expand All @@ -44,3 +44,19 @@ Just use the `env:encrypt` and `env:decrypt` commands as usual, but add an `--on
php artisan env:encrypt --only-values ...
php artisan env:decrypt --only-values ...
```

### Only Encrypting Secrets
By default, if the `--only-values` flag is used only variables ending with `_PASSWORD`, `_KEY` and `_SECRET` will be encrypted. You can configure this behaviour with the `--only` flag. If you would only want to encrypt the variables ending with `_SECRET` and the `APP_KEY`, use it like this:

```shell
php artisan env:encrypt --only-values --only="*_SECRET,APP_KEY"
```

For decrypting, there is no difference: the decrypt command will leave unencrypted values.

### Encrypting Everything
If you still want to encrypt everything while keeping variable names readable, use the `--all` flag:

```shell
php artisan env:encrypt --only-values --all
```
14 changes: 12 additions & 2 deletions src/Console/EnvironmentDecryptCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Intermax\Veil\Console;

use Exception;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Encryption\Encrypter;
use Illuminate\Foundation\Console\EnvironmentDecryptCommand as BaseDecryptCommand;
use Illuminate\Support\Env;
Expand Down Expand Up @@ -96,8 +97,17 @@ protected function decryptValues(string $contents, Encrypter $encrypter): string
return $line->before('=')
->append('=')
->append(
$line->after('=')
->pipe(fn (Stringable $value) => $encrypter->decrypt($value->toString()))
$line->after('=')->pipe(function (Stringable $value) use ($encrypter) {
try {
return $encrypter->decrypt($value->toString());
} catch (DecryptException $e) {
if ($e->getMessage() == 'The payload is invalid.') {
return $value->toString();
}

throw $e;
}
})
);
})->toArray());
}
Expand Down
13 changes: 11 additions & 2 deletions src/Console/EnvironmentEncryptCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class EnvironmentEncryptCommand extends BaseEncryptCommand
{--cipher= : The encryption cipher}
{--env= : The environment to be encrypted}
{--force : Overwrite the existing encrypted environment file}
{--only-values : Encrypt only the values to keep the file readable}';
{--only-values : Encrypt only the values to keep the file readable}
{--only=**_KEY,*_SECRET,*_PASSWORD : Encrypt only variables that match provided comma-separated patterns, by default values with *_KEY, *_SECRET and *_PASSWORD will be encrypted}
{--all : Ignore the --only flag and default patterns to encrypt all variables}';

public function handle()
{
Expand Down Expand Up @@ -76,13 +78,20 @@ public function handle()

protected function encryptValues(string $contents, Encrypter $encrypter): string
{
return implode(PHP_EOL, collect(explode(PHP_EOL, $contents))->map(function (string $line) use ($encrypter) {
/** @var array<int, string> $only */
$only = $this->option('only');

return implode(PHP_EOL, collect(explode(PHP_EOL, $contents))->map(function (string $line) use ($encrypter, $only) {
$line = Str::of($line);

if (! $line->contains('=')) {
return $line;
}

if (! $this->option('all') && $only !== null && ! $line->before('=')->is($only)) {
return $line;
}

return $line->before('=')
->append('=')
->append(
Expand Down
12 changes: 7 additions & 5 deletions tests/Integration/EnvironmentDecryptCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,23 @@
File::swap($this->filesystem);
});

it('decrypts an encrypted environment where only values are encrypted', function () {
it('decrypts an encrypted environment where only secrets are encrypted', function () {
$contents = <<<'Text'
APP_NAME=Laravel
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost
APP_KEY=1234
Text;

$encrypter = new Encrypter('abcdefghijklmnopabcdefghijklmnop', 'AES-256-CBC');

$encryptedContents = <<<TEXT
APP_NAME={$encrypter->encrypt('Laravel')}
APP_ENV={$encrypter->encrypt('local')}
APP_DEBUG={$encrypter->encrypt('true')}
APP_URL={$encrypter->encrypt('http://localhost')}
APP_NAME=Laravel
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost
APP_KEY={$encrypter->encrypt('1234')}
TEXT;

$this->filesystem->shouldReceive('exists')
Expand Down
9 changes: 7 additions & 2 deletions tests/Integration/EnvironmentEncryptCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Encryption\Encrypter;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Mockery as m;

beforeEach(function () {
Expand All @@ -16,8 +17,9 @@
File::swap($this->filesystem);
});

it('encrypts the values of an environment', function () {
it('encrypts the secrets of an environment', function () {
$contents = <<<'Text'
APP_KEY=1234
APP_NAME=Laravel
APP_ENV=local
APP_DEBUG=true
Expand All @@ -40,8 +42,11 @@
$this->assertStringContainsString('APP_ENV', $contents);
$this->assertStringContainsString('APP_DEBUG', $contents);
$this->assertStringContainsString('APP_URL', $contents);
$this->assertStringContainsString('APP_KEY', $contents);

$this->assertEquals('Laravel', $encrypter->decrypt(Str::betweenFirst($contents, '=', "\n")));
$this->assertEquals('1234', $encrypter->decrypt(Str::betweenFirst($contents, '=', "\n")));

$this->assertEquals('http://localhost', Str::afterLast($contents, '='));

return true;
})->andReturn(true);
Expand Down

0 comments on commit 2c2a67b

Please sign in to comment.