mirror of
https://github.com/kubernetes/client-go.git
synced 2025-06-25 06:31:35 +00:00
Merge pull request #99494 from enj/enj/i/not_after_ttl_hint
csr: add expirationSeconds field to control cert lifetime Kubernetes-commit: 659c7e709f3b7f5f2a25e456525cd8747f2e68cc
This commit is contained in:
commit
ca3a47f0b4
@ -25,13 +25,14 @@ import (
|
|||||||
// CertificateSigningRequestSpecApplyConfiguration represents an declarative configuration of the CertificateSigningRequestSpec type for use
|
// CertificateSigningRequestSpecApplyConfiguration represents an declarative configuration of the CertificateSigningRequestSpec type for use
|
||||||
// with apply.
|
// with apply.
|
||||||
type CertificateSigningRequestSpecApplyConfiguration struct {
|
type CertificateSigningRequestSpecApplyConfiguration struct {
|
||||||
Request []byte `json:"request,omitempty"`
|
Request []byte `json:"request,omitempty"`
|
||||||
SignerName *string `json:"signerName,omitempty"`
|
SignerName *string `json:"signerName,omitempty"`
|
||||||
Usages []v1.KeyUsage `json:"usages,omitempty"`
|
ExpirationSeconds *int32 `json:"expirationSeconds,omitempty"`
|
||||||
Username *string `json:"username,omitempty"`
|
Usages []v1.KeyUsage `json:"usages,omitempty"`
|
||||||
UID *string `json:"uid,omitempty"`
|
Username *string `json:"username,omitempty"`
|
||||||
Groups []string `json:"groups,omitempty"`
|
UID *string `json:"uid,omitempty"`
|
||||||
Extra map[string]v1.ExtraValue `json:"extra,omitempty"`
|
Groups []string `json:"groups,omitempty"`
|
||||||
|
Extra map[string]v1.ExtraValue `json:"extra,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CertificateSigningRequestSpecApplyConfiguration constructs an declarative configuration of the CertificateSigningRequestSpec type for use with
|
// CertificateSigningRequestSpecApplyConfiguration constructs an declarative configuration of the CertificateSigningRequestSpec type for use with
|
||||||
@ -58,6 +59,14 @@ func (b *CertificateSigningRequestSpecApplyConfiguration) WithSignerName(value s
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithExpirationSeconds sets the ExpirationSeconds field in the declarative configuration to the given value
|
||||||
|
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||||
|
// If called multiple times, the ExpirationSeconds field is set to the value of the last call.
|
||||||
|
func (b *CertificateSigningRequestSpecApplyConfiguration) WithExpirationSeconds(value int32) *CertificateSigningRequestSpecApplyConfiguration {
|
||||||
|
b.ExpirationSeconds = &value
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// WithUsages adds the given value to the Usages field in the declarative configuration
|
// WithUsages adds the given value to the Usages field in the declarative configuration
|
||||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||||
// If called multiple times, values provided by each call will be appended to the Usages field.
|
// If called multiple times, values provided by each call will be appended to the Usages field.
|
||||||
|
@ -25,13 +25,14 @@ import (
|
|||||||
// CertificateSigningRequestSpecApplyConfiguration represents an declarative configuration of the CertificateSigningRequestSpec type for use
|
// CertificateSigningRequestSpecApplyConfiguration represents an declarative configuration of the CertificateSigningRequestSpec type for use
|
||||||
// with apply.
|
// with apply.
|
||||||
type CertificateSigningRequestSpecApplyConfiguration struct {
|
type CertificateSigningRequestSpecApplyConfiguration struct {
|
||||||
Request []byte `json:"request,omitempty"`
|
Request []byte `json:"request,omitempty"`
|
||||||
SignerName *string `json:"signerName,omitempty"`
|
SignerName *string `json:"signerName,omitempty"`
|
||||||
Usages []v1beta1.KeyUsage `json:"usages,omitempty"`
|
ExpirationSeconds *int32 `json:"expirationSeconds,omitempty"`
|
||||||
Username *string `json:"username,omitempty"`
|
Usages []v1beta1.KeyUsage `json:"usages,omitempty"`
|
||||||
UID *string `json:"uid,omitempty"`
|
Username *string `json:"username,omitempty"`
|
||||||
Groups []string `json:"groups,omitempty"`
|
UID *string `json:"uid,omitempty"`
|
||||||
Extra map[string]v1beta1.ExtraValue `json:"extra,omitempty"`
|
Groups []string `json:"groups,omitempty"`
|
||||||
|
Extra map[string]v1beta1.ExtraValue `json:"extra,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CertificateSigningRequestSpecApplyConfiguration constructs an declarative configuration of the CertificateSigningRequestSpec type for use with
|
// CertificateSigningRequestSpecApplyConfiguration constructs an declarative configuration of the CertificateSigningRequestSpec type for use with
|
||||||
@ -58,6 +59,14 @@ func (b *CertificateSigningRequestSpecApplyConfiguration) WithSignerName(value s
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithExpirationSeconds sets the ExpirationSeconds field in the declarative configuration to the given value
|
||||||
|
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||||
|
// If called multiple times, the ExpirationSeconds field is set to the value of the last call.
|
||||||
|
func (b *CertificateSigningRequestSpecApplyConfiguration) WithExpirationSeconds(value int32) *CertificateSigningRequestSpecApplyConfiguration {
|
||||||
|
b.ExpirationSeconds = &value
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// WithUsages adds the given value to the Usages field in the declarative configuration
|
// WithUsages adds the given value to the Usages field in the declarative configuration
|
||||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||||
// If called multiple times, values provided by each call will be appended to the Usages field.
|
// If called multiple times, values provided by each call will be appended to the Usages field.
|
||||||
|
@ -2843,6 +2843,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
|||||||
- name: io.k8s.api.certificates.v1.CertificateSigningRequestSpec
|
- name: io.k8s.api.certificates.v1.CertificateSigningRequestSpec
|
||||||
map:
|
map:
|
||||||
fields:
|
fields:
|
||||||
|
- name: expirationSeconds
|
||||||
|
type:
|
||||||
|
scalar: numeric
|
||||||
- name: extra
|
- name: extra
|
||||||
type:
|
type:
|
||||||
map:
|
map:
|
||||||
@ -2939,6 +2942,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
|||||||
- name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec
|
- name: io.k8s.api.certificates.v1beta1.CertificateSigningRequestSpec
|
||||||
map:
|
map:
|
||||||
fields:
|
fields:
|
||||||
|
- name: expirationSeconds
|
||||||
|
type:
|
||||||
|
scalar: numeric
|
||||||
- name: extra
|
- name: extra
|
||||||
type:
|
type:
|
||||||
map:
|
map:
|
||||||
|
4
go.mod
4
go.mod
@ -30,7 +30,7 @@ require (
|
|||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||||
google.golang.org/protobuf v1.26.0
|
google.golang.org/protobuf v1.26.0
|
||||||
k8s.io/api v0.0.0-20210701054328-f75dde501d56
|
k8s.io/api v0.0.0-20210702094336-49e8721f8489
|
||||||
k8s.io/apimachinery v0.0.0-20210701054147-830375057167
|
k8s.io/apimachinery v0.0.0-20210701054147-830375057167
|
||||||
k8s.io/klog/v2 v2.9.0
|
k8s.io/klog/v2 v2.9.0
|
||||||
k8s.io/utils v0.0.0-20210521133846-da695404a2bc
|
k8s.io/utils v0.0.0-20210521133846-da695404a2bc
|
||||||
@ -39,6 +39,6 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
replace (
|
replace (
|
||||||
k8s.io/api => k8s.io/api v0.0.0-20210701054328-f75dde501d56
|
k8s.io/api => k8s.io/api v0.0.0-20210702094336-49e8721f8489
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20210701054147-830375057167
|
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20210701054147-830375057167
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@ -444,8 +444,8 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
|
|||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/api v0.0.0-20210701054328-f75dde501d56 h1:D7+RjL9qHD5SvrWwSnT0NugysPfJAopsJphgGxpp+kU=
|
k8s.io/api v0.0.0-20210702094336-49e8721f8489 h1:R+giJyPdlHfUvmzHBQ6tm2tlmxcZ2NWgkGSxLbQZ/ZM=
|
||||||
k8s.io/api v0.0.0-20210701054328-f75dde501d56/go.mod h1:zoURDvOPW5UMFZr2YUU/sStjYnWSPt+x+MM4R94ATgQ=
|
k8s.io/api v0.0.0-20210702094336-49e8721f8489/go.mod h1:zoURDvOPW5UMFZr2YUU/sStjYnWSPt+x+MM4R94ATgQ=
|
||||||
k8s.io/apimachinery v0.0.0-20210701054147-830375057167 h1:fob/j8+uMBIVvyo+9bG7GvjFSj0LX3RNuSXW+RcUrwo=
|
k8s.io/apimachinery v0.0.0-20210701054147-830375057167 h1:fob/j8+uMBIVvyo+9bG7GvjFSj0LX3RNuSXW+RcUrwo=
|
||||||
k8s.io/apimachinery v0.0.0-20210701054147-830375057167/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
k8s.io/apimachinery v0.0.0-20210701054147-830375057167/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
@ -88,6 +88,11 @@ type Config struct {
|
|||||||
// SignerName is the name of the certificate signer that should sign certificates
|
// SignerName is the name of the certificate signer that should sign certificates
|
||||||
// generated by the manager.
|
// generated by the manager.
|
||||||
SignerName string
|
SignerName string
|
||||||
|
// RequestedCertificateLifetime is the requested lifetime length for certificates generated by the manager.
|
||||||
|
// Optional.
|
||||||
|
// This will set the spec.expirationSeconds field on the CSR. Controlling the lifetime of
|
||||||
|
// the issued certificate is not guaranteed as the signer may choose to ignore the request.
|
||||||
|
RequestedCertificateLifetime *time.Duration
|
||||||
// Usages is the types of usages that certificates generated by the manager
|
// Usages is the types of usages that certificates generated by the manager
|
||||||
// can be used for.
|
// can be used for.
|
||||||
Usages []certificates.KeyUsage
|
Usages []certificates.KeyUsage
|
||||||
@ -184,10 +189,11 @@ type manager struct {
|
|||||||
lastRequestCancel context.CancelFunc
|
lastRequestCancel context.CancelFunc
|
||||||
lastRequest *x509.CertificateRequest
|
lastRequest *x509.CertificateRequest
|
||||||
|
|
||||||
dynamicTemplate bool
|
dynamicTemplate bool
|
||||||
signerName string
|
signerName string
|
||||||
usages []certificates.KeyUsage
|
requestedCertificateLifetime *time.Duration
|
||||||
forceRotation bool
|
usages []certificates.KeyUsage
|
||||||
|
forceRotation bool
|
||||||
|
|
||||||
certStore Store
|
certStore Store
|
||||||
|
|
||||||
@ -230,18 +236,19 @@ func NewManager(config *Config) (Manager, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m := manager{
|
m := manager{
|
||||||
stopCh: make(chan struct{}),
|
stopCh: make(chan struct{}),
|
||||||
clientsetFn: config.ClientsetFn,
|
clientsetFn: config.ClientsetFn,
|
||||||
getTemplate: getTemplate,
|
getTemplate: getTemplate,
|
||||||
dynamicTemplate: config.GetTemplate != nil,
|
dynamicTemplate: config.GetTemplate != nil,
|
||||||
signerName: config.SignerName,
|
signerName: config.SignerName,
|
||||||
usages: config.Usages,
|
requestedCertificateLifetime: config.RequestedCertificateLifetime,
|
||||||
certStore: config.CertificateStore,
|
usages: config.Usages,
|
||||||
cert: cert,
|
certStore: config.CertificateStore,
|
||||||
forceRotation: forceRotation,
|
cert: cert,
|
||||||
certificateRotation: config.CertificateRotation,
|
forceRotation: forceRotation,
|
||||||
certificateRenewFailure: config.CertificateRenewFailure,
|
certificateRotation: config.CertificateRotation,
|
||||||
now: time.Now,
|
certificateRenewFailure: config.CertificateRenewFailure,
|
||||||
|
now: time.Now,
|
||||||
}
|
}
|
||||||
|
|
||||||
name := config.Name
|
name := config.Name
|
||||||
@ -459,7 +466,7 @@ func (m *manager) rotateCerts() (bool, error) {
|
|||||||
|
|
||||||
// Call the Certificate Signing Request API to get a certificate for the
|
// Call the Certificate Signing Request API to get a certificate for the
|
||||||
// new private key.
|
// new private key.
|
||||||
reqName, reqUID, err := csr.RequestCertificate(clientSet, csrPEM, "", m.signerName, m.usages, privateKey)
|
reqName, reqUID, err := csr.RequestCertificate(clientSet, csrPEM, "", m.signerName, m.requestedCertificateLifetime, m.usages, privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utilruntime.HandleError(fmt.Errorf("%s: Failed while requesting a signed certificate from the control plane: %v", m.name, err))
|
utilruntime.HandleError(fmt.Errorf("%s: Failed while requesting a signed certificate from the control plane: %v", m.name, err))
|
||||||
if m.certificateRenewFailure != nil {
|
if m.certificateRenewFailure != nil {
|
||||||
|
@ -25,8 +25,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
|
|
||||||
certificatesv1 "k8s.io/api/certificates/v1"
|
certificatesv1 "k8s.io/api/certificates/v1"
|
||||||
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -41,12 +39,16 @@ import (
|
|||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
watchtools "k8s.io/client-go/tools/watch"
|
watchtools "k8s.io/client-go/tools/watch"
|
||||||
certutil "k8s.io/client-go/util/cert"
|
certutil "k8s.io/client-go/util/cert"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
"k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RequestCertificate will either use an existing (if this process has run
|
// RequestCertificate will either use an existing (if this process has run
|
||||||
// before but not to completion) or create a certificate signing request using the
|
// before but not to completion) or create a certificate signing request using the
|
||||||
// PEM encoded CSR and send it to API server.
|
// PEM encoded CSR and send it to API server. An optional requestedDuration may be passed
|
||||||
func RequestCertificate(client clientset.Interface, csrData []byte, name string, signerName string, usages []certificatesv1.KeyUsage, privateKey interface{}) (reqName string, reqUID types.UID, err error) {
|
// to set the spec.expirationSeconds field on the CSR to control the lifetime of the issued
|
||||||
|
// certificate. This is not guaranteed as the signer may choose to ignore the request.
|
||||||
|
func RequestCertificate(client clientset.Interface, csrData []byte, name, signerName string, requestedDuration *time.Duration, usages []certificatesv1.KeyUsage, privateKey interface{}) (reqName string, reqUID types.UID, err error) {
|
||||||
csr := &certificatesv1.CertificateSigningRequest{
|
csr := &certificatesv1.CertificateSigningRequest{
|
||||||
// Username, UID, Groups will be injected by API server.
|
// Username, UID, Groups will be injected by API server.
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "CertificateSigningRequest"},
|
TypeMeta: metav1.TypeMeta{Kind: "CertificateSigningRequest"},
|
||||||
@ -62,6 +64,9 @@ func RequestCertificate(client clientset.Interface, csrData []byte, name string,
|
|||||||
if len(csr.Name) == 0 {
|
if len(csr.Name) == 0 {
|
||||||
csr.GenerateName = "csr-"
|
csr.GenerateName = "csr-"
|
||||||
}
|
}
|
||||||
|
if requestedDuration != nil {
|
||||||
|
csr.Spec.ExpirationSeconds = DurationToExpirationSeconds(*requestedDuration)
|
||||||
|
}
|
||||||
|
|
||||||
reqName, reqUID, err = create(client, csr)
|
reqName, reqUID, err = create(client, csr)
|
||||||
switch {
|
switch {
|
||||||
@ -85,6 +90,14 @@ func RequestCertificate(client clientset.Interface, csrData []byte, name string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DurationToExpirationSeconds(duration time.Duration) *int32 {
|
||||||
|
return pointer.Int32(int32(duration / time.Second))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpirationSecondsToDuration(expirationSeconds int32) time.Duration {
|
||||||
|
return time.Duration(expirationSeconds) * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
func get(client clientset.Interface, name string) (*certificatesv1.CertificateSigningRequest, error) {
|
func get(client clientset.Interface, name string) (*certificatesv1.CertificateSigningRequest, error) {
|
||||||
v1req, v1err := client.CertificatesV1().CertificateSigningRequests().Get(context.TODO(), name, metav1.GetOptions{})
|
v1req, v1err := client.CertificatesV1().CertificateSigningRequests().Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
if v1err == nil || !apierrors.IsNotFound(v1err) {
|
if v1err == nil || !apierrors.IsNotFound(v1err) {
|
||||||
|
Loading…
Reference in New Issue
Block a user