verify.go 2.3 KB

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