mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-02-03 20:40:26 -05:00
Merge 5388988063 into 44ff6085cd
This commit is contained in:
commit
b9232e9800
21 changed files with 510 additions and 115 deletions
12
api/openapi-spec/swagger.json
generated
12
api/openapi-spec/swagger.json
generated
|
|
@ -5297,7 +5297,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"pkixPublicKey": {
|
||||
"description": "pkixPublicKey is the PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.",
|
||||
"description": "The PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty. Signer implementations should extract the public key from the StubPKCS10Request field.",
|
||||
"format": "byte",
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -5310,7 +5310,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"proofOfPossession": {
|
||||
"description": "proofOfPossession proves that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).",
|
||||
"description": "A proof that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty.",
|
||||
"format": "byte",
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -5326,6 +5326,11 @@
|
|||
"description": "signerName indicates the requested signer.\n\nAll signer names beginning with `kubernetes.io` are reserved for use by the Kubernetes project. There is currently one well-known signer documented by the Kubernetes project, `kubernetes.io/kube-apiserver-client-pod`, which will issue client certificates understood by kube-apiserver. It is currently unimplemented.",
|
||||
"type": "string"
|
||||
},
|
||||
"stubPKCS10Request": {
|
||||
"description": "A PKCS#10 certificate signing request (DER-serialized) generated by Kubelet using the subject private key.\n\nMost signer implementations will ignore the contents of the CSR except to extract the subject public key. The API server automatically verifies the CSR signature during admission, so the signer does not need to repeat the verification.\n\nThe subject public key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nSome CA implementations require that the client (the signer implementation, in this case) provide a PKCS#10 certificate signing request, even if the CA only extracts the subject public key from the request. To enable compatibility with these CAs, Kubelet will generate a stub PKCS#10 request that the signer implementation can then pass on to the CA.",
|
||||
"format": "byte",
|
||||
"type": "string"
|
||||
},
|
||||
"unverifiedUserAnnotations": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
|
|
@ -5342,8 +5347,7 @@
|
|||
"serviceAccountUID",
|
||||
"nodeName",
|
||||
"nodeUID",
|
||||
"pkixPublicKey",
|
||||
"proofOfPossession"
|
||||
"stubPKCS10Request"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"pkixPublicKey": {
|
||||
"description": "pkixPublicKey is the PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.",
|
||||
"description": "The PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty. Signer implementations should extract the public key from the StubPKCS10Request field.",
|
||||
"format": "byte",
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -237,7 +237,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"proofOfPossession": {
|
||||
"description": "proofOfPossession proves that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).",
|
||||
"description": "A proof that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty.",
|
||||
"format": "byte",
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -256,6 +256,11 @@
|
|||
"description": "signerName indicates the requested signer.\n\nAll signer names beginning with `kubernetes.io` are reserved for use by the Kubernetes project. There is currently one well-known signer documented by the Kubernetes project, `kubernetes.io/kube-apiserver-client-pod`, which will issue client certificates understood by kube-apiserver. It is currently unimplemented.",
|
||||
"type": "string"
|
||||
},
|
||||
"stubPKCS10Request": {
|
||||
"description": "A PKCS#10 certificate signing request (DER-serialized) generated by Kubelet using the subject private key.\n\nMost signer implementations will ignore the contents of the CSR except to extract the subject public key. The API server automatically verifies the CSR signature during admission, so the signer does not need to repeat the verification.\n\nThe subject public key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nSome CA implementations require that the client (the signer implementation, in this case) provide a PKCS#10 certificate signing request, even if the CA only extracts the subject public key from the request. To enable compatibility with these CAs, Kubelet will generate a stub PKCS#10 request that the signer implementation can then pass on to the CA.",
|
||||
"format": "byte",
|
||||
"type": "string"
|
||||
},
|
||||
"unverifiedUserAnnotations": {
|
||||
"additionalProperties": {
|
||||
"default": "",
|
||||
|
|
@ -273,8 +278,7 @@
|
|||
"serviceAccountUID",
|
||||
"nodeName",
|
||||
"nodeUID",
|
||||
"pkixPublicKey",
|
||||
"proofOfPossession"
|
||||
"stubPKCS10Request"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -340,8 +340,7 @@ type PodCertificateRequestSpec struct {
|
|||
// seconds (1 hour). This constraint is enforced by kube-apiserver.
|
||||
MaxExpirationSeconds *int32
|
||||
|
||||
// pkixPublicKey is the PKIX-serialized public key the signer will issue the
|
||||
// certificate to.
|
||||
// The PKIX-serialized public key the signer will issue the certificate to.
|
||||
//
|
||||
// The key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521,
|
||||
// or ED25519. Note that this list may be expanded in the future.
|
||||
|
|
@ -352,13 +351,20 @@ type PodCertificateRequestSpec struct {
|
|||
// setting a status.conditions entry with a type of "Denied" and a reason of
|
||||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty. Signer
|
||||
// implementations should extract the public key from the StubPKCS10Request
|
||||
// field.
|
||||
//
|
||||
// +optional
|
||||
PKIXPublicKey []byte
|
||||
|
||||
// proofOfPossession proves that the requesting kubelet holds the private
|
||||
// key corresponding to pkixPublicKey.
|
||||
// A proof that the requesting kubelet holds the private key corresponding
|
||||
// to pkixPublicKey.
|
||||
//
|
||||
// It is contructed by signing the ASCII bytes of the pod's UID using
|
||||
// `PKIXPublicKey`.
|
||||
// `pkixPublicKey`.
|
||||
//
|
||||
// kube-apiserver validates the proof of possession during creation of the
|
||||
// PodCertificateRequest.
|
||||
|
|
@ -374,8 +380,40 @@ type PodCertificateRequestSpec struct {
|
|||
// If the key is an ED25519 key, the the signature is as described by the
|
||||
// [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the
|
||||
// golang library crypto/ed25519.Sign).
|
||||
//
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty.
|
||||
//
|
||||
// +optional
|
||||
ProofOfPossession []byte
|
||||
|
||||
// A PKCS#10 certificate signing request (DER-serialized) generated by
|
||||
// Kubelet using the subject private key.
|
||||
//
|
||||
// Most signer implementations will ignore the contents of the CSR except to
|
||||
// extract the subject public key. The API server automatically verifies the
|
||||
// CSR signature during admission, so the signer does not need to repeat the
|
||||
// verification.
|
||||
//
|
||||
// The subject public key must be one of RSA3072, RSA4096, ECDSAP256,
|
||||
// ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in
|
||||
// the future.
|
||||
//
|
||||
// Signer implementations do not need to support all key types supported by
|
||||
// kube-apiserver and kubelet. If a signer does not support the key type
|
||||
// used for a given PodCertificateRequest, it must deny the request by
|
||||
// setting a status.conditions entry with a type of "Denied" and a reason of
|
||||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// Some CA implementations require that the client (the signer
|
||||
// implementation, in this case) provide a PKCS#10 certificate signing
|
||||
// request, even if the CA only extracts the subject public key from the
|
||||
// request. To enable compatibility with these CAs, Kubelet will generate a
|
||||
// stub PKCS#10 request that the signer implementation can then pass on to
|
||||
// the CA.
|
||||
StubPKCS10Request []byte
|
||||
|
||||
// unverifiedUserAnnotations allow pod authors to pass additional information to
|
||||
// the signer implementation. Kubernetes does not restrict or validate this
|
||||
// metadata in any way.
|
||||
|
|
@ -485,6 +523,9 @@ const (
|
|||
// MaxProofOfPossessionSize is the maximum size permitted for the
|
||||
// ProofOfPossession field.
|
||||
MaxProofOfPossessionSize = 10 * 1024
|
||||
// MaxStubPKCS10RequestSize is the maximum size permitted for the
|
||||
// UnverifiedPKCS10Request field.
|
||||
MaxStubPKCS10RequestSize = 10 * 1024
|
||||
// MaxCertificateChainSize is the maximum size permitted for the
|
||||
// CertificateChain field.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -463,6 +463,7 @@ func autoConvert_v1beta1_PodCertificateRequestSpec_To_certificates_PodCertificat
|
|||
out.MaxExpirationSeconds = (*int32)(unsafe.Pointer(in.MaxExpirationSeconds))
|
||||
out.PKIXPublicKey = *(*[]byte)(unsafe.Pointer(&in.PKIXPublicKey))
|
||||
out.ProofOfPossession = *(*[]byte)(unsafe.Pointer(&in.ProofOfPossession))
|
||||
out.StubPKCS10Request = *(*[]byte)(unsafe.Pointer(&in.StubPKCS10Request))
|
||||
out.UnverifiedUserAnnotations = *(*map[string]string)(unsafe.Pointer(&in.UnverifiedUserAnnotations))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -483,6 +484,7 @@ func autoConvert_certificates_PodCertificateRequestSpec_To_v1beta1_PodCertificat
|
|||
out.MaxExpirationSeconds = (*int32)(unsafe.Pointer(in.MaxExpirationSeconds))
|
||||
out.PKIXPublicKey = *(*[]byte)(unsafe.Pointer(&in.PKIXPublicKey))
|
||||
out.ProofOfPossession = *(*[]byte)(unsafe.Pointer(&in.ProofOfPossession))
|
||||
out.StubPKCS10Request = *(*[]byte)(unsafe.Pointer(&in.StubPKCS10Request))
|
||||
out.UnverifiedUserAnnotations = *(*map[string]string)(unsafe.Pointer(&in.UnverifiedUserAnnotations))
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -646,6 +646,26 @@ func ValidatePodCertificateRequestCreate(req *certificates.PodCertificateRequest
|
|||
}
|
||||
}
|
||||
|
||||
// Either (PKIXPublicKey, ProofOfPossession) xor (StubPKCS10Request)
|
||||
// must be set.
|
||||
if len(req.Spec.StubPKCS10Request) != 0 && len(req.Spec.PKIXPublicKey) == 0 && len(req.Spec.ProofOfPossession) == 0 {
|
||||
// Valid, using StubPKCS10Request
|
||||
allErrors = append(allErrors, validateStubPKCS10Request(req)...)
|
||||
return allErrors
|
||||
} else if len(req.Spec.StubPKCS10Request) == 0 && len(req.Spec.PKIXPublicKey) != 0 && len(req.Spec.ProofOfPossession) != 0 {
|
||||
// Valid, using PKIXPublicKey and ProofOfPossession
|
||||
allErrors = append(allErrors, validateDeprecatedPKIXPublicKey(req)...)
|
||||
return allErrors
|
||||
} else {
|
||||
// Invalid, any other combination.
|
||||
allErrors = append(allErrors, field.Invalid(field.NewPath("spec"), field.OmitValueType{}, "exactly one of (stubPKCS10Request) or (pkixPublicKey, proofOfPossession) must be set"))
|
||||
return allErrors
|
||||
}
|
||||
}
|
||||
|
||||
func validateDeprecatedPKIXPublicKey(req *certificates.PodCertificateRequest) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
|
||||
if len(req.Spec.PKIXPublicKey) > certificates.MaxPKIXPublicKeySize {
|
||||
allErrors = append(allErrors, field.TooLong(field.NewPath("spec", "pkixPublicKey"), req.Spec.PKIXPublicKey, certificates.MaxPKIXPublicKeySize))
|
||||
return allErrors
|
||||
|
|
@ -699,6 +719,85 @@ func ValidatePodCertificateRequestCreate(req *certificates.PodCertificateRequest
|
|||
return allErrors
|
||||
}
|
||||
|
||||
var (
|
||||
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
|
||||
)
|
||||
|
||||
func validateStubPKCS10Request(req *certificates.PodCertificateRequest) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
|
||||
if len(req.Spec.StubPKCS10Request) > certificates.MaxStubPKCS10RequestSize {
|
||||
allErrors = append(allErrors, field.TooLong(pkcs10ReqPath, req.Spec.StubPKCS10Request, certificates.MaxStubPKCS10RequestSize))
|
||||
return allErrors
|
||||
}
|
||||
|
||||
pkcs10Req, err := x509.ParseCertificateRequest(req.Spec.StubPKCS10Request)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "must be a valid PKCS#10 CSR"))
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// Check key type and parameters
|
||||
switch pkcs10Pub := pkcs10Req.PublicKey.(type) {
|
||||
case ed25519.PublicKey:
|
||||
// ed25519 has no key configuration to check
|
||||
case *ecdsa.PublicKey:
|
||||
if pkcs10Pub.Curve != elliptic.P256() && pkcs10Pub.Curve != elliptic.P384() && pkcs10Pub.Curve != elliptic.P521() {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, "curve "+pkcs10Pub.Curve.Params().Name, "elliptic public keys must use curve P256, P384, or P521"))
|
||||
return allErrors
|
||||
}
|
||||
case *rsa.PublicKey:
|
||||
if pkcs10Pub.Size()*8 != 3072 && pkcs10Pub.Size()*8 != 4096 {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, fmt.Sprintf("%d-bit modulus", pkcs10Pub.Size()*8), "RSA keys must have modulus size 3072 or 4096"))
|
||||
return allErrors
|
||||
}
|
||||
default:
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "unknown public key type; supported types are Ed25519, ECDSA, and RSA"))
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// Check that the request is empty, except for DNS or IP SANs.
|
||||
if len(pkcs10Req.Subject.Country) != 0 ||
|
||||
len(pkcs10Req.Subject.Organization) != 0 ||
|
||||
len(pkcs10Req.Subject.OrganizationalUnit) != 0 ||
|
||||
len(pkcs10Req.Subject.Locality) != 0 ||
|
||||
len(pkcs10Req.Subject.Province) != 0 ||
|
||||
len(pkcs10Req.Subject.StreetAddress) != 0 ||
|
||||
len(pkcs10Req.Subject.PostalCode) != 0 ||
|
||||
len(pkcs10Req.Subject.SerialNumber) != 0 ||
|
||||
len(pkcs10Req.Subject.CommonName) != 0 ||
|
||||
len(pkcs10Req.Subject.Names) != 0 {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "PKCS#10 request must have empty subject"))
|
||||
return allErrors
|
||||
}
|
||||
if len(pkcs10Req.EmailAddresses) != 0 {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "PKCS#10 request must not contain EmailAddress subject alternate names"))
|
||||
return allErrors
|
||||
}
|
||||
if len(pkcs10Req.URIs) != 0 {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "PKCS#10 request must not contain URI subject alternate names"))
|
||||
return allErrors
|
||||
}
|
||||
|
||||
for i := range pkcs10Req.Extensions {
|
||||
if pkcs10Req.Extensions[i].Id.Equal(oidExtensionSubjectAltName) {
|
||||
// If the SubjectAlternateName contained non-IP or non-DNS content,
|
||||
// then EmailAddresses or URIs would have been non-empty above.
|
||||
} else {
|
||||
// All other extensions are forbidden.
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "PKCS#10 request may not contain arbitrary extensions"))
|
||||
return allErrors
|
||||
}
|
||||
}
|
||||
|
||||
if err := pkcs10Req.CheckSignature(); err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "invalid signature"))
|
||||
return allErrors
|
||||
}
|
||||
|
||||
return allErrors
|
||||
}
|
||||
|
||||
func hashBytes(in []byte) []byte {
|
||||
out := sha256.Sum256(in)
|
||||
return out[:]
|
||||
|
|
@ -707,6 +806,7 @@ func hashBytes(in []byte) []byte {
|
|||
var (
|
||||
pkixPath = field.NewPath("spec", "pkixPublicKey")
|
||||
popPath = field.NewPath("spec", "proofOfPossession")
|
||||
pkcs10ReqPath = field.NewPath("spec", "stubPKCS10Request")
|
||||
certChainPath = field.NewPath("status", "certificateChain")
|
||||
notBeforePath = field.NewPath("status", "notBefore")
|
||||
notAfterPath = field.NewPath("status", "notAfter")
|
||||
|
|
@ -826,12 +926,24 @@ func ValidatePodCertificateRequestStatusUpdate(newReq, oldReq *certificates.PodC
|
|||
}
|
||||
}
|
||||
|
||||
// Was the certificate issued to the public key in the spec?
|
||||
wantPKAny, err := x509.ParsePKIXPublicKey(oldReq.Spec.PKIXPublicKey)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(pkixPath, oldReq.Spec.PKIXPublicKey, "must be a valid PKIX-serialized public key"))
|
||||
return allErrors
|
||||
// Get the public key from either StubPKCS10Request or PKIXPublicKey.
|
||||
var wantPKAny crypto.PublicKey
|
||||
if len(oldReq.Spec.StubPKCS10Request) != 0 {
|
||||
pkcs10Req, err := x509.ParseCertificateRequest(oldReq.Spec.StubPKCS10Request)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(pkcs10ReqPath, field.OmitValueType{}, "must be a valid PKCS#10 CSR"))
|
||||
return allErrors
|
||||
}
|
||||
wantPKAny = pkcs10Req.PublicKey
|
||||
} else {
|
||||
wantPKAny, err = x509.ParsePKIXPublicKey(oldReq.Spec.PKIXPublicKey)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(pkixPath, field.OmitValueType{}, "must be a valid PKIX-serialized public key"))
|
||||
return allErrors
|
||||
}
|
||||
}
|
||||
|
||||
// Was the certificate issued to the public key in the spec?
|
||||
switch wantPK := wantPKAny.(type) {
|
||||
case ed25519.PublicKey:
|
||||
if !wantPK.Equal(leafCert.PublicKey) {
|
||||
|
|
|
|||
|
|
@ -1610,9 +1610,10 @@ func TestValidateClusterTrustBundleUpdate(t *testing.T) {
|
|||
|
||||
func TestValidatePodCertificateRequestCreate(t *testing.T) {
|
||||
podUID1 := "pod-uid-1"
|
||||
_, _, ed25519PubPKIX1, ed25519Proof1 := mustMakeEd25519KeyAndProof(t, []byte(podUID1))
|
||||
_, _, ed25519PubPKIX2, ed25519Proof2 := mustMakeEd25519KeyAndProof(t, []byte("other-value"))
|
||||
_, _, _, ed25519Proof3 := mustMakeEd25519KeyAndProof(t, []byte(podUID1))
|
||||
_, _, ed25519PubPKIX1, ed25519Proof1, ed25519CSR1 := mustMakeEd25519KeyAndProof(t, []byte(podUID1), []string{})
|
||||
_, _, ed25519PubPKIX2, ed25519Proof2, _ := mustMakeEd25519KeyAndProof(t, []byte("other-value"), []string{})
|
||||
_, _, _, ed25519Proof3, _ := mustMakeEd25519KeyAndProof(t, []byte(podUID1), []string{})
|
||||
_, _, _, _, ed25519CSR4 := mustMakeEd25519KeyAndProof(t, []byte(podUID1), []string{"example.com", "foo.example.example"})
|
||||
_, _, ecdsaP224PubPKIX1, ecdsaP224Proof1 := mustMakeECDSAKeyAndProof(t, elliptic.P224(), []byte(podUID1))
|
||||
_, _, ecdsaP256PubPKIX1, ecdsaP256Proof1 := mustMakeECDSAKeyAndProof(t, elliptic.P256(), []byte(podUID1))
|
||||
_, _, ecdsaP384PubPKIX1, ecdsaP384Proof1 := mustMakeECDSAKeyAndProof(t, elliptic.P384(), []byte(podUID1))
|
||||
|
|
@ -1624,7 +1625,7 @@ func TestValidatePodCertificateRequestCreate(t *testing.T) {
|
|||
_, _, rsaWrongProofPKIX, rsaWrongProof := mustMakeRSAKeyAndProof(t, 3072, []byte("other-value"))
|
||||
|
||||
podUIDEmpty := ""
|
||||
_, _, pubPKIXEmpty, proofEmpty := mustMakeEd25519KeyAndProof(t, []byte(podUIDEmpty))
|
||||
_, _, pubPKIXEmpty, proofEmpty, _ := mustMakeEd25519KeyAndProof(t, []byte(podUIDEmpty), []string{})
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
|
|
@ -1653,6 +1654,73 @@ func TestValidatePodCertificateRequestCreate(t *testing.T) {
|
|||
},
|
||||
wantErrors: nil,
|
||||
},
|
||||
{
|
||||
description: "valid Ed25519 PCR (using PKCS#10)",
|
||||
pcr: &capi.PodCertificateRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "foo",
|
||||
Name: "bar",
|
||||
},
|
||||
Spec: capi.PodCertificateRequestSpec{
|
||||
SignerName: "foo.com/abc",
|
||||
PodName: "pod-1",
|
||||
PodUID: types.UID(podUID1),
|
||||
ServiceAccountName: "sa-1",
|
||||
ServiceAccountUID: "sa-uid-1",
|
||||
NodeName: "node-1",
|
||||
NodeUID: "node-uid-1",
|
||||
MaxExpirationSeconds: ptr.To[int32](86400),
|
||||
StubPKCS10Request: ed25519CSR1,
|
||||
},
|
||||
},
|
||||
wantErrors: nil,
|
||||
},
|
||||
{
|
||||
description: "valid Ed25519 PCR (using PKCS#10, with DNS SANs)",
|
||||
pcr: &capi.PodCertificateRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "foo",
|
||||
Name: "bar",
|
||||
},
|
||||
Spec: capi.PodCertificateRequestSpec{
|
||||
SignerName: "foo.com/abc",
|
||||
PodName: "pod-1",
|
||||
PodUID: types.UID(podUID1),
|
||||
ServiceAccountName: "sa-1",
|
||||
ServiceAccountUID: "sa-uid-1",
|
||||
NodeName: "node-1",
|
||||
NodeUID: "node-uid-1",
|
||||
MaxExpirationSeconds: ptr.To[int32](86400),
|
||||
StubPKCS10Request: ed25519CSR4,
|
||||
},
|
||||
},
|
||||
wantErrors: nil,
|
||||
},
|
||||
{
|
||||
description: "invalid Ed25519 PCR (both StubPKCS10Request and PKIXPublicKey set)",
|
||||
pcr: &capi.PodCertificateRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "foo",
|
||||
Name: "bar",
|
||||
},
|
||||
Spec: capi.PodCertificateRequestSpec{
|
||||
SignerName: "foo.com/abc",
|
||||
PodName: "pod-1",
|
||||
PodUID: types.UID(podUID1),
|
||||
ServiceAccountName: "sa-1",
|
||||
ServiceAccountUID: "sa-uid-1",
|
||||
NodeName: "node-1",
|
||||
NodeUID: "node-uid-1",
|
||||
MaxExpirationSeconds: ptr.To[int32](86400),
|
||||
PKIXPublicKey: ed25519PubPKIX1,
|
||||
ProofOfPossession: ed25519Proof1,
|
||||
StubPKCS10Request: ed25519CSR1,
|
||||
},
|
||||
},
|
||||
wantErrors: field.ErrorList{
|
||||
field.Invalid(field.NewPath("spec"), field.OmitValueType{}, "exactly one of (stubPKCS10Request) or (pkixPublicKey, proofOfPossession) must be set"),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "invalid Ed25519 proof of possession (correct key signed wrong message)",
|
||||
pcr: &capi.PodCertificateRequest{
|
||||
|
|
@ -2187,7 +2255,7 @@ func TestValidatePodCertificateRequestCreate(t *testing.T) {
|
|||
NodeUID: "node-uid-1",
|
||||
MaxExpirationSeconds: ptr.To[int32](86400),
|
||||
PKIXPublicKey: make([]byte, capi.MaxPKIXPublicKeySize+1),
|
||||
ProofOfPossession: []byte{},
|
||||
ProofOfPossession: []byte("abc"),
|
||||
},
|
||||
},
|
||||
wantErrors: field.ErrorList{
|
||||
|
|
@ -2210,7 +2278,7 @@ func TestValidatePodCertificateRequestCreate(t *testing.T) {
|
|||
NodeName: "node-1",
|
||||
NodeUID: "node-uid-1",
|
||||
MaxExpirationSeconds: ptr.To[int32](86400),
|
||||
PKIXPublicKey: []byte{},
|
||||
PKIXPublicKey: ed25519PubPKIX1,
|
||||
ProofOfPossession: make([]byte, capi.MaxProofOfPossessionSize+1),
|
||||
},
|
||||
},
|
||||
|
|
@ -2308,7 +2376,7 @@ func TestValidatePodCertificateRequestCreate(t *testing.T) {
|
|||
|
||||
func TestValidatePodCertificateRequestUpdate(t *testing.T) {
|
||||
podUID1 := "pod-uid-1"
|
||||
_, _, pubPKIX1, proof1 := mustMakeEd25519KeyAndProof(t, []byte(podUID1))
|
||||
_, _, pubPKIX1, proof1, _ := mustMakeEd25519KeyAndProof(t, []byte(podUID1), []string{})
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
|
|
@ -2396,7 +2464,7 @@ func TestValidatePodCertificateRequestStatusUpdate(t *testing.T) {
|
|||
intermediateCACertDER, intermediateCAPrivKey := mustMakeIntermediateCA(t, caCertDER, caPrivKey)
|
||||
|
||||
podUID1 := "pod-uid-1"
|
||||
_, pub1, pubPKIX1, proof1 := mustMakeEd25519KeyAndProof(t, []byte(podUID1))
|
||||
_, pub1, pubPKIX1, proof1, _ := mustMakeEd25519KeyAndProof(t, []byte(podUID1), []string{})
|
||||
|
||||
pod1Cert1 := mustSignCertForPublicKey(t, 24*time.Hour, pub1, caCertDER, caPrivKey, false, "", "")
|
||||
pod1Cert2 := mustSignCertForPublicKey(t, 18*time.Hour, pub1, caCertDER, caPrivKey, false, "", "")
|
||||
|
|
@ -4438,7 +4506,7 @@ func mustParseTime(t *testing.T, stamp string) time.Time {
|
|||
return got
|
||||
}
|
||||
|
||||
func mustMakeEd25519KeyAndProof(t *testing.T, toBeSigned []byte) (ed25519.PrivateKey, ed25519.PublicKey, []byte, []byte) {
|
||||
func mustMakeEd25519KeyAndProof(t *testing.T, toBeSigned []byte, pkcs10DNSSANS []string) (ed25519.PrivateKey, ed25519.PublicKey, []byte, []byte, []byte) {
|
||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("Error while generating ed25519 key: %v", err)
|
||||
|
|
@ -4448,7 +4516,13 @@ func mustMakeEd25519KeyAndProof(t *testing.T, toBeSigned []byte) (ed25519.Privat
|
|||
t.Fatalf("Error while marshaling PKIX public key: %v", err)
|
||||
}
|
||||
sig := ed25519.Sign(priv, toBeSigned)
|
||||
return priv, pub, pubPKIX, sig
|
||||
|
||||
pkcs10DER, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{DNSNames: pkcs10DNSSANS}, priv)
|
||||
if err != nil {
|
||||
t.Fatalf("Error while creating PKCS#10 certificate signing request: %v", err)
|
||||
}
|
||||
|
||||
return priv, pub, pubPKIX, sig, pkcs10DER
|
||||
}
|
||||
|
||||
func mustMakeECDSAKeyAndProof(t *testing.T, curve elliptic.Curve, toBeSigned []byte) (*ecdsa.PrivateKey, *ecdsa.PublicKey, []byte, []byte) {
|
||||
|
|
|
|||
5
pkg/apis/certificates/zz_generated.deepcopy.go
generated
5
pkg/apis/certificates/zz_generated.deepcopy.go
generated
|
|
@ -359,6 +359,11 @@ func (in *PodCertificateRequestSpec) DeepCopyInto(out *PodCertificateRequestSpec
|
|||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.StubPKCS10Request != nil {
|
||||
in, out := &in.StubPKCS10Request, &out.StubPKCS10Request
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.UnverifiedUserAnnotations != nil {
|
||||
in, out := &in.UnverifiedUserAnnotations, &out.UnverifiedUserAnnotations
|
||||
*out = make(map[string]string, len(*in))
|
||||
|
|
|
|||
13
pkg/generated/openapi/zz_generated.openapi.go
generated
13
pkg/generated/openapi/zz_generated.openapi.go
generated
|
|
@ -18266,14 +18266,21 @@ func schema_k8sio_api_certificates_v1beta1_PodCertificateRequestSpec(ref common.
|
|||
},
|
||||
"pkixPublicKey": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "pkixPublicKey is the PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.",
|
||||
Description: "The PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty. Signer implementations should extract the public key from the StubPKCS10Request field.",
|
||||
Type: []string{"string"},
|
||||
Format: "byte",
|
||||
},
|
||||
},
|
||||
"proofOfPossession": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "proofOfPossession proves that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).",
|
||||
Description: "A proof that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty.",
|
||||
Type: []string{"string"},
|
||||
Format: "byte",
|
||||
},
|
||||
},
|
||||
"stubPKCS10Request": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A PKCS#10 certificate signing request (DER-serialized) generated by Kubelet using the subject private key.\n\nMost signer implementations will ignore the contents of the CSR except to extract the subject public key. The API server automatically verifies the CSR signature during admission, so the signer does not need to repeat the verification.\n\nThe subject public key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nSome CA implementations require that the client (the signer implementation, in this case) provide a PKCS#10 certificate signing request, even if the CA only extracts the subject public key from the request. To enable compatibility with these CAs, Kubelet will generate a stub PKCS#10 request that the signer implementation can then pass on to the CA.",
|
||||
Type: []string{"string"},
|
||||
Format: "byte",
|
||||
},
|
||||
|
|
@ -18295,7 +18302,7 @@ func schema_k8sio_api_certificates_v1beta1_PodCertificateRequestSpec(ref common.
|
|||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"signerName", "podName", "podUID", "serviceAccountName", "serviceAccountUID", "nodeName", "nodeUID", "pkixPublicKey", "proofOfPossession"},
|
||||
Required: []string{"signerName", "podName", "podUID", "serviceAccountName", "serviceAccountUID", "nodeName", "nodeUID", "stubPKCS10Request"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import (
|
|||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
|
@ -742,18 +741,14 @@ func (m *IssuingManager) createPodCertificateRequest(
|
|||
podName string, podUID types.UID,
|
||||
serviceAccountName string, serviceAccountUID types.UID,
|
||||
nodeName types.NodeName, nodeUID types.UID,
|
||||
signerName, keyType string, maxExpirationSeconds *int32, userAnnotations map[string]string) ([]byte, *certificatesv1beta1.PodCertificateRequest, error) {
|
||||
|
||||
privateKey, publicKey, proof, err := generateKeyAndProof(keyType, []byte(podUID))
|
||||
signerName, keyType string, maxExpirationSeconds *int32,
|
||||
userAnnotations map[string]string,
|
||||
) ([]byte, *certificatesv1beta1.PodCertificateRequest, error) {
|
||||
privateKey, pkcs10Req, err := generateKeyAndProof(keyType)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("while generating keypair: %w", err)
|
||||
}
|
||||
|
||||
pkixPublicKey, err := x509.MarshalPKIXPublicKey(publicKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("while marshaling public key: %w", err)
|
||||
}
|
||||
|
||||
keyPEM, err := pemEncodeKey(privateKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("while PEM-encoding private key: %w", err)
|
||||
|
|
@ -781,8 +776,7 @@ func (m *IssuingManager) createPodCertificateRequest(
|
|||
NodeName: nodeName,
|
||||
NodeUID: nodeUID,
|
||||
MaxExpirationSeconds: maxExpirationSeconds,
|
||||
PKIXPublicKey: pkixPublicKey,
|
||||
ProofOfPossession: proof,
|
||||
StubPKCS10Request: pkcs10Req,
|
||||
UnverifiedUserAnnotations: userAnnotations,
|
||||
},
|
||||
}
|
||||
|
|
@ -877,73 +871,57 @@ func (m *IssuingManager) MetricReport() *MetricReport {
|
|||
return report
|
||||
}
|
||||
|
||||
func hashBytes(in []byte) []byte {
|
||||
out := sha256.Sum256(in)
|
||||
return out[:]
|
||||
}
|
||||
func generateKeyAndProof(keyType string) (crypto.PrivateKey, []byte, error) {
|
||||
var privKey crypto.PrivateKey
|
||||
|
||||
func generateKeyAndProof(keyType string, toBeSigned []byte) (privKey crypto.PrivateKey, pubKey crypto.PublicKey, sig []byte, err error) {
|
||||
switch keyType {
|
||||
case "RSA3072":
|
||||
key, err := rsa.GenerateKey(rand.Reader, 3072)
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 3072)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while generating RSA 3072 key: %w", err)
|
||||
return nil, nil, fmt.Errorf("while generating RSA 3072 key: %w", err)
|
||||
}
|
||||
sig, err := rsa.SignPSS(rand.Reader, key, crypto.SHA256, hashBytes(toBeSigned), nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while signing proof: %w", err)
|
||||
}
|
||||
return key, &key.PublicKey, sig, nil
|
||||
privKey = priv
|
||||
case "RSA4096":
|
||||
key, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while generating RSA 4096 key: %w", err)
|
||||
return nil, nil, fmt.Errorf("while generating RSA 4096 key: %w", err)
|
||||
}
|
||||
sig, err := rsa.SignPSS(rand.Reader, key, crypto.SHA256, hashBytes(toBeSigned), nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while signing proof: %w", err)
|
||||
}
|
||||
return key, &key.PublicKey, sig, nil
|
||||
privKey = priv
|
||||
case "ECDSAP256":
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while generating ECDSA P256 key: %w", err)
|
||||
return nil, nil, fmt.Errorf("while generating ECDSA P256 key: %w", err)
|
||||
}
|
||||
sig, err := ecdsa.SignASN1(rand.Reader, key, hashBytes(toBeSigned))
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while signing proof: %w", err)
|
||||
}
|
||||
return key, &key.PublicKey, sig, nil
|
||||
privKey = priv
|
||||
case "ECDSAP384":
|
||||
key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while generating ECDSA P384 key: %w", err)
|
||||
return nil, nil, fmt.Errorf("while generating ECDSA P384 key: %w", err)
|
||||
}
|
||||
sig, err := ecdsa.SignASN1(rand.Reader, key, hashBytes(toBeSigned))
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while signing proof: %w", err)
|
||||
}
|
||||
return key, &key.PublicKey, sig, nil
|
||||
privKey = priv
|
||||
case "ECDSAP521":
|
||||
key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while generating ECDSA P521 key: %w", err)
|
||||
return nil, nil, fmt.Errorf("while generating ECDSA P521 key: %w", err)
|
||||
}
|
||||
sig, err := ecdsa.SignASN1(rand.Reader, key, hashBytes(toBeSigned))
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while signing proof: %w", err)
|
||||
}
|
||||
return key, &key.PublicKey, sig, nil
|
||||
privKey = priv
|
||||
case "ED25519":
|
||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
_, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("while generating Ed25519 key: %w", err)
|
||||
return nil, nil, fmt.Errorf("while generating Ed25519 key: %w", err)
|
||||
}
|
||||
sig := ed25519.Sign(priv, toBeSigned)
|
||||
return priv, pub, sig, nil
|
||||
privKey = priv
|
||||
default:
|
||||
return nil, nil, nil, fmt.Errorf("unknown key type %q", keyType)
|
||||
return nil, nil, fmt.Errorf("unknown key type %q", keyType)
|
||||
}
|
||||
|
||||
tmpl := &x509.CertificateRequest{}
|
||||
pkcs10Req, err := x509.CreateCertificateRequest(rand.Reader, tmpl, privKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("while generating stub PKCS#10 request: %w", err)
|
||||
}
|
||||
|
||||
return privKey, pkcs10Req, nil
|
||||
}
|
||||
|
||||
func pemEncodeKey(key crypto.PrivateKey) ([]byte, error) {
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ func NewStatusStrategy(strategy *Strategy, authorizer authorizer.Authorizer, clo
|
|||
// and should not be modified by the user.
|
||||
func (s *StatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
|
||||
fields := map[fieldpath.APIVersion]*fieldpath.Set{
|
||||
"certificates.k8s.io/v1alpha1": fieldpath.NewSet(
|
||||
"certificates.k8s.io/v1beta1": fieldpath.NewSet(
|
||||
fieldpath.MakePathOrDie("spec"),
|
||||
),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -642,6 +642,13 @@ func (m *PodCertificateRequestSpec) MarshalToSizedBuffer(dAtA []byte) (int, erro
|
|||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.StubPKCS10Request != nil {
|
||||
i -= len(m.StubPKCS10Request)
|
||||
copy(dAtA[i:], m.StubPKCS10Request)
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.StubPKCS10Request)))
|
||||
i--
|
||||
dAtA[i] = 0x62
|
||||
}
|
||||
if len(m.UnverifiedUserAnnotations) > 0 {
|
||||
keysForUnverifiedUserAnnotations := make([]string, 0, len(m.UnverifiedUserAnnotations))
|
||||
for k := range m.UnverifiedUserAnnotations {
|
||||
|
|
@ -1058,6 +1065,10 @@ func (m *PodCertificateRequestSpec) Size() (n int) {
|
|||
n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
if m.StubPKCS10Request != nil {
|
||||
l = len(m.StubPKCS10Request)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
|
|
@ -1274,6 +1285,7 @@ func (this *PodCertificateRequestSpec) String() string {
|
|||
`PKIXPublicKey:` + valueToStringGenerated(this.PKIXPublicKey) + `,`,
|
||||
`ProofOfPossession:` + valueToStringGenerated(this.ProofOfPossession) + `,`,
|
||||
`UnverifiedUserAnnotations:` + mapStringForUnverifiedUserAnnotations + `,`,
|
||||
`StubPKCS10Request:` + valueToStringGenerated(this.StubPKCS10Request) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
|
|
@ -3490,6 +3502,40 @@ func (m *PodCertificateRequestSpec) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
m.UnverifiedUserAnnotations[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
case 12:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field StubPKCS10Request", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.StubPKCS10Request = append(m.StubPKCS10Request[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.StubPKCS10Request == nil {
|
||||
m.StubPKCS10Request = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
|
|
|
|||
|
|
@ -369,8 +369,7 @@ message PodCertificateRequestSpec {
|
|||
// +default=86400
|
||||
optional int32 maxExpirationSeconds = 8;
|
||||
|
||||
// pkixPublicKey is the PKIX-serialized public key the signer will issue the
|
||||
// certificate to.
|
||||
// The PKIX-serialized public key the signer will issue the certificate to.
|
||||
//
|
||||
// The key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521,
|
||||
// or ED25519. Note that this list may be expanded in the future.
|
||||
|
|
@ -382,11 +381,16 @@ message PodCertificateRequestSpec {
|
|||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// +required
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty. Signer
|
||||
// implementations should extract the public key from the StubPKCS10Request
|
||||
// field.
|
||||
//
|
||||
// +optional
|
||||
optional bytes pkixPublicKey = 9;
|
||||
|
||||
// proofOfPossession proves that the requesting kubelet holds the private
|
||||
// key corresponding to pkixPublicKey.
|
||||
// A proof that the requesting kubelet holds the private key corresponding
|
||||
// to pkixPublicKey.
|
||||
//
|
||||
// It is contructed by signing the ASCII bytes of the pod's UID using
|
||||
// `pkixPublicKey`.
|
||||
|
|
@ -403,12 +407,42 @@ message PodCertificateRequestSpec {
|
|||
// golang library function crypto/ecdsa.SignASN1)
|
||||
//
|
||||
// If the key is an ED25519 key, the the signature is as described by the
|
||||
// [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by
|
||||
// the golang library crypto/ed25519.Sign).
|
||||
// [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the
|
||||
// golang library crypto/ed25519.Sign).
|
||||
//
|
||||
// +required
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty.
|
||||
//
|
||||
// +optional
|
||||
optional bytes proofOfPossession = 10;
|
||||
|
||||
// A PKCS#10 certificate signing request (DER-serialized) generated by
|
||||
// Kubelet using the subject private key.
|
||||
//
|
||||
// Most signer implementations will ignore the contents of the CSR except to
|
||||
// extract the subject public key. The API server automatically verifies the
|
||||
// CSR signature during admission, so the signer does not need to repeat the
|
||||
// verification.
|
||||
//
|
||||
// The subject public key must be one of RSA3072, RSA4096, ECDSAP256,
|
||||
// ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in
|
||||
// the future.
|
||||
//
|
||||
// Signer implementations do not need to support all key types supported by
|
||||
// kube-apiserver and kubelet. If a signer does not support the key type
|
||||
// used for a given PodCertificateRequest, it must deny the request by
|
||||
// setting a status.conditions entry with a type of "Denied" and a reason of
|
||||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// Some CA implementations require that the client (the signer
|
||||
// implementation, in this case) provide a PKCS#10 certificate signing
|
||||
// request, even if the CA only extracts the subject public key from the
|
||||
// request. To enable compatibility with these CAs, Kubelet will generate a
|
||||
// stub PKCS#10 request that the signer implementation can then pass on to
|
||||
// the CA.
|
||||
optional bytes stubPKCS10Request = 12;
|
||||
|
||||
// unverifiedUserAnnotations allow pod authors to pass additional information to
|
||||
// the signer implementation. Kubernetes does not restrict or validate this
|
||||
// metadata in any way.
|
||||
|
|
|
|||
|
|
@ -438,8 +438,7 @@ type PodCertificateRequestSpec struct {
|
|||
// +default=86400
|
||||
MaxExpirationSeconds *int32 `json:"maxExpirationSeconds,omitempty" protobuf:"varint,8,opt,name=maxExpirationSeconds"`
|
||||
|
||||
// pkixPublicKey is the PKIX-serialized public key the signer will issue the
|
||||
// certificate to.
|
||||
// The PKIX-serialized public key the signer will issue the certificate to.
|
||||
//
|
||||
// The key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521,
|
||||
// or ED25519. Note that this list may be expanded in the future.
|
||||
|
|
@ -451,11 +450,16 @@ type PodCertificateRequestSpec struct {
|
|||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// +required
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty. Signer
|
||||
// implementations should extract the public key from the StubPKCS10Request
|
||||
// field.
|
||||
//
|
||||
// +optional
|
||||
PKIXPublicKey []byte `json:"pkixPublicKey" protobuf:"bytes,9,opt,name=pkixPublicKey"`
|
||||
|
||||
// proofOfPossession proves that the requesting kubelet holds the private
|
||||
// key corresponding to pkixPublicKey.
|
||||
// A proof that the requesting kubelet holds the private key corresponding
|
||||
// to pkixPublicKey.
|
||||
//
|
||||
// It is contructed by signing the ASCII bytes of the pod's UID using
|
||||
// `pkixPublicKey`.
|
||||
|
|
@ -472,12 +476,42 @@ type PodCertificateRequestSpec struct {
|
|||
// golang library function crypto/ecdsa.SignASN1)
|
||||
//
|
||||
// If the key is an ED25519 key, the the signature is as described by the
|
||||
// [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by
|
||||
// the golang library crypto/ed25519.Sign).
|
||||
// [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the
|
||||
// golang library crypto/ed25519.Sign).
|
||||
//
|
||||
// +required
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty.
|
||||
//
|
||||
// +optional
|
||||
ProofOfPossession []byte `json:"proofOfPossession" protobuf:"bytes,10,opt,name=proofOfPossession"`
|
||||
|
||||
// A PKCS#10 certificate signing request (DER-serialized) generated by
|
||||
// Kubelet using the subject private key.
|
||||
//
|
||||
// Most signer implementations will ignore the contents of the CSR except to
|
||||
// extract the subject public key. The API server automatically verifies the
|
||||
// CSR signature during admission, so the signer does not need to repeat the
|
||||
// verification.
|
||||
//
|
||||
// The subject public key must be one of RSA3072, RSA4096, ECDSAP256,
|
||||
// ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in
|
||||
// the future.
|
||||
//
|
||||
// Signer implementations do not need to support all key types supported by
|
||||
// kube-apiserver and kubelet. If a signer does not support the key type
|
||||
// used for a given PodCertificateRequest, it must deny the request by
|
||||
// setting a status.conditions entry with a type of "Denied" and a reason of
|
||||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// Some CA implementations require that the client (the signer
|
||||
// implementation, in this case) provide a PKCS#10 certificate signing
|
||||
// request, even if the CA only extracts the subject public key from the
|
||||
// request. To enable compatibility with these CAs, Kubelet will generate a
|
||||
// stub PKCS#10 request that the signer implementation can then pass on to
|
||||
// the CA.
|
||||
StubPKCS10Request []byte `json:"stubPKCS10Request" protobuf:"bytes,12,opt,name=stubPKCS10Request"`
|
||||
|
||||
// unverifiedUserAnnotations allow pod authors to pass additional information to
|
||||
// the signer implementation. Kubernetes does not restrict or validate this
|
||||
// metadata in any way.
|
||||
|
|
|
|||
|
|
@ -136,8 +136,9 @@ var map_PodCertificateRequestSpec = map[string]string{
|
|||
"nodeName": "nodeName is the name of the node the pod is assigned to.",
|
||||
"nodeUID": "nodeUID is the UID of the node the pod is assigned to.",
|
||||
"maxExpirationSeconds": "maxExpirationSeconds is the maximum lifetime permitted for the certificate.\n\nIf omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver will reject values shorter than 3600 (1 hour). The maximum allowable value is 7862400 (91 days).\n\nThe signer implementation is then free to issue a certificate with any lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 seconds (1 hour). This constraint is enforced by kube-apiserver. `kubernetes.io` signers will never issue certificates with a lifetime longer than 24 hours.",
|
||||
"pkixPublicKey": "pkixPublicKey is the PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.",
|
||||
"proofOfPossession": "proofOfPossession proves that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).",
|
||||
"pkixPublicKey": "The PKIX-serialized public key the signer will issue the certificate to.\n\nThe key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty. Signer implementations should extract the public key from the StubPKCS10Request field.",
|
||||
"proofOfPossession": "A proof that the requesting kubelet holds the private key corresponding to pkixPublicKey.\n\nIt is contructed by signing the ASCII bytes of the pod's UID using `pkixPublicKey`.\n\nkube-apiserver validates the proof of possession during creation of the PodCertificateRequest.\n\nIf the key is an RSA key, then the signature is over the ASCII bytes of the pod UID, using RSASSA-PSS from RFC 8017 (as implemented by the golang function crypto/rsa.SignPSS with nil options).\n\nIf the key is an ECDSA key, then the signature is as described by [SEC 1, Version 2.0](https://www.secg.org/sec1-v2.pdf) (as implemented by the golang library function crypto/ecdsa.SignASN1)\n\nIf the key is an ED25519 key, the the signature is as described by the [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the golang library crypto/ed25519.Sign).\n\nDEPRECATED: This field is replaced by StubPKCS10Request. If StubPKCS10Request is set, this field must be empty.",
|
||||
"stubPKCS10Request": "A PKCS#10 certificate signing request (DER-serialized) generated by Kubelet using the subject private key.\n\nMost signer implementations will ignore the contents of the CSR except to extract the subject public key. The API server automatically verifies the CSR signature during admission, so the signer does not need to repeat the verification.\n\nThe subject public key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in the future.\n\nSigner implementations do not need to support all key types supported by kube-apiserver and kubelet. If a signer does not support the key type used for a given PodCertificateRequest, it must deny the request by setting a status.conditions entry with a type of \"Denied\" and a reason of \"UnsupportedKeyType\". It may also suggest a key type that it does support in the message field.\n\nSome CA implementations require that the client (the signer implementation, in this case) provide a PKCS#10 certificate signing request, even if the CA only extracts the subject public key from the request. To enable compatibility with these CAs, Kubelet will generate a stub PKCS#10 request that the signer implementation can then pass on to the CA.",
|
||||
"unverifiedUserAnnotations": "unverifiedUserAnnotations allow pod authors to pass additional information to the signer implementation. Kubernetes does not restrict or validate this metadata in any way.\n\nEntries are subject to the same validation as object metadata annotations, with the addition that all keys must be domain-prefixed. No restrictions are placed on values, except an overall size limitation on the entire field.\n\nSigners should document the keys and values they support. Signers should deny requests that contain keys they do not recognize.",
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -364,6 +364,11 @@ func (in *PodCertificateRequestSpec) DeepCopyInto(out *PodCertificateRequestSpec
|
|||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.StubPKCS10Request != nil {
|
||||
in, out := &in.StubPKCS10Request, &out.StubPKCS10Request
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.UnverifiedUserAnnotations != nil {
|
||||
in, out := &in.UnverifiedUserAnnotations, &out.UnverifiedUserAnnotations
|
||||
*out = make(map[string]string, len(*in))
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
"maxExpirationSeconds": 8,
|
||||
"pkixPublicKey": "CQ==",
|
||||
"proofOfPossession": "Cg==",
|
||||
"stubPKCS10Request": "DA==",
|
||||
"unverifiedUserAnnotations": {
|
||||
"unverifiedUserAnnotationsKey": "unverifiedUserAnnotationsValue"
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -43,6 +43,7 @@ spec:
|
|||
serviceAccountName: serviceAccountNameValue
|
||||
serviceAccountUID: serviceAccountUIDValue
|
||||
signerName: signerNameValue
|
||||
stubPKCS10Request: DA==
|
||||
unverifiedUserAnnotations:
|
||||
unverifiedUserAnnotationsKey: unverifiedUserAnnotationsValue
|
||||
status:
|
||||
|
|
|
|||
|
|
@ -62,8 +62,7 @@ type PodCertificateRequestSpecApplyConfiguration struct {
|
|||
// `kubernetes.io` signers will never issue certificates with a lifetime
|
||||
// longer than 24 hours.
|
||||
MaxExpirationSeconds *int32 `json:"maxExpirationSeconds,omitempty"`
|
||||
// pkixPublicKey is the PKIX-serialized public key the signer will issue the
|
||||
// certificate to.
|
||||
// The PKIX-serialized public key the signer will issue the certificate to.
|
||||
//
|
||||
// The key must be one of RSA3072, RSA4096, ECDSAP256, ECDSAP384, ECDSAP521,
|
||||
// or ED25519. Note that this list may be expanded in the future.
|
||||
|
|
@ -74,9 +73,14 @@ type PodCertificateRequestSpecApplyConfiguration struct {
|
|||
// setting a status.conditions entry with a type of "Denied" and a reason of
|
||||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty. Signer
|
||||
// implementations should extract the public key from the StubPKCS10Request
|
||||
// field.
|
||||
PKIXPublicKey []byte `json:"pkixPublicKey,omitempty"`
|
||||
// proofOfPossession proves that the requesting kubelet holds the private
|
||||
// key corresponding to pkixPublicKey.
|
||||
// A proof that the requesting kubelet holds the private key corresponding
|
||||
// to pkixPublicKey.
|
||||
//
|
||||
// It is contructed by signing the ASCII bytes of the pod's UID using
|
||||
// `pkixPublicKey`.
|
||||
|
|
@ -93,9 +97,38 @@ type PodCertificateRequestSpecApplyConfiguration struct {
|
|||
// golang library function crypto/ecdsa.SignASN1)
|
||||
//
|
||||
// If the key is an ED25519 key, the the signature is as described by the
|
||||
// [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by
|
||||
// the golang library crypto/ed25519.Sign).
|
||||
// [ED25519 Specification](https://ed25519.cr.yp.to/) (as implemented by the
|
||||
// golang library crypto/ed25519.Sign).
|
||||
//
|
||||
// DEPRECATED: This field is replaced by StubPKCS10Request. If
|
||||
// StubPKCS10Request is set, this field must be empty.
|
||||
ProofOfPossession []byte `json:"proofOfPossession,omitempty"`
|
||||
// A PKCS#10 certificate signing request (DER-serialized) generated by
|
||||
// Kubelet using the subject private key.
|
||||
//
|
||||
// Most signer implementations will ignore the contents of the CSR except to
|
||||
// extract the subject public key. The API server automatically verifies the
|
||||
// CSR signature during admission, so the signer does not need to repeat the
|
||||
// verification.
|
||||
//
|
||||
// The subject public key must be one of RSA3072, RSA4096, ECDSAP256,
|
||||
// ECDSAP384, ECDSAP521, or ED25519. Note that this list may be expanded in
|
||||
// the future.
|
||||
//
|
||||
// Signer implementations do not need to support all key types supported by
|
||||
// kube-apiserver and kubelet. If a signer does not support the key type
|
||||
// used for a given PodCertificateRequest, it must deny the request by
|
||||
// setting a status.conditions entry with a type of "Denied" and a reason of
|
||||
// "UnsupportedKeyType". It may also suggest a key type that it does support
|
||||
// in the message field.
|
||||
//
|
||||
// Some CA implementations require that the client (the signer
|
||||
// implementation, in this case) provide a PKCS#10 certificate signing
|
||||
// request, even if the CA only extracts the subject public key from the
|
||||
// request. To enable compatibility with these CAs, Kubelet will generate a
|
||||
// stub PKCS#10 request that the signer implementation can then pass on to
|
||||
// the CA.
|
||||
StubPKCS10Request []byte `json:"stubPKCS10Request,omitempty"`
|
||||
// unverifiedUserAnnotations allow pod authors to pass additional information to
|
||||
// the signer implementation. Kubernetes does not restrict or validate this
|
||||
// metadata in any way.
|
||||
|
|
@ -199,6 +232,16 @@ func (b *PodCertificateRequestSpecApplyConfiguration) WithProofOfPossession(valu
|
|||
return b
|
||||
}
|
||||
|
||||
// WithStubPKCS10Request adds the given value to the StubPKCS10Request field in the declarative configuration
|
||||
// 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 StubPKCS10Request field.
|
||||
func (b *PodCertificateRequestSpecApplyConfiguration) WithStubPKCS10Request(values ...byte) *PodCertificateRequestSpecApplyConfiguration {
|
||||
for i := range values {
|
||||
b.StubPKCS10Request = append(b.StubPKCS10Request, values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithUnverifiedUserAnnotations puts the entries into the UnverifiedUserAnnotations field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, the entries provided by each call will be put on the UnverifiedUserAnnotations field,
|
||||
|
|
|
|||
|
|
@ -3983,6 +3983,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
|||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: stubPKCS10Request
|
||||
type:
|
||||
scalar: string
|
||||
- name: unverifiedUserAnnotations
|
||||
type:
|
||||
map:
|
||||
|
|
|
|||
|
|
@ -229,9 +229,9 @@ func (c *Controller) handlePCR(ctx context.Context, pcr *certsv1beta1.PodCertifi
|
|||
return nil
|
||||
}
|
||||
|
||||
subjectPublicKey, err := x509.ParsePKIXPublicKey(pcr.Spec.PKIXPublicKey)
|
||||
req, err := x509.ParseCertificateRequest(pcr.Spec.StubPKCS10Request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("while parsing subject public key: %w", err)
|
||||
return fmt.Errorf("while parsing PKCS#10 request: %w", err)
|
||||
}
|
||||
|
||||
// If our signer had an opinion on which key types were allowable, it would
|
||||
|
|
@ -276,7 +276,7 @@ func (c *Controller) handlePCR(ctx context.Context, pcr *certsv1beta1.PodCertifi
|
|||
return fmt.Errorf("while parsing signing certificate: %w", err)
|
||||
}
|
||||
|
||||
subjectCertDER, err := x509.CreateCertificate(rand.Reader, template, signingCert, subjectPublicKey, c.caKeys[len(c.caKeys)-1])
|
||||
subjectCertDER, err := x509.CreateCertificate(rand.Reader, template, signingCert, req.PublicKey, c.caKeys[len(c.caKeys)-1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("while signing subject cert: %w", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue