Skip to content
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

feat!: only encrypt secrets #2

Merged
merged 1 commit into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading