From 0dc7d081834672fc5548fb87155e0c8f75d755bc Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 16 Oct 2020 19:11:30 +0300 Subject: [PATCH] Allow user to provide existing CA certificate and key --- pkg/certificate/certificate.go | 23 +++++++++++++++++++---- pkg/certificate/manifest.go | 11 ++++++++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/pkg/certificate/certificate.go b/pkg/certificate/certificate.go index 48f0497..bdf20aa 100644 --- a/pkg/certificate/certificate.go +++ b/pkg/certificate/certificate.go @@ -52,8 +52,9 @@ type Certificate struct { NotAfter *time.Time `yaml:"not_after"` // generated at runtime, not read from yaml - Key crypto.Signer `yaml:"-"` - Cert []byte `yaml:"-"` + Key crypto.Signer `yaml:"-"` + Cert []byte `yaml:"-"` + Generated bool `hash:"-"` } // getKeyUsage converts key usage string representation to x509.KeyUsage @@ -247,6 +248,9 @@ func (c *Certificate) Generate(ca *Certificate) error { c.Cert, err = x509.CreateCertificate(rand.Reader, template, issuerCert, c.Key.Public(), issuerKey) + // Mark the state as valid + c.Generated = true + return err } @@ -311,16 +315,27 @@ func (c *Certificate) Load(srcdir string) error { return err } decoded, _ = pem.Decode(buf) - if decoded == nil || decoded.Type != "PRIVATE KEY" { + if decoded == nil { + return fmt.Errorf("Error while decoding %s", keyFilename) + } + + var key interface{} + if decoded.Type == "PRIVATE KEY" { + key, err = x509.ParsePKCS8PrivateKey(decoded.Bytes) + } else if decoded.Type == "RSA PRIVATE KEY" { + key, err = x509.ParsePKCS1PrivateKey(decoded.Bytes) + } else { return fmt.Errorf("Error while decoding %s", keyFilename) } - key, err := x509.ParsePKCS8PrivateKey(decoded.Bytes) if err != nil { return err } c.Key = key.(crypto.Signer) + // Mark the state as valid + c.Generated = true + return nil } diff --git a/pkg/certificate/manifest.go b/pkg/certificate/manifest.go index 026bf08..19e54cd 100644 --- a/pkg/certificate/manifest.go +++ b/pkg/certificate/manifest.go @@ -67,11 +67,20 @@ func GenerateCertficatesFromManifest(manifestFilename, stateFilename, destinatio allCerts[c.Subject] = &c // compare hash from state file to has of loaded certificate - if state[c.Subject] == c.Hash() { + hash, ok := state[c.Subject] + if hash == c.Hash() { fmt.Printf("No changes: skipping %s\n", c.Filename) continue // continue to next certificate in manifest } + // if certificate is already valid but it did not exist in state file: + // "adopt" the existing certificate like we would have generated it + if c.Generated && !ok { + fmt.Printf("Recognized existing certificate: skipping %s\n", c.Filename) + state[c.Subject] = c.Hash() + continue // continue to next certificate in manifest + } + ca, ok := allCerts[c.Issuer] if c.Issuer != "" && !ok { return fmt.Errorf("Issuer field defined but CA certificate `%s` not found", c.Issuer)