edgeservices icon indicating copy to clipboard operation
edgeservices copied to clipboard

Consider honoring Kubernetes CSR spec.expirationSeconds to control cert duration

Open enj opened this issue 2 years ago • 1 comments

The GA requirements for the Kubernetes CSR Duration KEP state:

Inform external signer implementations of the spec.expirationSeconds field

smart-edge-open/edgeservices is an external signer implementation. This diff outlines how this signer may be updated to honor this new field:

diff --git a/pkg/certsigner/certsigner.go b/pkg/certsigner/certsigner.go
index 927299b..96bedf1 100644
--- a/pkg/certsigner/certsigner.go
+++ b/pkg/certsigner/certsigner.go
@@ -22,6 +22,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/informers"
 	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/util/certificate/csr"
 	capihelper "k8s.io/kubernetes/pkg/apis/certificates/v1"
 	"k8s.io/kubernetes/pkg/controller/certificates"
 	"k8s.io/kubernetes/pkg/controller/certificates/authority"
@@ -99,7 +100,7 @@ func (c *CertificateSigner) handleCSR(csr *capi.CertificateSigningRequest) error
 	}
 
 	certData, err := c.ca.Sign(x509cr.Raw, authority.PermissiveSigningPolicy{
-		TTL:    c.cfg.CertTTL.Duration,
+		TTL:    c.duration(csr.Spec.ExpirationSeconds),
 		Usages: csr.Spec.Usages,
 	})
 	if err != nil {
@@ -118,6 +119,28 @@ func (c *CertificateSigner) handleCSR(csr *capi.CertificateSigningRequest) error
 	return nil
 }
 
+func (c *CertificateSigner) duration(expirationSeconds *int32) time.Duration {
+	defaultDuration := c.cfg.CertTTL.Duration
+
+	if expirationSeconds == nil {
+		return defaultDuration
+	}
+
+	// honor requested duration is if it is less than the default TTL
+	// use 10 min (2x hard coded backdate above) as a sanity check lower bound
+	const min = 10 * time.Minute
+	switch requestedDuration := csr.ExpirationSecondsToDuration(*expirationSeconds); {
+	case requestedDuration > defaultDuration:
+		return defaultDuration
+
+	case requestedDuration < min:
+		return min
+
+	default:
+		return requestedDuration
+	}
+}
+
 func loadCA(certPath, keyPath string) (authority.CertificateAuthority, error) {
 	caCert, err := tls.LoadX509KeyPair(certPath, keyPath)
 	if err != nil {

Note that this requires Kubernetes v1.22+

enj avatar Mar 17 '22 20:03 enj

cc @cjnolan @pankajgoyal2 @cezaryxmarczak

enj avatar Mar 17 '22 20:03 enj