github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/command/tls/ca/create/tls_ca_create.go (about) 1 package create 2 3 import ( 4 "flag" 5 "fmt" 6 "os" 7 8 "github.com/hashicorp/consul/command/flags" 9 "github.com/hashicorp/consul/command/tls" 10 "github.com/mitchellh/cli" 11 ) 12 13 func New(ui cli.Ui) *cmd { 14 c := &cmd{UI: ui} 15 c.init() 16 return c 17 } 18 19 type cmd struct { 20 UI cli.Ui 21 flags *flag.FlagSet 22 help string 23 days int 24 domain string 25 constraint bool 26 additionalConstraints flags.AppendSliceValue 27 } 28 29 func (c *cmd) init() { 30 c.flags = flag.NewFlagSet("", flag.ContinueOnError) 31 // TODO: perhaps add a -years arg to better capture user intent given that leap years are a thing 32 c.flags.IntVar(&c.days, "days", 1825, "Provide number of days the CA is valid for from now on. Defaults to 5 years.") 33 c.flags.BoolVar(&c.constraint, "name-constraint", false, "Add name constraints for the CA. Results in rejecting "+ 34 "certificates for other DNS than specified. If turned on localhost and -domain will be added to the allowed "+ 35 "DNS. If the UI is going to be served over HTTPS its DNS has to be added with -additional-constraint. It is not "+ 36 "possible to add that after the fact! Defaults to false.") 37 c.flags.StringVar(&c.domain, "domain", "consul", "Domain of consul cluster. Only used in combination with -name-constraint. Defaults to consul.") 38 c.flags.Var(&c.additionalConstraints, "additional-name-constraint", "Add name constraints for the CA. Results in rejecting certificates "+ 39 "for other DNS than specified. Can be used multiple times. Only used in combination with -name-constraint.") 40 c.help = flags.Usage(help, c.flags) 41 } 42 43 func (c *cmd) Run(args []string) int { 44 if err := c.flags.Parse(args); err != nil { 45 if err == flag.ErrHelp { 46 return 0 47 } 48 c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err)) 49 return 1 50 } 51 52 certFileName := fmt.Sprintf("%s-agent-ca.pem", c.domain) 53 pkFileName := fmt.Sprintf("%s-agent-ca-key.pem", c.domain) 54 55 if !(tls.FileDoesNotExist(certFileName)) { 56 c.UI.Error(certFileName + " already exists.") 57 return 1 58 } 59 if !(tls.FileDoesNotExist(pkFileName)) { 60 c.UI.Error(pkFileName + " already exists.") 61 return 1 62 } 63 64 sn, err := tls.GenerateSerialNumber() 65 if err != nil { 66 c.UI.Error(err.Error()) 67 return 1 68 } 69 s, pk, err := tls.GeneratePrivateKey() 70 if err != nil { 71 c.UI.Error(err.Error()) 72 } 73 constraints := []string{} 74 if c.constraint { 75 constraints = append(c.additionalConstraints, []string{c.domain, "localhost"}...) 76 } 77 ca, err := tls.GenerateCA(s, sn, c.days, constraints) 78 if err != nil { 79 c.UI.Error(err.Error()) 80 } 81 caFile, err := os.Create(certFileName) 82 if err != nil { 83 c.UI.Error(err.Error()) 84 } 85 caFile.WriteString(ca) 86 c.UI.Output("==> Saved " + certFileName) 87 pkFile, err := os.Create(pkFileName) 88 if err != nil { 89 c.UI.Error(err.Error()) 90 } 91 pkFile.WriteString(pk) 92 c.UI.Output("==> Saved " + pkFileName) 93 94 return 0 95 } 96 97 func (c *cmd) Synopsis() string { 98 return synopsis 99 } 100 101 func (c *cmd) Help() string { 102 return c.help 103 } 104 105 const synopsis = "Create a new consul CA" 106 const help = ` 107 Usage: consul tls ca create [options] 108 109 Create a new consul CA: 110 111 $ consul tls ca create 112 ==> saved consul-agent-ca.pem 113 ==> saved consul-agent-ca-key.pem 114 `