print.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package main
  2. import (
  3. "encoding/json"
  4. "flag"
  5. "fmt"
  6. "io"
  7. "os"
  8. "strings"
  9. "github.com/skip2/go-qrcode"
  10. "github.com/slackhq/nebula/cert"
  11. )
  12. type printFlags struct {
  13. set *flag.FlagSet
  14. json *bool
  15. outQRPath *string
  16. path *string
  17. }
  18. func newPrintFlags() *printFlags {
  19. pf := printFlags{set: flag.NewFlagSet("print", flag.ContinueOnError)}
  20. pf.set.Usage = func() {}
  21. pf.json = pf.set.Bool("json", false, "Optional: outputs certificates in json format")
  22. pf.outQRPath = pf.set.String("out-qr", "", "Optional: output a qr code image (png) of the certificate")
  23. pf.path = pf.set.String("path", "", "Required: path to the certificate")
  24. return &pf
  25. }
  26. func printCert(args []string, out io.Writer, errOut io.Writer) error {
  27. pf := newPrintFlags()
  28. err := pf.set.Parse(args)
  29. if err != nil {
  30. return err
  31. }
  32. if err := mustFlagString("path", pf.path); err != nil {
  33. return err
  34. }
  35. var claims ioClaims
  36. if err := reserveInputs(&claims, "path", *pf.path); err != nil {
  37. return err
  38. }
  39. if err := reserveOutputs(&claims, "out-qr", *pf.outQRPath); err != nil {
  40. return err
  41. }
  42. rawCert, err := readInput("path", *pf.path, &claims)
  43. if err != nil {
  44. return fmt.Errorf("unable to read cert; %s", err)
  45. }
  46. // When the QR is going to stdout, suppress the human-readable text/json
  47. // output so the binary stream is not contaminated.
  48. qrToStdout := isStdio(*pf.outQRPath)
  49. var c cert.Certificate
  50. var qrBytes []byte
  51. part := 0
  52. var jsonCerts []cert.Certificate
  53. for {
  54. c, rawCert, err = cert.UnmarshalCertificateFromPEM(rawCert)
  55. if err != nil {
  56. return fmt.Errorf("error while unmarshaling cert: %s", err)
  57. }
  58. if !qrToStdout {
  59. if *pf.json {
  60. jsonCerts = append(jsonCerts, c)
  61. } else {
  62. _, _ = out.Write([]byte(c.String()))
  63. _, _ = out.Write([]byte("\n"))
  64. }
  65. }
  66. if *pf.outQRPath != "" {
  67. b, err := c.MarshalPEM()
  68. if err != nil {
  69. return fmt.Errorf("error while marshalling cert to PEM: %s", err)
  70. }
  71. qrBytes = append(qrBytes, b...)
  72. }
  73. if rawCert == nil || len(rawCert) == 0 || strings.TrimSpace(string(rawCert)) == "" {
  74. break
  75. }
  76. part++
  77. }
  78. if *pf.json && !qrToStdout {
  79. b, _ := json.Marshal(jsonCerts)
  80. _, _ = out.Write(b)
  81. _, _ = out.Write([]byte("\n"))
  82. }
  83. if *pf.outQRPath != "" {
  84. b, err := qrcode.Encode(string(qrBytes), qrcode.Medium, -5)
  85. if err != nil {
  86. return fmt.Errorf("error while generating qr code: %s", err)
  87. }
  88. err = writeOutput(*pf.outQRPath, b, 0600, out)
  89. if err != nil {
  90. return fmt.Errorf("error while writing out-qr: %s", err)
  91. }
  92. }
  93. return nil
  94. }
  95. func printSummary() string {
  96. return "print <flags>: prints details about a certificate"
  97. }
  98. func printHelp(out io.Writer) {
  99. pf := newPrintFlags()
  100. out.Write([]byte("Usage of " + os.Args[0] + " " + printSummary() + "\n"))
  101. out.Write([]byte(stdioHelpText))
  102. pf.set.SetOutput(out)
  103. pf.set.PrintDefaults()
  104. }