tcms-vault-key 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/env perl
  2. use v5.36;
  3. use re '/aa';
  4. use FindBin::libs;
  5. use Crypt::Misc ();
  6. use Crypt::PRNG ();
  7. use Getopt::Long qw{GetOptions};
  8. use Trog::Vault ();
  9. =head1 SYNOPSIS
  10. Make the key that seals this installation's stored secrets, and say where to put
  11. it.
  12. =head2 USAGE
  13. bin/tcms-vault-key # print a key and the commands to install it
  14. bin/tcms-vault-key --file # write config/secrets.key instead
  15. =head2 WHAT THIS IS
  16. Every secret a user stores through /secrets is encrypted under a key derived
  17. from this one. It is not in the database, which is the whole point: without it
  18. config/auth.db is ciphertext. Losing it loses every stored secret, and there is
  19. no way around that -- they go back to typing the password, which is what they
  20. did before.
  21. There is one key per installation, and it does not need rotating on a schedule.
  22. If you do replace it, everything sealed under the old one stops opening and says
  23. so rather than presenting as corruption; the fix is for each user to store
  24. theirs again.
  25. =head2 WHERE TO PUT IT
  26. In systemd's credential store, which is what the default output tells you how to
  27. do. tPSGI's unit imports it from there and hands it to tCMS in the environment,
  28. tCMS takes it back out of the environment as it loads, and it never touches a
  29. disk anywhere on the way. Encrypted with systemd-creds it is also sealed to
  30. this machine, so the file is useless if it walks.
  31. --file is the fallback for a machine that is not running systemd. It writes
  32. config/secrets.key, mode 600, and that is genuinely weaker: a key beside the
  33. database it protects is a key in the same backup as the database it protects.
  34. =head2 CAVEATS
  35. Prints a key to your terminal, which is a place keys end up in scrollback. The
  36. default output is meant to be piped rather than read.
  37. =cut
  38. my ( $file, $help );
  39. GetOptions(
  40. 'file' => \$file,
  41. 'help' => \$help,
  42. ) or exit 2;
  43. if ($help) {
  44. print "Usage: bin/tcms-vault-key [--file]\n";
  45. exit 0;
  46. }
  47. my $key = Crypt::Misc::encode_b64( Crypt::PRNG::random_bytes(32) );
  48. if ($file) {
  49. # Printed and exited rather than died: Carp::Always is in the dependency
  50. # chain, and refusing to clobber a key is not a crash.
  51. if ( -e $Trog::Vault::key_file ) { ## no critic (ProhibitFiletest_e) -- refusing to overwrite the one thing that cannot be regenerated
  52. print STDERR "There is already a key at $Trog::Vault::key_file. Move it out of the way if you really mean to replace it, and read what that costs first: perldoc bin/tcms-vault-key\n";
  53. exit 2;
  54. }
  55. open( my $fh, '>', $Trog::Vault::key_file ) or die "Could not write $Trog::Vault::key_file: $!\n";
  56. print {$fh} "$key\n";
  57. close($fh);
  58. chmod( oct('600'), $Trog::Vault::key_file ) or die "Could not chmod $Trog::Vault::key_file: $!\n";
  59. print "Wrote $Trog::Vault::key_file. Restart tCMS to pick it up.\n";
  60. print "This is the weaker of the two places to keep it: see perldoc bin/tcms-vault-key.\n";
  61. exit 0;
  62. }
  63. print <<"COMMANDS";
  64. A new vault key. Put it in systemd's credential store, sealed to this machine:
  65. echo '$key' | sudo systemd-creds encrypt --name=tcms-vault - /etc/credstore.encrypted/tcms-vault
  66. ...or unsealed, if this machine has no TPM:
  67. echo '$key' | sudo tee /etc/credstore/tcms-vault > /dev/null
  68. sudo chmod 600 /etc/credstore/tcms-vault
  69. Then restart the service. tPSGI's unit imports it and hands it over before it
  70. chroots; see the Service configuration section of its Readme.
  71. Losing this key loses every secret stored under it, and it is not in any backup
  72. you take of tCMS, which is the point. Keep it wherever you keep the things you
  73. cannot regenerate.
  74. COMMANDS