mirror of https://github.com/k3s-io/k3s
Collapse duplicate code into pkg/util/csr
There is no reason to duplicate this code into two places.pull/6/head
parent
de3d7d1881
commit
c3bea24ab6
|
@ -68,16 +68,16 @@ func RequestNodeCertificate(client certificatesclient.CertificateSigningRequestI
|
|||
certificates.UsageClientAuth,
|
||||
}
|
||||
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
|
||||
// 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.
|
||||
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{
|
||||
// Username, UID, Groups will be injected by API server.
|
||||
TypeMeta: metav1.TypeMeta{Kind: "CertificateSigningRequest"},
|
||||
|
@ -89,11 +89,14 @@ func requestCertificate(client certificatesclient.CertificateSigningRequestInter
|
|||
Usages: usages,
|
||||
},
|
||||
}
|
||||
if len(csr.Name) == 0 {
|
||||
csr.GenerateName = "csr-"
|
||||
}
|
||||
|
||||
req, err := client.Create(csr)
|
||||
switch {
|
||||
case err == nil:
|
||||
case errors.IsAlreadyExists(err):
|
||||
case errors.IsAlreadyExists(err) && len(name) > 0:
|
||||
glog.Infof("csr for this node already exists, reusing")
|
||||
req, err = client.Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
|
@ -149,7 +152,6 @@ func requestCertificate(client certificatesclient.CertificateSigningRequestInter
|
|||
}
|
||||
|
||||
return event.Object.(*certificates.CertificateSigningRequest).Status.Certificate, nil
|
||||
|
||||
}
|
||||
|
||||
// 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",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/kubelet/util/csr:go_default_library",
|
||||
"//vendor/github.com/golang/glog: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/watch: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",
|
||||
],
|
||||
|
|
|
@ -30,12 +30,10 @@ import (
|
|||
"github.com/golang/glog"
|
||||
|
||||
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/watch"
|
||||
certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
|
||||
"k8s.io/client-go/util/cert"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/csr"
|
||||
)
|
||||
|
||||
// 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) {
|
||||
glog.V(2).Infof("Rotating certificates")
|
||||
|
||||
csrPEM, keyPEM, err := m.generateCSR()
|
||||
csrPEM, keyPEM, privateKey, err := m.generateCSR()
|
||||
if err != nil {
|
||||
glog.Errorf("Unable to generate a certificate signing request: %v", err)
|
||||
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
|
||||
// new private key.
|
||||
crtPEM, err := requestCertificate(m.certSigningRequestClient, csrPEM, m.usages)
|
||||
crtPEM, err := csr.RequestCertificate(m.certSigningRequestClient, csrPEM, "", m.usages, privateKey)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed while requesting a signed certificate from the master: %v", err)
|
||||
return false, nil
|
||||
|
@ -343,85 +341,22 @@ func (m *manager) updateCached(cert *tls.Certificate) {
|
|||
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.
|
||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
|
||||
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)
|
||||
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})
|
||||
|
||||
csrPEM, err = cert.MakeCSRFromTemplate(privateKey, m.template)
|
||||
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
|
||||
}
|
||||
|
||||
// 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")
|
||||
return csrPEM, keyPEM, privateKey, nil
|
||||
}
|
||||
|
|
|
@ -643,6 +643,18 @@ type fakeClient struct {
|
|||
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) {
|
||||
if c.failureType == createError {
|
||||
return nil, fmt.Errorf("Create error")
|
||||
|
|
Loading…
Reference in New Issue