mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 06:27:05 +00:00
Collapse duplicate code into pkg/util/csr
There is no reason to duplicate this code into two places.
This commit is contained in:
parent
de3d7d1881
commit
c3bea24ab6
@ -68,16 +68,16 @@ func RequestNodeCertificate(client certificatesclient.CertificateSigningRequestI
|
|||||||
certificates.UsageClientAuth,
|
certificates.UsageClientAuth,
|
||||||
}
|
}
|
||||||
name := digestedName(privateKeyData, subject, usages)
|
name := digestedName(privateKeyData, subject, usages)
|
||||||
return requestCertificate(client, csrData, name, usages, privateKey)
|
return RequestCertificate(client, csrData, name, usages, privateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, then it will watch the object's
|
// PEM encoded CSR and send it to API server, then it will watch the object's
|
||||||
// status, once approved by API server, it will return the API server's issued
|
// status, once approved by API server, it will return the API server's issued
|
||||||
// certificate (pem-encoded). If there is any errors, or the watch timeouts, it
|
// certificate (pem-encoded). If there is any errors, or the watch timeouts, it
|
||||||
// will return an error.
|
// will return an error.
|
||||||
func requestCertificate(client certificatesclient.CertificateSigningRequestInterface, csrData []byte, name string, usages []certificates.KeyUsage, privateKey interface{}) (certData []byte, err error) {
|
func RequestCertificate(client certificatesclient.CertificateSigningRequestInterface, csrData []byte, name string, usages []certificates.KeyUsage, privateKey interface{}) (certData []byte, err error) {
|
||||||
csr := &certificates.CertificateSigningRequest{
|
csr := &certificates.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"},
|
||||||
@ -89,11 +89,14 @@ func requestCertificate(client certificatesclient.CertificateSigningRequestInter
|
|||||||
Usages: usages,
|
Usages: usages,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if len(csr.Name) == 0 {
|
||||||
|
csr.GenerateName = "csr-"
|
||||||
|
}
|
||||||
|
|
||||||
req, err := client.Create(csr)
|
req, err := client.Create(csr)
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
case errors.IsAlreadyExists(err):
|
case errors.IsAlreadyExists(err) && len(name) > 0:
|
||||||
glog.Infof("csr for this node already exists, reusing")
|
glog.Infof("csr for this node already exists, reusing")
|
||||||
req, err = client.Get(name, metav1.GetOptions{})
|
req, err = client.Get(name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -149,7 +152,6 @@ func requestCertificate(client certificatesclient.CertificateSigningRequestInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
return event.Object.(*certificates.CertificateSigningRequest).Status.Certificate, nil
|
return event.Object.(*certificates.CertificateSigningRequest).Status.Certificate, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This digest should include all the relevant pieces of the CSR we care about.
|
// This digest should include all the relevant pieces of the CSR we care about.
|
||||||
|
@ -35,12 +35,10 @@ go_library(
|
|||||||
importpath = "k8s.io/client-go/util/certificate",
|
importpath = "k8s.io/client-go/util/certificate",
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/kubelet/util/csr:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
|
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library",
|
"//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -30,12 +30,10 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
certificates "k8s.io/api/certificates/v1beta1"
|
certificates "k8s.io/api/certificates/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
|
certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
|
||||||
"k8s.io/client-go/util/cert"
|
"k8s.io/client-go/util/cert"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/util/csr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Manager maintains and updates the certificates in use by this certificate
|
// Manager maintains and updates the certificates in use by this certificate
|
||||||
@ -278,7 +276,7 @@ func (m *manager) shouldRotate() bool {
|
|||||||
func (m *manager) rotateCerts() (bool, error) {
|
func (m *manager) rotateCerts() (bool, error) {
|
||||||
glog.V(2).Infof("Rotating certificates")
|
glog.V(2).Infof("Rotating certificates")
|
||||||
|
|
||||||
csrPEM, keyPEM, err := m.generateCSR()
|
csrPEM, keyPEM, privateKey, err := m.generateCSR()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Unable to generate a certificate signing request: %v", err)
|
glog.Errorf("Unable to generate a certificate signing request: %v", err)
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -286,7 +284,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.
|
||||||
crtPEM, err := requestCertificate(m.certSigningRequestClient, csrPEM, m.usages)
|
crtPEM, err := csr.RequestCertificate(m.certSigningRequestClient, csrPEM, "", m.usages, privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed while requesting a signed certificate from the master: %v", err)
|
glog.Errorf("Failed while requesting a signed certificate from the master: %v", err)
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -343,85 +341,22 @@ func (m *manager) updateCached(cert *tls.Certificate) {
|
|||||||
m.cert = cert
|
m.cert = cert
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *manager) generateCSR() (csrPEM []byte, keyPEM []byte, err error) {
|
func (m *manager) generateCSR() (csrPEM []byte, keyPEM []byte, key interface{}, err error) {
|
||||||
// Generate a new private key.
|
// Generate a new private key.
|
||||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
|
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to generate a new private key: %v", err)
|
return nil, nil, nil, fmt.Errorf("unable to generate a new private key: %v", err)
|
||||||
}
|
}
|
||||||
der, err := x509.MarshalECPrivateKey(privateKey)
|
der, err := x509.MarshalECPrivateKey(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to marshal the new key to DER: %v", err)
|
return nil, nil, nil, fmt.Errorf("unable to marshal the new key to DER: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
keyPEM = pem.EncodeToMemory(&pem.Block{Type: cert.ECPrivateKeyBlockType, Bytes: der})
|
keyPEM = pem.EncodeToMemory(&pem.Block{Type: cert.ECPrivateKeyBlockType, Bytes: der})
|
||||||
|
|
||||||
csrPEM, err = cert.MakeCSRFromTemplate(privateKey, m.template)
|
csrPEM, err = cert.MakeCSRFromTemplate(privateKey, m.template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to create a csr from the private key: %v", err)
|
return nil, nil, nil, fmt.Errorf("unable to create a csr from the private key: %v", err)
|
||||||
}
|
}
|
||||||
return csrPEM, keyPEM, nil
|
return csrPEM, keyPEM, privateKey, nil
|
||||||
}
|
|
||||||
|
|
||||||
// requestCertificate will create a certificate signing request using the PEM
|
|
||||||
// encoded CSR and send it to API server, then it will watch the object's
|
|
||||||
// status, once approved by API server, it will return the API server's issued
|
|
||||||
// certificate (pem-encoded). If there is any errors, or the watch timeouts, it
|
|
||||||
// will return an error.
|
|
||||||
//
|
|
||||||
// NOTE This is a copy of a function with the same name in
|
|
||||||
// k8s.io/kubernetes/pkg/kubelet/util/csr/csr.go, changing only the package that
|
|
||||||
// CertificateSigningRequestInterface and KeyUsage are imported from.
|
|
||||||
func requestCertificate(client certificatesclient.CertificateSigningRequestInterface, csrData []byte, usages []certificates.KeyUsage) (certData []byte, err error) {
|
|
||||||
glog.Infof("Requesting new certificate.")
|
|
||||||
req, err := client.Create(&certificates.CertificateSigningRequest{
|
|
||||||
// Username, UID, Groups will be injected by API server.
|
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "CertificateSigningRequest"},
|
|
||||||
ObjectMeta: metav1.ObjectMeta{GenerateName: "csr-"},
|
|
||||||
|
|
||||||
Spec: certificates.CertificateSigningRequestSpec{
|
|
||||||
Request: csrData,
|
|
||||||
Usages: usages,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot create certificate signing request: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a default timeout = 3600s.
|
|
||||||
var defaultTimeoutSeconds int64 = 3600
|
|
||||||
certWatch, err := client.Watch(metav1.ListOptions{
|
|
||||||
Watch: true,
|
|
||||||
TimeoutSeconds: &defaultTimeoutSeconds,
|
|
||||||
FieldSelector: fields.OneTermEqualSelector("metadata.name", req.Name).String(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot watch on the certificate signing request: %v", err)
|
|
||||||
}
|
|
||||||
defer certWatch.Stop()
|
|
||||||
ch := certWatch.ResultChan()
|
|
||||||
|
|
||||||
for {
|
|
||||||
event, ok := <-ch
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if event.Type == watch.Modified || event.Type == watch.Added {
|
|
||||||
if event.Object.(*certificates.CertificateSigningRequest).UID != req.UID {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
status := event.Object.(*certificates.CertificateSigningRequest).Status
|
|
||||||
for _, c := range status.Conditions {
|
|
||||||
if c.Type == certificates.CertificateDenied {
|
|
||||||
return nil, fmt.Errorf("certificate signing request is not approved, reason: %v, message: %v", c.Reason, c.Message)
|
|
||||||
}
|
|
||||||
if c.Type == certificates.CertificateApproved && status.Certificate != nil {
|
|
||||||
return status.Certificate, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("watch channel closed")
|
|
||||||
}
|
}
|
||||||
|
@ -643,6 +643,18 @@ type fakeClient struct {
|
|||||||
certificatePEM []byte
|
certificatePEM []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c fakeClient) List(opts v1.ListOptions) (*certificates.CertificateSigningRequestList, error) {
|
||||||
|
if c.failureType == watchError {
|
||||||
|
return nil, fmt.Errorf("Watch error")
|
||||||
|
}
|
||||||
|
csrReply := certificates.CertificateSigningRequestList{
|
||||||
|
Items: []certificates.CertificateSigningRequest{
|
||||||
|
{ObjectMeta: v1.ObjectMeta{UID: "fake-uid"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &csrReply, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c fakeClient) Create(*certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, error) {
|
func (c fakeClient) Create(*certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, error) {
|
||||||
if c.failureType == createError {
|
if c.failureType == createError {
|
||||||
return nil, fmt.Errorf("Create error")
|
return nil, fmt.Errorf("Create error")
|
||||||
|
Loading…
Reference in New Issue
Block a user