Skip to content

[release-4.19] OCPBUGS-56082: UPSTREAM: 130047: adjusting loopback certificate validity in kube-apiserver #2297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: release-4.19
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package options

import (
"fmt"
"time"

"github.com/google/uuid"

Expand Down Expand Up @@ -49,9 +50,18 @@ func (s *SecureServingOptionsWithLoopback) ApplyTo(secureServingInfo **server.Se
return nil
}

// Set a validity period of approximately 3 years for the loopback certificate
// to avoid kube-apiserver disruptions due to certificate expiration.
// When this certificate expires, restarting kube-apiserver will automatically
// regenerate a new certificate with fresh validity dates.
maxAge := (3*365 + 1) * 24 * time.Hour

// create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and
// let the server return it when the loopback client connects.
certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil)
certPem, keyPem, err := certutil.GenerateSelfSignedCertKeyWithOptions(certutil.SelfSignedCertKeyOptions{
Host: server.LoopbackClientServerNameOverride,
MaxAge: maxAge,
})
if err != nil {
return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
}
Expand Down
48 changes: 46 additions & 2 deletions staging/src/k8s.io/client-go/util/cert/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,37 @@ func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, erro
return x509.ParseCertificate(certDERBytes)
}

// SelfSignedCertKeyOptions contains configuration parameters for generating self-signed certificates.
type SelfSignedCertKeyOptions struct {
// Host is required, and identifies the host of the serving certificate. Can be a DNS name or IP address.
Host string
// AlternateIPs is optional, and identifies additional IPs the serving certificate should be valid for.
AlternateIPs []net.IP
// AlternateDNS is optional, and identifies additional DNS names the serving certificate should be valid for.
AlternateDNS []string

// MaxAge controls the duration of the issued certificate.
// Defaults to 1 year if unset.
// Ignored if FixtureDirectory is set.
MaxAge time.Duration

// FixtureDirectory is intended for use in tests.
// If non-empty, it is a directory path which can contain pre-generated certs. The format is:
// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.crt
// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.key
// Certs/keys not existing in that directory are created with a duration of 100 years.
FixtureDirectory string
}

// GenerateSelfSignedCertKey creates a self-signed certificate and key for the given host.
// Host may be an IP or a DNS name
// You may also specify additional subject alt names (either ip or dns names) for the certificate.
func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) {
return GenerateSelfSignedCertKeyWithFixtures(host, alternateIPs, alternateDNS, "")
return GenerateSelfSignedCertKeyWithOptions(SelfSignedCertKeyOptions{
Host: host,
AlternateIPs: alternateIPs,
AlternateDNS: alternateDNS,
})
}

// GenerateSelfSignedCertKeyWithFixtures creates a self-signed certificate and key for the given host.
Expand All @@ -106,8 +132,26 @@ func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS
// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.key
// Certs/keys not existing in that directory are created.
func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, alternateDNS []string, fixtureDirectory string) ([]byte, []byte, error) {
return GenerateSelfSignedCertKeyWithOptions(SelfSignedCertKeyOptions{
Host: host,
AlternateIPs: alternateIPs,
AlternateDNS: alternateDNS,
FixtureDirectory: fixtureDirectory,
})
}

// GenerateSelfSignedCertKeyWithOptions generates a self-signed certificate and key based on the provided options.
func GenerateSelfSignedCertKeyWithOptions(opts SelfSignedCertKeyOptions) ([]byte, []byte, error) {
host := opts.Host
alternateIPs := opts.AlternateIPs
alternateDNS := opts.AlternateDNS
fixtureDirectory := opts.FixtureDirectory
maxAge := opts.MaxAge
if maxAge == 0 {
maxAge = 365 * 24 * time.Hour
}

validFrom := time.Now().Add(-time.Hour) // valid an hour earlier to avoid flakes due to clock skew
maxAge := time.Hour * 24 * 365 // one year self-signed certs

baseName := fmt.Sprintf("%s_%s_%s", host, strings.Join(ipsToStrings(alternateIPs), "-"), strings.Join(alternateDNS, "-"))
certFixturePath := filepath.Join(fixtureDirectory, baseName+".crt")
Expand Down