aboutsummaryrefslogtreecommitdiff
path: root/cmd/easyca/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/easyca/main.go')
-rw-r--r--cmd/easyca/main.go165
1 files changed, 165 insertions, 0 deletions
diff --git a/cmd/easyca/main.go b/cmd/easyca/main.go
new file mode 100644
index 0000000..4a16172
--- /dev/null
+++ b/cmd/easyca/main.go
@@ -0,0 +1,165 @@
+package main
+
+import (
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "log"
+ "net"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/codegangsta/cli"
+ "github.com/jeremy-clerc/easyca/pkg/easyca"
+)
+
+// https://access.redhat.com/documentation/en-US/Red_Hat_Certificate_System/8.0/html/Admin_Guide/Standard_X.509_v3_Certificate_Extensions.html
+// B.3.8. keyUsage
+
+func initPki(c *cli.Context) {
+ log.Print("generating new pki structure")
+ err := os.MkdirAll(filepath.Join(c.GlobalString("root"), "private"), 0755)
+ if err != nil {
+ log.Fatalf("creating pki structure %v", err)
+ }
+}
+
+func createBundle(c *cli.Context) {
+ if !c.Args().Present() {
+ cli.ShowSubcommandHelp(c)
+ log.Fatalf("Usage: %v name (common name defaults to name, use --cn and "+
+ "different name if you need multiple certs for same cn)", c.Command.FullName())
+ }
+
+ var filename string
+ commonName := strings.Join(c.Args()[:], " ")
+
+ if len(c.String("filename")) > 0 {
+ filename = c.String("filename")
+ } else {
+ filename = strings.Replace(commonName, " ", "_", -1)
+ filename = strings.Replace(filename, "*", "wildcard", -1)
+ }
+
+ template := &x509.Certificate{
+ Subject: pkix.Name{
+ CommonName: commonName,
+ Organization: c.StringSlice("organization"),
+ Locality: c.StringSlice("locality"),
+ Country: c.StringSlice("country"),
+ Province: c.StringSlice("province"),
+ },
+ NotAfter: time.Now().AddDate(0, 0, c.Int("expire")),
+ }
+
+ if c.Bool("ca") {
+ template.IsCA = true
+ filename = "ca"
+ } else if c.Bool("client") {
+ template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
+ template.EmailAddresses = c.StringSlice("email")
+ } else {
+ // We default to server
+ template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
+
+ IPs := make([]net.IP, 0, len(c.StringSlice("ip")))
+ for _, ipStr := range c.StringSlice("ip") {
+ if i := net.ParseIP(ipStr); i != nil {
+ IPs = append(IPs, i)
+ }
+ }
+ template.IPAddresses = IPs
+ template.DNSNames = c.StringSlice("dns")
+ }
+ err := easyca.GenerateCertifcate(c.GlobalString("root"), filename, template)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func parseArgs() {
+ app := cli.NewApp()
+ app.Name = "easypki"
+ app.Usage = "Manage pki"
+ app.Author = "Jeremy Clerc"
+ app.Email = "jeremy@clerc.io"
+ app.Version = "0.0.1"
+
+ app.Flags = []cli.Flag{
+ cli.StringFlag{
+ Name: "root",
+ Value: filepath.Join(os.Getenv("PWD"), "pki_auto_generated_dir"),
+ Usage: "path to pki root directory",
+ EnvVar: "PKI_ROOT",
+ },
+ }
+ app.Commands = []cli.Command{
+ {
+ Name: "init",
+ Usage: "create directory structure",
+ Action: initPki,
+ },
+ {
+ Name: "create",
+ Usage: "create COMMON NAME",
+ Description: "create private key + cert signed by CA",
+ Action: createBundle,
+ Flags: []cli.Flag{
+ cli.BoolFlag{
+ Name: "ca",
+ Usage: "certificate authority",
+ },
+ cli.BoolFlag{
+ Name: "client",
+ Usage: "generate a client certificate (default is server)",
+ },
+ cli.IntFlag{
+ Name: "expire",
+ Usage: "expiration limit in days",
+ Value: 365,
+ },
+ cli.StringFlag{
+ Name: "filename",
+ Usage: "filename for bundle, use when you generate multiple certs for same cn",
+ },
+ cli.StringSliceFlag{
+ Name: "organization",
+ EnvVar: "PKI_ORGANIZATION",
+ },
+ cli.StringSliceFlag{
+ Name: "locality",
+ EnvVar: "PKI_LOCALITY",
+ },
+ cli.StringSliceFlag{
+ Name: "country",
+ EnvVar: "PKI_COUNTRY",
+ Usage: "Country name, 2 letter code",
+ },
+ cli.StringSliceFlag{
+ Name: "province",
+ Usage: "province/state",
+ EnvVar: "PKI_PROVINCE",
+ },
+ cli.StringSliceFlag{
+ Name: "dns, d",
+ Usage: "dns alt names",
+ },
+ cli.StringSliceFlag{
+ Name: "ip, i",
+ Usage: "IP alt names",
+ },
+ cli.StringSliceFlag{
+ Name: "email, e",
+ Usage: "Email alt names",
+ },
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+
+func main() {
+ parseArgs()
+}