vendor/symfony/framework-bundle/Command/SecretsSetCommand.php line 40

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Bundle\FrameworkBundle\Command;
  11. use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
  12. use Symfony\Component\Console\Command\Command;
  13. use Symfony\Component\Console\Completion\CompletionInput;
  14. use Symfony\Component\Console\Completion\CompletionSuggestions;
  15. use Symfony\Component\Console\Input\InputArgument;
  16. use Symfony\Component\Console\Input\InputInterface;
  17. use Symfony\Component\Console\Input\InputOption;
  18. use Symfony\Component\Console\Output\ConsoleOutputInterface;
  19. use Symfony\Component\Console\Output\OutputInterface;
  20. use Symfony\Component\Console\Style\SymfonyStyle;
  21. /**
  22.  * @author Tobias Schultze <http://tobion.de>
  23.  * @author Jérémy Derussé <jeremy@derusse.com>
  24.  * @author Nicolas Grekas <p@tchwork.com>
  25.  *
  26.  * @internal
  27.  */
  28. final class SecretsSetCommand extends Command
  29. {
  30.     protected static $defaultName 'secrets:set';
  31.     protected static $defaultDescription 'Set a secret in the vault';
  32.     private $vault;
  33.     private $localVault;
  34.     public function __construct(AbstractVault $vaultAbstractVault $localVault null)
  35.     {
  36.         $this->vault $vault;
  37.         $this->localVault $localVault;
  38.         parent::__construct();
  39.     }
  40.     protected function configure()
  41.     {
  42.         $this
  43.             ->setDescription(self::$defaultDescription)
  44.             ->addArgument('name'InputArgument::REQUIRED'The name of the secret')
  45.             ->addArgument('file'InputArgument::OPTIONAL'A file where to read the secret from or "-" for reading from STDIN')
  46.             ->addOption('local''l'InputOption::VALUE_NONE'Update the local vault.')
  47.             ->addOption('random''r'InputOption::VALUE_OPTIONAL'Generate a random value.'false)
  48.             ->setHelp(<<<'EOF'
  49. The <info>%command.name%</info> command stores a secret in the vault.
  50.     <info>%command.full_name% <name></info>
  51. To reference secrets in services.yaml or any other config
  52. files, use <info>"%env(<name>)%"</info>.
  53. By default, the secret value should be entered interactively.
  54. Alternatively, provide a file where to read the secret from:
  55.     <info>php %command.full_name% <name> filename</info>
  56. Use "-" as a file name to read from STDIN:
  57.     <info>cat filename | php %command.full_name% <name> -</info>
  58. Use <info>--local</info> to override secrets for local needs.
  59. EOF
  60.             )
  61.         ;
  62.     }
  63.     protected function execute(InputInterface $inputOutputInterface $output): int
  64.     {
  65.         $errOutput $output instanceof ConsoleOutputInterface $output->getErrorOutput() : $output;
  66.         $io = new SymfonyStyle($input$errOutput);
  67.         $name $input->getArgument('name');
  68.         $vault $input->getOption('local') ? $this->localVault $this->vault;
  69.         if (null === $vault) {
  70.             $io->error('The local vault is disabled.');
  71.             return 1;
  72.         }
  73.         if ($this->localVault === $vault && !\array_key_exists($name$this->vault->list())) {
  74.             $io->error(sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.'$name));
  75.             return 1;
  76.         }
  77.         if ($random $input->getOption('random') ?? 16) {
  78.             $value strtr(substr(base64_encode(random_bytes($random)), 0$random), '+/''-_');
  79.         } elseif (!$file $input->getArgument('file')) {
  80.             $value $io->askHidden('Please type the secret value');
  81.             if (null === $value) {
  82.                 $io->warning('No value provided: using empty string');
  83.                 $value '';
  84.             }
  85.         } elseif ('-' === $file) {
  86.             $value file_get_contents('php://stdin');
  87.         } elseif (is_file($file) && is_readable($file)) {
  88.             $value file_get_contents($file);
  89.         } elseif (!is_file($file)) {
  90.             throw new \InvalidArgumentException(sprintf('File not found: "%s".'$file));
  91.         } elseif (!is_readable($file)) {
  92.             throw new \InvalidArgumentException(sprintf('File is not readable: "%s".'$file));
  93.         }
  94.         if ($vault->generateKeys()) {
  95.             $io->success($vault->getLastMessage());
  96.             if ($this->vault === $vault) {
  97.                 $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️');
  98.             }
  99.         }
  100.         $vault->seal($name$value);
  101.         $io->success($vault->getLastMessage() ?? 'Secret was successfully stored in the vault.');
  102.         if ($random) {
  103.             $errOutput->write(' // The generated random value is: <comment>');
  104.             $output->write($value);
  105.             $errOutput->writeln('</comment>');
  106.             $io->newLine();
  107.         }
  108.         if ($this->vault === $vault && null !== $this->localVault->reveal($name)) {
  109.             $io->comment('Note that this secret is overridden in the local vault.');
  110.         }
  111.         return 0;
  112.     }
  113.     public function complete(CompletionInput $inputCompletionSuggestions $suggestions): void
  114.     {
  115.         if ($input->mustSuggestArgumentValuesFor('name')) {
  116.             $suggestions->suggestValues(array_keys($this->vault->list(false)));
  117.         }
  118.     }
  119. }