Merge branch '4.4'
* 4.4: [FrameworkBundle] Remove suffix convention when using env vars to override secrets from the vault
This commit is contained in:
commit
6c3924c80a
@ -45,7 +45,7 @@ final class SecretsDecryptToLocalCommand extends Command
|
||||
->setDescription('Decrypts all secrets and stores them in the local vault.')
|
||||
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces overriding of secrets that already exist in the local vault')
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command list decrypts all secrets and stores them in the local vault..
|
||||
The <info>%command.name%</info> command decrypts all secrets and copies them in the local vault.
|
||||
|
||||
<info>%command.full_name%</info>
|
||||
|
||||
|
@ -14,7 +14,6 @@ namespace Symfony\Bundle\FrameworkBundle\Command;
|
||||
use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
@ -43,15 +42,10 @@ final class SecretsEncryptFromLocalCommand extends Command
|
||||
{
|
||||
$this
|
||||
->setDescription('Encrypts all local secrets to the vault.')
|
||||
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces overriding of secrets that already exist in the vault')
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command list encrypts all local secrets and stores them in the vault..
|
||||
The <info>%command.name%</info> command encrypts all locally overridden secrets to the vault.
|
||||
|
||||
<info>%command.full_name%</info>
|
||||
|
||||
When the option <info>--force</info> is provided, secrets that already exist in the vault are overriden.
|
||||
|
||||
<info>%command.full_name% --force</info>
|
||||
EOF
|
||||
)
|
||||
;
|
||||
@ -67,22 +61,16 @@ EOF
|
||||
return 1;
|
||||
}
|
||||
|
||||
$secrets = $this->localVault->list(true);
|
||||
foreach ($this->vault->list(true) as $name => $value) {
|
||||
$localValue = $this->localVault->reveal($name);
|
||||
|
||||
if (!$input->getOption('force')) {
|
||||
foreach ($this->vault->list() as $k => $v) {
|
||||
unset($secrets[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($secrets as $k => $v) {
|
||||
if (null === $v) {
|
||||
$io->error($this->localVault->getLastMessage());
|
||||
if (null !== $localValue && $value !== $localValue) {
|
||||
$this->vault->seal($name, $localValue);
|
||||
} elseif (null !== $message = $this->localVault->getLastMessage()) {
|
||||
$io->error($message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->vault->seal($k, $v);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -89,10 +89,10 @@ EOF
|
||||
}
|
||||
|
||||
foreach ($localSecrets ?? [] as $name => $value) {
|
||||
$rows[$name] = [$name, $rows[$name][1] ?? '', $dump($value)];
|
||||
if (isset($rows[$name])) {
|
||||
$rows[$name][] = $dump($value);
|
||||
}
|
||||
}
|
||||
|
||||
uksort($rows, 'strnatcmp');
|
||||
|
||||
if (null !== $this->localVault && null !== $message = $this->localVault->getLastMessage()) {
|
||||
$io->comment($message);
|
||||
|
@ -86,6 +86,12 @@ EOF
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($this->localVault === $vault && !\array_key_exists($name, $this->vault->list())) {
|
||||
$io->error(sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.', $name));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 < $random = $input->getOption('random') ?? 16) {
|
||||
$value = strtr(substr(base64_encode(random_bytes($random)), 0, $random), '+/', '-_');
|
||||
} elseif (!$file = $input->getArgument('file')) {
|
||||
|
@ -36,14 +36,13 @@ class DotenvVault extends AbstractVault
|
||||
{
|
||||
$this->lastMessage = null;
|
||||
$this->validateName($name);
|
||||
$k = $name.'_SECRET';
|
||||
$v = str_replace("'", "'\\''", $value);
|
||||
|
||||
$content = file_exists($this->dotenvFile) ? file_get_contents($this->dotenvFile) : '';
|
||||
$content = preg_replace("/^$k=((\\\\'|'[^']++')++|.*)/m", "$k='$v'", $content, -1, $count);
|
||||
$content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)/m", "$name='$v'", $content, -1, $count);
|
||||
|
||||
if (!$count) {
|
||||
$content .= "$k='$v'\n";
|
||||
$content .= "$name='$v'\n";
|
||||
}
|
||||
|
||||
file_put_contents($this->dotenvFile, $content);
|
||||
@ -55,8 +54,7 @@ class DotenvVault extends AbstractVault
|
||||
{
|
||||
$this->lastMessage = null;
|
||||
$this->validateName($name);
|
||||
$k = $name.'_SECRET';
|
||||
$v = \is_string($_SERVER[$k] ?? null) ? $_SERVER[$k] : ($_ENV[$k] ?? null);
|
||||
$v = \is_string($_SERVER[$name] ?? null) ? $_SERVER[$name] : ($_ENV[$name] ?? null);
|
||||
|
||||
if (null === $v) {
|
||||
$this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile));
|
||||
@ -71,10 +69,9 @@ class DotenvVault extends AbstractVault
|
||||
{
|
||||
$this->lastMessage = null;
|
||||
$this->validateName($name);
|
||||
$k = $name.'_SECRET';
|
||||
|
||||
$content = file_exists($this->dotenvFile) ? file_get_contents($this->dotenvFile) : '';
|
||||
$content = preg_replace("/^$k=((\\\\'|'[^']++')++|.*)\n?/m", '', $content, -1, $count);
|
||||
$content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)\n?/m", '', $content, -1, $count);
|
||||
|
||||
if ($count) {
|
||||
file_put_contents($this->dotenvFile, $content);
|
||||
@ -94,14 +91,14 @@ class DotenvVault extends AbstractVault
|
||||
$secrets = [];
|
||||
|
||||
foreach ($_ENV as $k => $v) {
|
||||
if (preg_match('/^(\w+)_SECRET$/D', $k, $m)) {
|
||||
$secrets[$m[1]] = $reveal ? $v : null;
|
||||
if (preg_match('/^\w+$/D', $k)) {
|
||||
$secrets[$k] = $reveal ? $v : null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($_SERVER as $k => $v) {
|
||||
if (\is_string($v) && preg_match('/^(\w+)_SECRET$/D', $k, $m)) {
|
||||
$secrets[$m[1]] = $reveal ? $v : null;
|
||||
if (\is_string($v) && preg_match('/^\w+$/D', $k)) {
|
||||
$secrets[$k] = $reveal ? $v : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,9 @@ class SecretEnvVarProcessor implements EnvVarProcessorInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEnv($prefix, $name, \Closure $getEnv)
|
||||
public function getEnv($prefix, $name, \Closure $getEnv): string
|
||||
{
|
||||
if (null !== $this->localVault && null !== $secret = $this->localVault->reveal($name)) {
|
||||
if (null !== $this->localVault && null !== ($secret = $this->localVault->reveal($name)) && \array_key_exists($name, $this->vault->list())) {
|
||||
return $secret;
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,12 @@ class SodiumVault extends AbstractVault
|
||||
$this->validateName($name);
|
||||
$this->loadKeys();
|
||||
$this->export($name.'.'.substr_replace(md5($name), '.sodium', -26), sodium_crypto_box_seal($value, $this->encryptionKey ?? sodium_crypto_box_publickey($this->decryptionKey)));
|
||||
|
||||
$list = $this->list();
|
||||
$list[$name] = null;
|
||||
uksort($list, 'strnatcmp');
|
||||
file_put_contents($this->pathPrefix.'sodium.list', sprintf("<?php\n\nreturn %s;\n", var_export($list, true), LOCK_EX));
|
||||
|
||||
$this->lastMessage = sprintf('Secret "%s" encrypted in "%s"; you can commit it.', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR));
|
||||
}
|
||||
|
||||
@ -123,6 +129,10 @@ class SodiumVault extends AbstractVault
|
||||
return false;
|
||||
}
|
||||
|
||||
$list = $this->list();
|
||||
unset($list[$name]);
|
||||
file_put_contents($this->pathPrefix.'sodium.list', sprintf("<?php\n\nreturn %s;\n", var_export($list, true), LOCK_EX));
|
||||
|
||||
$this->lastMessage = sprintf('Secret "%s" removed from "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR));
|
||||
|
||||
return @unlink($file) || !file_exists($file);
|
||||
@ -131,13 +141,19 @@ class SodiumVault extends AbstractVault
|
||||
public function list(bool $reveal = false): array
|
||||
{
|
||||
$this->lastMessage = null;
|
||||
$secrets = [];
|
||||
$regexp = sprintf('{^%s(\w++)\.[0-9a-f]{6}\.sodium$}D', preg_quote(basename($this->pathPrefix)));
|
||||
|
||||
foreach (scandir(\dirname($this->pathPrefix)) as $name) {
|
||||
if (preg_match($regexp, $name, $m)) {
|
||||
$secrets[$m[1]] = $reveal ? $this->reveal($m[1]) : null;
|
||||
if (!file_exists($file = $this->pathPrefix.'sodium.list')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$secrets = include $file;
|
||||
|
||||
if (!$reveal) {
|
||||
return $secrets;
|
||||
}
|
||||
|
||||
foreach ($secrets as $name => $value) {
|
||||
$secrets[$name] = $this->reveal($name);
|
||||
}
|
||||
|
||||
return $secrets;
|
||||
|
@ -37,21 +37,21 @@ class DotenvVaultTest extends TestCase
|
||||
|
||||
$vault->seal('foo', $plain);
|
||||
|
||||
unset($_SERVER['foo_SECRET'], $_ENV['foo_SECRET']);
|
||||
unset($_SERVER['foo'], $_ENV['foo']);
|
||||
(new Dotenv(false))->load($this->envFile);
|
||||
|
||||
$decrypted = $vault->reveal('foo');
|
||||
$this->assertSame($plain, $decrypted);
|
||||
|
||||
$this->assertSame(['foo' => null], $vault->list());
|
||||
$this->assertSame(['foo' => $plain], $vault->list(true));
|
||||
$this->assertSame(['foo' => null], array_intersect_key($vault->list(), ['foo' => 123]));
|
||||
$this->assertSame(['foo' => $plain], array_intersect_key($vault->list(true), ['foo' => 123]));
|
||||
|
||||
$this->assertTrue($vault->remove('foo'));
|
||||
$this->assertFalse($vault->remove('foo'));
|
||||
|
||||
unset($_SERVER['foo_SECRET'], $_ENV['foo_SECRET']);
|
||||
unset($_SERVER['foo'], $_ENV['foo']);
|
||||
(new Dotenv(false))->load($this->envFile);
|
||||
|
||||
$this->assertSame([], $vault->list());
|
||||
$this->assertArrayNotHasKey('foo', $vault->list());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user