Skip to content

Commit

Permalink
checks for isCA and duration
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphaelVogel committed Sep 11, 2024
1 parent b0980ee commit 10b68eb
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 23 deletions.
6 changes: 2 additions & 4 deletions pkg/cert/legobridge/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ type ObtainInput struct {
// IsCA is used to request a self-signed certificate
IsCA bool
// Duration is the lifetime of the certificate
Duration time.Duration
Duration *time.Duration
}

// DNSControllerSettings are the settings for the DNSController.
Expand Down Expand Up @@ -165,7 +165,6 @@ func obtainForDomains(client *lego.Client, domains []string, input ObtainInput)
AlwaysDeactivateAuthorizations: input.AlwaysDeactivateAuthorizations,
PreferredChain: input.PreferredChain,
PrivateKey: privateKey,
NotAfter: time.Now().Add(input.Duration),
}
return client.Certificate.Obtain(request)
}
Expand Down Expand Up @@ -282,7 +281,6 @@ func obtainForCSR(client *lego.Client, csr []byte, input ObtainInput) (*certific
Bundle: true,
AlwaysDeactivateAuthorizations: input.AlwaysDeactivateAuthorizations,
PreferredChain: input.PreferredChain,
NotAfter: time.Now().Add(input.Duration),
})
}

Expand Down Expand Up @@ -608,7 +606,7 @@ func newCASignedCertFromInput(input ObtainInput) (*certificate.Resource, error)

// newCASignedCertFromCertReq returns a new Certificate signed by a CA based on
// an x509.CertificateRequest and a CA key pair. A private key will be generated.
func newCASignedCertFromCertReq(csr *x509.CertificateRequest, CAKeyPair *TLSKeyPair, duration time.Duration) (*certificate.Resource, error) {
func newCASignedCertFromCertReq(csr *x509.CertificateRequest, CAKeyPair *TLSKeyPair, duration *time.Duration) (*certificate.Resource, error) {
pubKeySize := pubKeySize(csr.PublicKey)
if pubKeySize == 0 {
pubKeySize = defaultKeySize(csr.PublicKeyAlgorithm)
Expand Down
8 changes: 4 additions & 4 deletions pkg/cert/legobridge/pki.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const (
)

// issueSignedCert does all the Certificate Issuing.
func issueSignedCert(csr *x509.CertificateRequest, isCA bool, privKey crypto.Signer, privKeyPEM []byte, signerKeyPair *TLSKeyPair, duration time.Duration) (*certificate.Resource, error) {
func issueSignedCert(csr *x509.CertificateRequest, isCA bool, privKey crypto.Signer, privKeyPEM []byte, signerKeyPair *TLSKeyPair, duration *time.Duration) (*certificate.Resource, error) {
csrPEM, err := generateCSRPEM(csr, privKey)
if err != nil {
return nil, err
Expand Down Expand Up @@ -183,7 +183,7 @@ func generateCSRPEM(csr *x509.CertificateRequest, privateKey crypto.Signer) ([]b
}

// generateCertFromCSR generates an x509.Certificate based on a PEM encoded CSR.
func generateCertFromCSR(csrPEM []byte, duration time.Duration, isCA bool) (*x509.Certificate, error) {
func generateCertFromCSR(csrPEM []byte, duration *time.Duration, isCA bool) (*x509.Certificate, error) {
var serialNumberLimit = new(big.Int).Lsh(big.NewInt(1), 128)

csr, err := extractCertificateRequest(csrPEM)
Expand Down Expand Up @@ -217,7 +217,7 @@ func generateCertFromCSR(csrPEM []byte, duration time.Duration, isCA bool) (*x50
IsCA: isCA,
Subject: csr.Subject,
NotBefore: time.Now(),
NotAfter: time.Now().Add(duration),
NotAfter: time.Now().Add(*duration),
KeyUsage: ku,
ExtKeyUsage: DefaultCertExtKeyUsage,
DNSNames: csr.DNSNames,
Expand All @@ -244,7 +244,7 @@ func newSelfSignedCertInPEMFormat(
},
DNSNames: input.DNSNames,
NotBefore: time.Now(),
NotAfter: time.Now().Add(input.Duration),
NotAfter: time.Now().Add(*input.Duration),
KeyUsage: keyUsage,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
IsCA: true,
Expand Down
44 changes: 29 additions & 15 deletions pkg/controller/issuer/certificate/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
apierrrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/utils/ptr"

api "github.com/gardener/cert-management/pkg/apis/cert/v1alpha1"
"github.com/gardener/cert-management/pkg/cert/legobridge"
Expand Down Expand Up @@ -409,9 +410,11 @@ func (r *certReconciler) obtainCertificateAndPendingACME(logctx logger.LogContex
if err != nil {
return r.failed(logctx, obj, api.StateError, err)
}
duration, err := r.getDuration(cert)
if err != nil {
return r.failedStop(logctx, obj, api.StateError, err)
if cert.Spec.Duration != nil {
return r.failedStop(logctx, obj, api.StateError, fmt.Errorf("duration cannot be set for ACME certificate"))
}
if cert.Spec.IsCA != nil {
return r.failedStop(logctx, obj, api.StateError, fmt.Errorf("isCA cannot be set for ACME certificate"))
}
err = r.validateDomainsAndCsr(&cert.Spec, issuer.Spec.ACME.Domains, issuerKey)
if err != nil {
Expand Down Expand Up @@ -511,7 +514,6 @@ func (r *certReconciler) obtainCertificateAndPendingACME(logctx logger.LogContex
AlwaysDeactivateAuthorizations: r.alwaysDeactivateAuthorizations,
PreferredChain: preferredChain,
KeyType: keyType,
Duration: duration,
}

err = r.obtainer.Obtain(input)
Expand Down Expand Up @@ -568,6 +570,10 @@ func (r *certReconciler) obtainCertificateSelfSigned(logctx logger.LogContext, o
if err != nil {
return r.failedStop(logctx, obj, api.StateError, err)
}
if duration == nil {
defaultDuration := legobridge.DefaultCertDuration
duration = &defaultDuration
}
err = r.validateDomainsAndCsr(&cert.Spec, nil, issuerKey)
if err != nil {
return r.failedStop(logctx, obj, api.StateError, err)
Expand Down Expand Up @@ -623,14 +629,22 @@ func (r *certReconciler) obtainCertificateSelfSigned(logctx logger.LogContext, o

func (r *certReconciler) obtainCertificateCA(logctx logger.LogContext, obj resources.Object,
renew bool, cert *api.Certificate, issuerKey utils.IssuerKey, issuer *api.Issuer) reconcile.Status {
if cert.Spec.IsCA != nil {
return r.failedStop(logctx, obj, api.StateError, fmt.Errorf("isCA cannot be set for CA certificate"))
}
CAKeyPair, err := r.restoreCA(issuerKey, issuer)
if err != nil {
return r.failed(logctx, obj, api.StateError, err)
}

duration, err := r.getDuration(cert)
if err != nil {
return r.failedStop(logctx, obj, api.StateError, err)
}
if duration == nil {
defaultDuration := 2 * legobridge.DefaultCertDuration
duration = &defaultDuration
}
err = r.validateCertDuration(duration, CAKeyPair)
if err != nil {
return r.failedStop(logctx, obj, api.StateError, err)
Expand Down Expand Up @@ -723,22 +737,22 @@ func (r *certReconciler) checkDomainRangeRestriction(issuerDomains *api.DNSSelec
return nil
}

func (r *certReconciler) getDuration(cert *api.Certificate) (time.Duration, error) {
duration := legobridge.DefaultCertDuration
if cert.Spec.Duration != nil {
duration = cert.Spec.Duration.Duration
if duration < 2*r.renewalWindow {
return 0, fmt.Errorf("certificate duration must be greater than %v", 2*r.renewalWindow)
}
func (r *certReconciler) getDuration(cert *api.Certificate) (*time.Duration, error) {
if cert.Spec.Duration == nil {
return nil, nil
}
duration := cert.Spec.Duration.Duration
if duration < 2*r.renewalWindow {
return nil, fmt.Errorf("certificate duration must be greater than %v", 2*r.renewalWindow)
}
return duration, nil
return ptr.To(duration), nil
}

func (r *certReconciler) validateCertDuration(duration time.Duration, caKeyPair *legobridge.TLSKeyPair) error {
func (r *certReconciler) validateCertDuration(duration *time.Duration, caKeyPair *legobridge.TLSKeyPair) error {
caNotAfter := caKeyPair.Cert.NotAfter
now := time.Now()
if now.Add(duration).After(caNotAfter) {
return fmt.Errorf("certificate lifetime (%v) is longer than the lifetime of the CA certificate (%v)", now.Add(duration), caNotAfter)
if now.Add(*duration).After(caNotAfter) {
return fmt.Errorf("certificate lifetime (%v) is longer than the lifetime of the CA certificate (%v)", now.Add(*duration), caNotAfter)
}
return nil
}
Expand Down

0 comments on commit 10b68eb

Please sign in to comment.