diff --git a/certificate.go b/certificate.go index d934e9c..596341a 100644 --- a/certificate.go +++ b/certificate.go @@ -10,6 +10,7 @@ type ( IsCA bool Duration time.Duration + Created time.Time PrivateKey ResourceName Serial ResourceName diff --git a/cmd/pkiadm/ca.go b/cmd/pkiadm/ca.go index 5978f10..b318da8 100644 --- a/cmd/pkiadm/ca.go +++ b/cmd/pkiadm/ca.go @@ -32,16 +32,25 @@ func createCA(args []string, client *pkiadm.Client) error { func setCA(args []string, client *pkiadm.Client) error { fs := flag.NewFlagSet("pkiadm set-public", flag.ExitOnError) id := fs.String("id", "", "the id of the CA to change") - pk := fs.String("private-key", "", "the id of the new private key to use for CA generation") + ct := fs.String("type", "local", "the type of CA to create (local, LetsEncrypt)") + cert := fs.String("certificate", "", "the id of the certificate to use for signing") fs.Parse(args) - if !fs.Lookup("private-key").Changed { - return nil + fieldList := []string{} + for _, field := range []string{"certificate", "type"} { + flag := fs.Lookup(field) + if flag.Changed { + fieldList = append(fieldList, field) + } } - caName := pkiadm.ResourceName{ID: *pk, Type: pkiadm.RTPrivateKey} + caType := pkiadm.StringToCAType(*ct) + if caType == pkiadm.CAUnknown { + return errors.New("unknown ca type") + } + caName := pkiadm.ResourceName{ID: *cert, Type: pkiadm.RTCertificate} if err := client.SetCA( pkiadm.CA{ID: *id, Certificate: caName}, - []string{"private-key"}, + fieldList, ); err != nil { return errors.Wrap(err, "Could not change CA") } diff --git a/cmd/pkiadm/certificate.go b/cmd/pkiadm/certificate.go index 0624684..a7c5836 100644 --- a/cmd/pkiadm/certificate.go +++ b/cmd/pkiadm/certificate.go @@ -88,9 +88,9 @@ func listCertificate(args []string, client *pkiadm.Client) error { return nil } out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight) - fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n", "id", "private", "csr", "ca", "serial", "duration", "self-signed") + fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n", "id", "private", "csr", "ca", "serial", "created", "duration", "self-signed") for _, cert := range certs { - fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%t\t\n", cert.ID, cert.PrivateKey.ID, cert.CSR.ID, cert.CA.ID, cert.Serial.ID, cert.Duration, cert.IsCA) + fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%t\t\n", cert.ID, cert.PrivateKey.ID, cert.CSR.ID, cert.CA.ID, cert.Serial.ID, cert.Created, cert.Duration, cert.IsCA) } out.Flush() @@ -111,6 +111,7 @@ func showCertificate(args []string, client *pkiadm.Client) error { fmt.Fprintf(out, "csr:\t%s\n", cert.CSR.ID) fmt.Fprintf(out, "ca:\t%s\n", cert.CA.ID) fmt.Fprintf(out, "serial:\t%s\n", cert.Serial.ID) + fmt.Fprintf(out, "created:\t%s\n", cert.Created) fmt.Fprintf(out, "duration:\t%s\n", cert.Duration) fmt.Fprintf(out, "self-signed:\t%t\n", cert.IsCA) fmt.Fprintf(out, "checksum:\t%s\n", base64.StdEncoding.EncodeToString(cert.Checksum)) diff --git a/cmd/pkiadmd/ca.go b/cmd/pkiadmd/ca.go index fa39946..db6b8d5 100644 --- a/cmd/pkiadmd/ca.go +++ b/cmd/pkiadmd/ca.go @@ -1,6 +1,8 @@ package main import ( + "log" + "github.com/gibheer/pki" "github.com/gibheer/pkiadm" ) @@ -33,25 +35,51 @@ func NewCA(id string, caType pkiadm.CAType, cert pkiadm.ResourceName) (*CA, erro } // Sign the certificate sign request with this CA -func (ca *CA) Sign(lookup *Storage, csr *pki.CertificateRequest, opts pki.CertificateOptions) (*pki.Certificate, error) { - caCertDef, err := lookup.GetCertificate(ca.Certificate) +func (ca *CA) Sign(lookup *Storage, csr pkiadm.ResourceName, opts pki.CertificateOptions) (*pki.Certificate, error) { + var caCert *pki.Certificate + var pk pki.PrivateKey + var caCertDef *Certificate + + csrRes, err := lookup.GetCSR(csr) if err != nil { return nil, err } - caCert, err := caCertDef.GetCertificate() - if err != nil { - return nil, err - } - pkDef, err := lookup.GetPrivateKey(caCertDef.PrivateKey) - if err != nil { - return nil, err - } - pk, err := pkDef.GetKey() + csrIns, err := csrRes.GetCSR() if err != nil { return nil, err } - return csr.ToCertificate(pk, opts, caCert) + if ca == CASelfSign { + pkDef, err := lookup.GetPrivateKey(csrRes.PrivateKey) + if err != nil { + return nil, err + } + pk, err = pkDef.GetKey() + if err != nil { + return nil, err + } + caCertDef = &Certificate{ID: "self-signed"} + } else { + caCertDef, err = lookup.GetCertificate(ca.Certificate) + if err != nil { + return nil, err + } + caCert, err = caCertDef.GetCertificate() + if err != nil { + return nil, err + } + pkDef, err := lookup.GetPrivateKey(caCertDef.PrivateKey) + if err != nil { + return nil, err + } + pk, err = pkDef.GetKey() + if err != nil { + return nil, err + } + } + + log.Printf("ca '%s' signing csr '%s' using cert '%s'", ca.ID, csr.ID, caCertDef.ID) + return csrIns.ToCertificate(pk, opts, caCert) } // Return the unique ResourceName @@ -135,7 +163,7 @@ func (s *Server) ShowCA(inCA pkiadm.CA, res *pkiadm.ResultCA) error { ca, err := s.storage.GetCA(pkiadm.ResourceName{ID: inCA.ID, Type: pkiadm.RTCA}) if err != nil { - res.Result.SetError(err, "Could not find private key '%s'", inCA.ID) + res.Result.SetError(err, "Could not find CA '%s'", inCA.ID) return nil } res.CAs = []pkiadm.CA{pkiadm.CA{ diff --git a/cmd/pkiadmd/certificate.go b/cmd/pkiadmd/certificate.go index aeba917..db3c400 100644 --- a/cmd/pkiadmd/certificate.go +++ b/cmd/pkiadmd/certificate.go @@ -19,6 +19,7 @@ type ( IsCA bool Duration time.Duration + Created time.Time PrivateKey pkiadm.ResourceName Serial pkiadm.ResourceName @@ -57,14 +58,6 @@ func (c *Certificate) Refresh(lookup *Storage) error { return err } } - csrRes, err := lookup.GetCSR(c.CSR) - if err != nil { - return err - } - csr, err := csrRes.GetCSR() - if err != nil { - return err - } serRes, err := lookup.GetSerial(c.Serial) if err != nil { return err @@ -84,7 +77,7 @@ func (c *Certificate) Refresh(lookup *Storage) error { CALength: 0, // TODO make this an option } //cert, err := csr.ToCertificate(pk, opts, ca) - cert, err := ca.Sign(lookup, csr, opts) + cert, err := ca.Sign(lookup, c.CSR, opts) if err != nil { return err } @@ -92,8 +85,8 @@ func (c *Certificate) Refresh(lookup *Storage) error { if err != nil { return err } - block.Headers = map[string]string{"ID": c.ID} c.Data = pem.EncodeToMemory(&block) + c.Created = time.Now() return nil } @@ -213,6 +206,7 @@ func (s *Server) ShowCertificate(inCert pkiadm.ResourceName, res *pkiadm.ResultC res.Certificates = []pkiadm.Certificate{pkiadm.Certificate{ ID: cert.ID, Duration: cert.Duration, + Created: cert.Created, PrivateKey: cert.PrivateKey, Serial: cert.Serial, CA: cert.CA, @@ -229,6 +223,7 @@ func (s *Server) ListCertificate(filter pkiadm.Filter, res *pkiadm.ResultCertifi res.Certificates = append(res.Certificates, pkiadm.Certificate{ ID: cert.ID, Duration: cert.Duration, + Created: cert.Created, PrivateKey: cert.PrivateKey, Serial: cert.Serial, CA: cert.CA, diff --git a/cmd/pkiadmd/csr.go b/cmd/pkiadmd/csr.go index 25de513..9320f42 100644 --- a/cmd/pkiadmd/csr.go +++ b/cmd/pkiadmd/csr.go @@ -77,7 +77,6 @@ func (c *CSR) Refresh(lookup *Storage) error { if err != nil { return err } - block.Headers = map[string]string{"ID": c.ID} c.Data = pem.EncodeToMemory(&block) return nil } diff --git a/cmd/pkiadmd/location.go b/cmd/pkiadmd/location.go index e82239c..f547826 100644 --- a/cmd/pkiadmd/location.go +++ b/cmd/pkiadmd/location.go @@ -3,6 +3,7 @@ package main import ( "fmt" "io/ioutil" + "log" "os" "os/exec" @@ -59,15 +60,19 @@ func (l *Location) Refresh(lookup *Storage) error { raw = append(raw, output...) } if l.PreCommand != "" { + log.Printf("location '%s' is updating '%s' - pre '%s'", l.ID, l.Path, l.PreCommand) cmd := exec.Command(l.PreCommand, l.Path) if err := cmd.Run(); err != nil { return err } } + log.Printf("location '%s' is updating '%s'", l.ID, l.Path) if err := ioutil.WriteFile(l.Path, raw, 0600); err != nil { + log.Printf("could not write location '%s': %s", l.ID, err) return err } if l.PostCommand != "" { + log.Printf("location '%s' is updating '%s' - post '%s'", l.ID, l.Path, l.PostCommand) cmd := exec.Command(l.PostCommand, l.Path) if err := cmd.Run(); err != nil { return err @@ -132,6 +137,7 @@ func (s *Server) SetLocation(changeset pkiadm.LocationChange, res *pkiadm.Result } } if err := s.storage.Update(locName); err != nil { + log.Printf("could not update location '%s': %s", loc.ID, err) res.SetError(err, "Could not update location '%s'", loc.ID) return nil } diff --git a/cmd/pkiadmd/private_key.go b/cmd/pkiadmd/private_key.go index 4889f2a..51041ce 100644 --- a/cmd/pkiadmd/private_key.go +++ b/cmd/pkiadmd/private_key.go @@ -87,7 +87,6 @@ func (p *PrivateKey) Refresh(_ *Storage) error { if err != nil { return err } - block.Headers = map[string]string{"ID": p.ID} p.Key = pem.EncodeToMemory(&block) return nil } diff --git a/cmd/pkiadmd/public_key.go b/cmd/pkiadmd/public_key.go index 7700458..7e91333 100644 --- a/cmd/pkiadmd/public_key.go +++ b/cmd/pkiadmd/public_key.go @@ -44,7 +44,6 @@ func (p *PublicKey) Refresh(lookup *Storage) error { if err != nil { return err } - block.Headers = map[string]string{"ID": p.ID, "TYPE": p.Type.String()} p.Key = pem.EncodeToMemory(&block) return nil } diff --git a/cmd/pkiadmd/storage.go b/cmd/pkiadmd/storage.go index b3e2015..c8cb6fb 100644 --- a/cmd/pkiadmd/storage.go +++ b/cmd/pkiadmd/storage.go @@ -359,6 +359,7 @@ func (s *Storage) Update(rn pkiadm.ResourceName) error { } for _, dep := range updateOrder { + log.Printf("refreshing resource '%s' because of '%s'", dep.Name(), rn.String()) if err := dep.Refresh(s); err != nil { return err } diff --git a/resourcetype_string.go b/resourcetype_string.go index f9b8cb7..98b8d9c 100644 --- a/resourcetype_string.go +++ b/resourcetype_string.go @@ -20,6 +20,8 @@ func (i ResourceType) String() string { return "serial" case RTLocation: return "location" + case RTCA: + return "CA" case RTUnknown: return "unknown" default: @@ -43,6 +45,8 @@ func StringToResourceType(in string) (ResourceType, error) { return RTSubject, nil case "serial": return RTSerial, nil + case "ca": + return RTCA, nil default: return RTUnknown, fmt.Errorf("unknown resource type") }