123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- /*
- Copyright 2018 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package renewal
- import (
- "context"
- "crypto"
- "crypto/x509"
- "crypto/x509/pkix"
- "fmt"
- "time"
- "github.com/pkg/errors"
- certsapi "k8s.io/api/certificates/v1beta1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- clientset "k8s.io/client-go/kubernetes"
- certstype "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
- certutil "k8s.io/client-go/util/cert"
- csrutil "k8s.io/client-go/util/certificate/csr"
- pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
- )
- const certAPIPrefixName = "kubeadm-cert"
- var watchTimeout = 5 * time.Minute
- // APIRenewer define a certificate renewer implementation that uses the K8s certificate API
- type APIRenewer struct {
- client certstype.CertificatesV1beta1Interface
- }
- // NewAPIRenewer a new certificate renewer implementation that uses the K8s certificate API
- func NewAPIRenewer(client clientset.Interface) *APIRenewer {
- return &APIRenewer{
- client: client.CertificatesV1beta1(),
- }
- }
- // Renew a certificate using the K8s certificate API
- func (r *APIRenewer) Renew(cfg *pkiutil.CertConfig) (*x509.Certificate, crypto.Signer, error) {
- reqTmp := &x509.CertificateRequest{
- Subject: pkix.Name{
- CommonName: cfg.CommonName,
- Organization: cfg.Organization,
- },
- DNSNames: cfg.AltNames.DNSNames,
- IPAddresses: cfg.AltNames.IPs,
- }
- key, err := pkiutil.NewPrivateKey(cfg.PublicKeyAlgorithm)
- if err != nil {
- return nil, nil, errors.Wrap(err, "couldn't create new private key")
- }
- csr, err := certutil.MakeCSRFromTemplate(key, reqTmp)
- if err != nil {
- return nil, nil, errors.Wrap(err, "couldn't create certificate signing request")
- }
- usages := make([]certsapi.KeyUsage, len(cfg.Usages))
- for i, usage := range cfg.Usages {
- certsAPIUsage, ok := usageMap[usage]
- if !ok {
- return nil, nil, errors.Errorf("unknown key usage: %v", usage)
- }
- usages[i] = certsAPIUsage
- }
- k8sCSR := &certsapi.CertificateSigningRequest{
- ObjectMeta: metav1.ObjectMeta{
- GenerateName: fmt.Sprintf("%s-%s-", certAPIPrefixName, cfg.CommonName),
- },
- Spec: certsapi.CertificateSigningRequestSpec{
- Request: csr,
- Usages: usages,
- },
- }
- req, err := r.client.CertificateSigningRequests().Create(context.TODO(), k8sCSR, metav1.CreateOptions{})
- if err != nil {
- return nil, nil, errors.Wrap(err, "couldn't create certificate signing request")
- }
- fmt.Printf("[certs] Certificate request %q created\n", req.Name)
- ctx, cancel := context.WithTimeout(context.Background(), watchTimeout)
- defer cancel()
- certData, err := csrutil.WaitForCertificate(ctx, r.client.CertificateSigningRequests(), req)
- if err != nil {
- return nil, nil, errors.Wrap(err, "certificate failed to appear")
- }
- cert, err := certutil.ParseCertsPEM(certData)
- if err != nil {
- return nil, nil, errors.Wrap(err, "couldn't parse issued certificate")
- }
- if len(cert) != 1 {
- return nil, nil, errors.Errorf("certificate request %q has %d certificates, wanted exactly 1", req.Name, len(cert))
- }
- return cert[0], key, nil
- }
- var usageMap = map[x509.ExtKeyUsage]certsapi.KeyUsage{
- x509.ExtKeyUsageAny: certsapi.UsageAny,
- x509.ExtKeyUsageServerAuth: certsapi.UsageServerAuth,
- x509.ExtKeyUsageClientAuth: certsapi.UsageClientAuth,
- x509.ExtKeyUsageCodeSigning: certsapi.UsageCodeSigning,
- x509.ExtKeyUsageEmailProtection: certsapi.UsageEmailProtection,
- x509.ExtKeyUsageIPSECEndSystem: certsapi.UsageIPsecEndSystem,
- x509.ExtKeyUsageIPSECTunnel: certsapi.UsageIPsecTunnel,
- x509.ExtKeyUsageIPSECUser: certsapi.UsageIPsecUser,
- x509.ExtKeyUsageTimeStamping: certsapi.UsageTimestamping,
- x509.ExtKeyUsageOCSPSigning: certsapi.UsageOCSPSigning,
- x509.ExtKeyUsageMicrosoftServerGatedCrypto: certsapi.UsageMicrosoftSGC,
- x509.ExtKeyUsageNetscapeServerGatedCrypto: certsapi.UsageNetscapeSGC,
- }
|