1
0

verify.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package main
  2. import (
  3. "errors"
  4. "flag"
  5. "fmt"
  6. "io"
  7. "os"
  8. "time"
  9. "github.com/slackhq/nebula/cert"
  10. )
  11. type verifyFlags struct {
  12. set *flag.FlagSet
  13. caPath *string
  14. certPath *string
  15. }
  16. func newVerifyFlags() *verifyFlags {
  17. vf := verifyFlags{set: flag.NewFlagSet("verify", flag.ContinueOnError)}
  18. vf.set.Usage = func() {}
  19. vf.caPath = vf.set.String("ca", "", "Required: path to a file containing one or more ca certificates")
  20. vf.certPath = vf.set.String("crt", "", "Required: path to a file containing a single certificate")
  21. return &vf
  22. }
  23. func verify(args []string, out io.Writer, errOut io.Writer) error {
  24. vf := newVerifyFlags()
  25. err := vf.set.Parse(args)
  26. if err != nil {
  27. return err
  28. }
  29. if err := mustFlagString("ca", vf.caPath); err != nil {
  30. return err
  31. }
  32. if err := mustFlagString("crt", vf.certPath); err != nil {
  33. return err
  34. }
  35. var claims ioClaims
  36. if err := reserveInputs(&claims,
  37. "ca", *vf.caPath,
  38. "crt", *vf.certPath,
  39. ); err != nil {
  40. return err
  41. }
  42. caReader, err := openInput("ca", *vf.caPath, &claims)
  43. if err != nil {
  44. return fmt.Errorf("error while reading ca: %w", err)
  45. }
  46. defer caReader.Close()
  47. caPool, err := cert.NewCAPoolFromPEMReader(caReader)
  48. if err != nil && !errors.Is(err, cert.ErrExpired) {
  49. return fmt.Errorf("error while adding ca cert to pool: %w", err)
  50. }
  51. rawCert, err := readInput("crt", *vf.certPath, &claims)
  52. if err != nil {
  53. return fmt.Errorf("unable to read crt: %w", err)
  54. }
  55. var errs []error
  56. for {
  57. if len(rawCert) == 0 {
  58. break
  59. }
  60. c, extra, err := cert.UnmarshalCertificateFromPEM(rawCert)
  61. if err != nil {
  62. return fmt.Errorf("error while parsing crt: %w", err)
  63. }
  64. rawCert = extra
  65. _, err = caPool.VerifyCertificate(time.Now(), c)
  66. if err != nil {
  67. switch {
  68. case errors.Is(err, cert.ErrCaNotFound):
  69. errs = append(errs, fmt.Errorf("error while verifying certificate v%d %s with issuer %s: %w", c.Version(), c.Name(), c.Issuer(), err))
  70. default:
  71. errs = append(errs, fmt.Errorf("error while verifying certificate %+v: %w", c, err))
  72. }
  73. }
  74. }
  75. return errors.Join(errs...)
  76. }
  77. func verifySummary() string {
  78. return "verify <flags>: verifies a certificate isn't expired and was signed by a trusted authority."
  79. }
  80. func verifyHelp(out io.Writer) {
  81. vf := newVerifyFlags()
  82. _, _ = out.Write([]byte("Usage of " + os.Args[0] + " " + verifySummary() + "\n"))
  83. _, _ = out.Write([]byte(stdioHelpText))
  84. vf.set.SetOutput(out)
  85. vf.set.PrintDefaults()
  86. }