Skip to content

Commit 6319837

Browse files
authored
[9.x] Prevents booting providers when running env:decrypt (#44654)
* Prevent provider boot * wip * wip * Support custom file path * Remove argument * Add reboot state * Wording * Revert reboot state * Update force check * Remove duplicate * Update tests * Format output filename
1 parent 1661857 commit 6319837

File tree

3 files changed

+92
-12
lines changed

3 files changed

+92
-12
lines changed

src/Illuminate/Foundation/Console/EnvironmentDecryptCommand.php

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ class EnvironmentDecryptCommand extends Command
2323
{--cipher= : The encryption cipher}
2424
{--env= : The environment to be decrypted}
2525
{--force : Overwrite the existing environment file}
26-
{--filename= : Where to write the decrypted file contents}';
26+
{--path= : Path to write the decrypted file}
27+
{--filename= : Filename of the decrypted file}';
2728

2829
/**
2930
* The name of the console command.
@@ -82,17 +83,13 @@ public function handle()
8283

8384
$key = $this->parseKey($key);
8485

85-
$environmentFile = $this->option('env')
86+
$encryptedFile = ($this->option('env')
8687
? base_path('.env').'.'.$this->option('env')
87-
: $this->laravel->environmentFilePath();
88+
: $this->laravel->environmentFilePath()).'.encrypted';
8889

89-
$encryptedFile = $environmentFile.'.encrypted';
90+
$outputFile = $this->outputFilePath();
9091

91-
$filename = $this->option('filename')
92-
? base_path($this->option('filename'))
93-
: $environmentFile;
94-
95-
if (Str::endsWith($filename, '.encrypted')) {
92+
if (Str::endsWith($outputFile, '.encrypted')) {
9693
$this->components->error('Invalid filename.');
9794

9895
return Command::FAILURE;
@@ -104,7 +101,7 @@ public function handle()
104101
return Command::FAILURE;
105102
}
106103

107-
if ($this->files->exists($environmentFile) && ! $this->option('force')) {
104+
if ($this->files->exists($outputFile) && ! $this->option('force')) {
108105
$this->components->error('Environment file already exists.');
109106

110107
return Command::FAILURE;
@@ -114,7 +111,7 @@ public function handle()
114111
$encrypter = new Encrypter($key, $cipher);
115112

116113
$this->files->put(
117-
$filename,
114+
$outputFile,
118115
$encrypter->decrypt($this->files->get($encryptedFile))
119116
);
120117
} catch (Exception $e) {
@@ -125,7 +122,7 @@ public function handle()
125122

126123
$this->components->info('Environment successfully decrypted.');
127124

128-
$this->components->twoColumnDetail('Decrypted file', $filename);
125+
$this->components->twoColumnDetail('Decrypted file', $outputFile);
129126

130127
$this->newLine();
131128
}
@@ -144,4 +141,19 @@ protected function parseKey(string $key)
144141

145142
return $key;
146143
}
144+
145+
/**
146+
* Get the output file path that should be used for the command.
147+
*
148+
* @return string
149+
*/
150+
protected function outputFilePath()
151+
{
152+
$path = Str::finish($this->option('path') ?: base_path(), DIRECTORY_SEPARATOR);
153+
154+
$outputFile = $this->option('filename') ?: ('.env'.($this->option('env') ? '.'.$this->option('env') : ''));
155+
$outputFile = ltrim($outputFile, DIRECTORY_SEPARATOR);
156+
157+
return $path.$outputFile;
158+
}
147159
}

src/Illuminate/Foundation/Console/Kernel.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ public function handle($input, $output = null)
146146
$this->commandStartedAt = Carbon::now();
147147

148148
try {
149+
if ($input->getFirstArgument() === 'env:decrypt') {
150+
$this->bootstrapWithoutBootingProviders();
151+
}
152+
149153
$this->bootstrap();
150154

151155
return $this->getArtisan()->run($input, $output);
@@ -323,6 +327,10 @@ public function registerCommand($command)
323327
*/
324328
public function call($command, array $parameters = [], $outputBuffer = null)
325329
{
330+
if ($command === 'env:decrypt') {
331+
$this->bootstrapWithoutBootingProviders();
332+
}
333+
326334
$this->bootstrap();
327335

328336
return $this->getArtisan()->call($command, $parameters, $outputBuffer);
@@ -384,6 +392,20 @@ public function bootstrap()
384392
}
385393
}
386394

395+
/**
396+
* Bootstrap the application without booting service providers.
397+
*
398+
* @return void
399+
*/
400+
public function bootstrapWithoutBootingProviders()
401+
{
402+
$this->app->bootstrapWith(
403+
collect($this->bootstrappers())->reject(function ($bootstrapper) {
404+
return $bootstrapper === \Illuminate\Foundation\Bootstrap\BootProviders::class;
405+
})->all()
406+
);
407+
}
408+
387409
/**
388410
* Get the Artisan application instance.
389411
*

tests/Integration/Console/EnvironmentDecryptCommandTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,52 @@ public function testItWritesTheEnvironmentFileCustomFilename()
226226
->with(base_path('.env'), 'APP_NAME="Laravel Two"');
227227
}
228228

229+
public function testItWritesTheEnvironmentFileCustomPath()
230+
{
231+
$this->filesystem->shouldReceive('exists')
232+
->once()
233+
->andReturn(true)
234+
->shouldReceive('exists')
235+
->once()
236+
->andReturn(false)
237+
->shouldReceive('get')
238+
->once()
239+
->andReturn(
240+
(new Encrypter('abcdefghijklmnopabcdefghijklmnop', 'AES-256-CBC'))
241+
->encrypt('APP_NAME="Laravel Two"')
242+
);
243+
244+
$this->artisan('env:decrypt', ['--env' => 'production', '--key' => 'abcdefghijklmnopabcdefghijklmnop', '--path' => '/tmp'])
245+
->expectsOutputToContain('Environment successfully decrypted.')
246+
->assertExitCode(0);
247+
248+
$this->filesystem->shouldHaveReceived('put')
249+
->with('/tmp'.DIRECTORY_SEPARATOR.'.env.production', 'APP_NAME="Laravel Two"');
250+
}
251+
252+
public function testItWritesTheEnvironmentFileCustomPathAndFilename()
253+
{
254+
$this->filesystem->shouldReceive('exists')
255+
->once()
256+
->andReturn(true)
257+
->shouldReceive('exists')
258+
->once()
259+
->andReturn(false)
260+
->shouldReceive('get')
261+
->once()
262+
->andReturn(
263+
(new Encrypter('abcdefghijklmnopabcdefghijklmnop', 'AES-256-CBC'))
264+
->encrypt('APP_NAME="Laravel Two"')
265+
);
266+
267+
$this->artisan('env:decrypt', ['--env' => 'production', '--key' => 'abcdefghijklmnopabcdefghijklmnop', '--filename' => '.env', '--path' => '/tmp'])
268+
->expectsOutputToContain('Environment successfully decrypted.')
269+
->assertExitCode(0);
270+
271+
$this->filesystem->shouldHaveReceived('put')
272+
->with('/tmp'.DIRECTORY_SEPARATOR.'.env', 'APP_NAME="Laravel Two"');
273+
}
274+
229275
public function testItCannotOverwriteEncryptedFiles()
230276
{
231277
$this->artisan('env:decrypt', ['--env' => 'production', '--key' => 'abcdefghijklmnop', '--filename' => '.env.production.encrypted'])

0 commit comments

Comments
 (0)