InitSecureRandomCommand.php 3.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <?php
  2. namespace JMS\SecurityExtraBundle\Command;
  3. use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
  4. use Doctrine\DBAL\Types\Type;
  5. use Symfony\Component\Console\Input\InputOption;
  6. use Doctrine\DBAL\Schema\Comparator;
  7. use Symfony\Component\Console\Output\OutputInterface;
  8. use Symfony\Component\Console\Input\InputInterface;
  9. use Symfony\Component\Console\Input\InputArgument;
  10. /**
  11. * Initializes the CSPRNG fallback algorithm.
  12. *
  13. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  14. */
  15. class InitSecureRandomCommand extends ContainerAwareCommand
  16. {
  17. protected function configure()
  18. {
  19. $this->setName('init:jms-secure-random');
  20. $this->addArgument('phrase', InputArgument::REQUIRED, 'Whatever comes to your mind right now. You do not need to remember it, it does not need to be cryptic, or long, and it will not be stored in a decipherable way. One restriction however, you should not let this be generated in an automated fashion.');
  21. $this->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Whether the SQL should be dumped.');
  22. $this->addOption('force', null, InputOption::VALUE_NONE, 'Whether the SQL should be executed.');
  23. }
  24. protected function execute(InputInterface $input, OutputInterface $output)
  25. {
  26. $seed = base64_encode(hash('sha512', $input->getArgument('phrase'), true));
  27. if ($this->getContainer()->has('security.util.secure_random_seed_provider')) {
  28. $this->getContainer()->get('security.util.secure_random_seed_provider')->updateSeed($seed);
  29. $output->writeln('The CSPRNG has been initialized successfully.');
  30. } elseif ($this->getContainer()->has('security.util.secure_random_connection')) {
  31. if ($input->getOption('force') === $input->getOption('dump-sql')) {
  32. throw new \InvalidArgumentException('This command needs to be run with one of these options: --force, or --dump-sql');
  33. }
  34. $con = $this->getContainer()->get('security.util.secure_random_connection');
  35. $schema = $this->getContainer()->get('security.util.secure_random_schema');
  36. $comparator = new Comparator();
  37. $execute = $input->getOption('force');
  38. foreach ($comparator->compare($con->getSchemaManager()->createSchema(), $schema)->toSaveSql($con->getDatabasePlatform()) as $sql) {
  39. if ($execute) {
  40. $con->executeQuery($sql);
  41. } else {
  42. $output->writeln($sql);
  43. }
  44. }
  45. $table = $this->getContainer()->getParameter('security.util.secure_random_table');
  46. $sql = $con->getDatabasePlatform()->getTruncateTableSQL($table);
  47. if ($execute) {
  48. $con->executeQuery($sql);
  49. } else {
  50. $output->writeln($sql);
  51. }
  52. $sql = "INSERT INTO {$table} VALUES (:seed, :updatedAt)";
  53. if ($execute) {
  54. $con->executeQuery($sql, array(
  55. ':seed' => $seed,
  56. ':updatedAt' => new \DateTime(),
  57. ), array(
  58. ':updatedAt' => Type::DATETIME,
  59. ));
  60. } else {
  61. $output->writeln($sql);
  62. }
  63. if ($execute) {
  64. $output->writeln('The CSPRNG has been initialized successfully.');
  65. }
  66. } else {
  67. throw new \RuntimeException('No seed provider has been configured under path "security.util.secure_random".');
  68. }
  69. }
  70. }