package ca import ( "fmt" "os" "time" "github.com/spf13/cobra" ) var ( dir string outputFilename string // signCommonFlags refers to these validFrom string validUntil string // createCACommonFlags refers to these bits int excludedDomains []string excludedIPs []string maxPathLen int permittedDomains []string permittedIPs []string ) // Register the "keygen" subcommand. func Register(root *cobra.Command) { caCmd := &cobra.Command{ Use: "ca", Short: "Certificate authority creation and operation", } caCmd.PersistentFlags().StringVarP(&dir, "dir", "d", "", "Directory holding CA") caCmd.MarkPersistentFlagRequired("dir") root.AddCommand(caCmd) // init command cmd := &cobra.Command{ Use: "init ", Short: "Initialise a brand-new certificate authority", Args: cobra.ExactArgs(1), Run: Init, } createCACommonFlags(cmd) signCommonFlags(cmd) caCmd.AddCommand(cmd) // sign command cmd = &cobra.Command{ Use: "sign csr.pem", Short: "Sign one or more CSRs", Args: cobra.ExactArgs(1), Run: Sign, } cmd.Flags().StringVarP(&outputFilename, "output", "o", "", "Name of output file (default stdout).") signCommonFlags(cmd) caCmd.AddCommand(cmd) // intermediate command cmd = &cobra.Command{ Use: "intermediate ", Short: "Using an existing CA, create a new intermediate CA", Args: cobra.ExactArgs(2), Run: Intermediate, } createCACommonFlags(cmd) signCommonFlags(cmd) caCmd.AddCommand(cmd) } func createCACommonFlags(cmd *cobra.Command) { cmd.Flags().IntVarP(&bits, "bits", "b", 3072, "Key size in bits") cmd.Flags().StringSliceVar(&excludedDomains, "exclude-domain", nil, "Do not allow certs to be issued for named domain. Multiple may be specified") cmd.Flags().StringSliceVar(&excludedIPs, "exclude-cidr", nil, "Do not allow certs to be issued for given IP range. Multiple may be specified") cmd.Flags().IntVar(&maxPathLen, "max-path-len", -1, "Maximum path length (whether any further CAs may be issued)") cmd.Flags().StringSliceVar(&permittedDomains, "permit-domain", nil, "Allow certs to be issued only for named domain. Multiple may be specified") cmd.Flags().StringSliceVar(&permittedIPs, "permit-cidr", nil, "Allow certs to be issued only for given IP range. Multiple may be specified") } func signCommonFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&validFrom, "valid-from", "", "RFC3339-format timestamp for start of cert validity") cmd.Flags().StringVar(&validUntil, "valid-until", "", "RFC3339-format timestamp for end of cert validity") } func signingDates(defaultDuration time.Duration) (from, until time.Time) { var err error if validFrom == "" { from = time.Now().Add(-2 * time.Hour) } else { from, err = time.Parse(time.RFC3339, validFrom) if err != nil { fmt.Fprintln(os.Stderr, "--valid-from %s: not a valid RFC3339-format timestamp\n") os.Exit(1) } } if validUntil == "" { until = time.Now().Add(defaultDuration) } else { until, err = time.Parse(time.RFC3339, validUntil) if err != nil { fmt.Fprintln(os.Stderr, "--valid-until %s: not a valid RFC3339-format timestamp\n") os.Exit(1) } } return }