diff --git a/pkg/controller/certificates/sync.go b/pkg/controller/certificates/sync.go index 587b9027e..5e5c941a1 100644 --- a/pkg/controller/certificates/sync.go +++ b/pkg/controller/certificates/sync.go @@ -92,7 +92,7 @@ func (c *Controller) Sync(crt *v1alpha1.Certificate) (err error) { } // grab existing certificate and validate private key - cert, _, err := kube.GetKeyPair(c.client, crt.Namespace, crt.Spec.SecretName) + cert, err := kube.SecretTLSCert(c.secretLister, crt.Namespace, crt.Spec.SecretName) if err != nil { s := messageErrorCheckCertificate + err.Error() @@ -155,7 +155,7 @@ func (c *Controller) scheduleRenewal(crt *v1alpha1.Certificate) { return } - cert, _, err := kube.GetKeyPair(c.client, crt.Namespace, crt.Spec.SecretName) + cert, err := kube.SecretTLSCert(c.secretLister, crt.Namespace, crt.Spec.SecretName) if err != nil { runtime.HandleError(fmt.Errorf("[%s/%s] Error getting certificate '%s': %s", crt.Namespace, crt.Name, crt.Spec.SecretName, err.Error())) diff --git a/pkg/issuer/acme/issue.go b/pkg/issuer/acme/issue.go index 3de3c7281..4a64ca148 100644 --- a/pkg/issuer/acme/issue.go +++ b/pkg/issuer/acme/issue.go @@ -27,9 +27,9 @@ func (a *Acme) obtainCertificate(crt *v1alpha1.Certificate) ([]byte, []byte, err return nil, nil, fmt.Errorf("no domains specified") } - _, acmePrivKey, err := kube.GetKeyPair(a.client, a.issuer.Namespace, a.issuer.Spec.ACME.PrivateKey) + acmePrivKey, err := kube.SecretTLSKey(a.secretsLister, a.issuer.Namespace, a.issuer.Spec.ACME.PrivateKey) - if acmePrivKey == nil { + if err != nil { return nil, nil, fmt.Errorf("error getting acme account private key: %s", err.Error()) } @@ -38,7 +38,7 @@ func (a *Acme) obtainCertificate(crt *v1alpha1.Certificate) ([]byte, []byte, err DirectoryURL: a.issuer.Spec.ACME.Server, } - _, key, err := kube.GetKeyPair(a.client, crt.Namespace, crt.Spec.SecretName) + key, err := kube.SecretTLSKey(a.secretsLister, crt.Namespace, crt.Spec.SecretName) if k8sErrors.IsNotFound(err) { key, err = pki.GenerateRSAPrivateKey(2048) @@ -47,7 +47,7 @@ func (a *Acme) obtainCertificate(crt *v1alpha1.Certificate) ([]byte, []byte, err } } - if key == nil { + if err != nil { return nil, nil, fmt.Errorf("error getting certificate private key: %s", err.Error()) } diff --git a/pkg/issuer/acme/prepare.go b/pkg/issuer/acme/prepare.go index d92afff21..21e457785 100644 --- a/pkg/issuer/acme/prepare.go +++ b/pkg/issuer/acme/prepare.go @@ -7,6 +7,7 @@ import ( "sync" "golang.org/x/crypto/acme" + k8sErrors "k8s.io/apimachinery/pkg/api/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors" "github.com/jetstack-experimental/cert-manager/pkg/apis/certmanager/v1alpha1" @@ -27,9 +28,13 @@ func (a *Acme) Prepare(crt *v1alpha1.Certificate) (v1alpha1.CertificateStatus, e } log.Printf("getting private key for acme issuer %s/%s", a.issuer.Namespace, a.issuer.Name) - _, accountPrivKey, err := kube.GetKeyPair(a.client, a.issuer.Namespace, a.issuer.Spec.ACME.PrivateKey) + accountPrivKey, err := kube.SecretTLSKey(a.secretsLister, a.issuer.Namespace, a.issuer.Spec.ACME.PrivateKey) - if accountPrivKey == nil { + if k8sErrors.IsNotFound(err) { + return updateStatus, err + } + + if err != nil { return updateStatus, fmt.Errorf("error getting acme account private key: %s", err.Error()) } diff --git a/pkg/issuer/acme/setup.go b/pkg/issuer/acme/setup.go index e1758e800..d72d9f105 100644 --- a/pkg/issuer/acme/setup.go +++ b/pkg/issuer/acme/setup.go @@ -2,6 +2,7 @@ package acme import ( "context" + "crypto/rsa" "fmt" "strings" @@ -32,39 +33,13 @@ const ( func (a *Acme) Setup() (v1alpha1.IssuerStatus, error) { update := a.issuer.DeepCopy() - _, accountPrivKey, err := kube.GetKeyPair(a.client, a.issuer.Namespace, a.issuer.Spec.ACME.PrivateKey) + accountPrivKey, err := kube.SecretTLSKey(a.secretsLister, a.issuer.Namespace, a.issuer.Spec.ACME.PrivateKey) if k8sErrors.IsNotFound(err) { - accountPrivKey, err = pki.GenerateRSAPrivateKey(2048) - - if err != nil { - s := messageAccountRegistrationFailed + "error generating private key " + err.Error() - glog.Info(s) - a.recorder.Event(a.issuer, v1.EventTypeWarning, errorAccountRegistrationFailed, s) - v1alpha1.UpdateIssuerStatusCondition(update, v1alpha1.IssuerConditionReady, v1alpha1.ConditionFalse, errorAccountRegistrationFailed, s) - return update.Status, fmt.Errorf(s) - } - - _, err = kube.EnsureSecret(a.client, &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: a.issuer.Spec.ACME.PrivateKey, - Namespace: a.issuer.Namespace, - }, - Data: map[string][]byte{ - v1.TLSPrivateKeyKey: pki.EncodePKCS1PrivateKey(accountPrivKey), - }, - }) - - if err != nil { - s := messageAccountRegistrationFailed + "error saving private key " + err.Error() - glog.Info(s) - a.recorder.Event(a.issuer, v1.EventTypeWarning, errorAccountRegistrationFailed, s) - v1alpha1.UpdateIssuerStatusCondition(update, v1alpha1.IssuerConditionReady, v1alpha1.ConditionFalse, errorAccountRegistrationFailed, s) - return update.Status, fmt.Errorf(s) - } + accountPrivKey, err = a.createAccountPrivateKey() } - if accountPrivKey == nil { + if err != nil { s := messageAccountRegistrationFailed + err.Error() glog.Info(s) a.recorder.Event(a.issuer, v1.EventTypeWarning, errorAccountRegistrationFailed, s) @@ -77,7 +52,7 @@ func (a *Acme) Setup() (v1alpha1.IssuerStatus, error) { DirectoryURL: a.issuer.Spec.ACME.Server, } - _, err = cl.GetReg(context.Background(), a.issuer.Status.ACME.URI) + _, err = cl.GetReg(context.Background(), a.issuer.Status.ACMEStatus().URI) if err == nil { glog.Info(messageAccountVerified) @@ -112,3 +87,27 @@ func (a *Acme) Setup() (v1alpha1.IssuerStatus, error) { return update.Status, nil } + +func (a *Acme) createAccountPrivateKey() (*rsa.PrivateKey, error) { + accountPrivKey, err := pki.GenerateRSAPrivateKey(2048) + + if err != nil { + return nil, err + } + + _, err = kube.EnsureSecret(a.client, &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.issuer.Spec.ACME.PrivateKey, + Namespace: a.issuer.Namespace, + }, + Data: map[string][]byte{ + v1.TLSPrivateKeyKey: pki.EncodePKCS1PrivateKey(accountPrivKey), + }, + }) + + if err != nil { + return nil, err + } + + return accountPrivKey, err +} diff --git a/pkg/util/kube/pki.go b/pkg/util/kube/pki.go index 466191671..00975357c 100644 --- a/pkg/util/kube/pki.go +++ b/pkg/util/kube/pki.go @@ -3,45 +3,54 @@ package kube import ( "crypto/rsa" "crypto/x509" - "fmt" "github.com/jetstack-experimental/cert-manager/pkg/util/errors" "github.com/jetstack-experimental/cert-manager/pkg/util/pki" api "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/client-go/kubernetes" + corelisters "k8s.io/client-go/listers/core/v1" ) -func GetKeyPair(cl kubernetes.Interface, namespace, name string) (*x509.Certificate, *rsa.PrivateKey, error) { - secret, err := cl.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{}) +func GetKeyPair(secretLister corelisters.SecretLister, namespace, name string) (certBytes []byte, keyBytes []byte, err error) { + secret, err := secretLister.Secrets(namespace).Get(name) if err != nil { return nil, nil, err } - certBytes, okcert := secret.Data[api.TLSCertKey] - keyBytes, okkey := secret.Data[api.TLSPrivateKeyKey] + certBytes = secret.Data[api.TLSCertKey] + keyBytes = secret.Data[api.TLSPrivateKeyKey] - // check if the certificate and private key exist, we stop so as to not - // destroy a secret potentially used for something else - if !okcert || !okkey { - return nil, nil, fmt.Errorf("Secret does not contain TLS fields") - } - - key, keyErr := pki.DecodePKCS1PrivateKeyBytes(keyBytes) - cert, certErr := pki.DecodeX509CertificateBytes(certBytes) - - var errs []error - if keyErr != nil { - errs = append(errs, keyErr) - } - if certErr != nil { - errs = append(errs, certErr) - } - if len(errs) > 0 { - err = errors.NewInvalidData(utilerrors.NewAggregate(errs).Error()) - } - - return cert, key, err + return certBytes, keyBytes, err +} + +func SecretTLSKey(secretLister corelisters.SecretLister, namespace, name string) (*rsa.PrivateKey, error) { + secret, err := secretLister.Secrets(namespace).Get(name) + + if err != nil { + return nil, err + } + + keyBytes := secret.Data[api.TLSPrivateKeyKey] + key, err := pki.DecodePKCS1PrivateKeyBytes(keyBytes) + + if err != nil { + return key, errors.NewInvalidData(err.Error()) + } + return key, nil +} + +func SecretTLSCert(secretLister corelisters.SecretLister, namespace, name string) (*x509.Certificate, error) { + secret, err := secretLister.Secrets(namespace).Get(name) + + if err != nil { + return nil, err + } + + certBytes := secret.Data[api.TLSCertKey] + cert, err := pki.DecodeX509CertificateBytes(certBytes) + + if err != nil { + return cert, errors.NewInvalidData(err.Error()) + } + return cert, nil }