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

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