This repository has been archived by the owner on Sep 17, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
certs.go
116 lines (101 loc) · 4.21 KB
/
certs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// copy-paste functions from k8s.io/kubernetes/cmd/kubeadm/app/phases/certs
package main
import (
"crypto"
"crypto/x509"
"fmt"
"github.com/pkg/errors"
certutil "k8s.io/client-go/util/cert"
pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
)
// writeCertificateAuthorityFilesIfNotExist write a new certificate Authority to the given path.
// If there already is a certificate file at the given path; kubeadm tries to load it and check if the values in the
// existing and the expected certificate equals. If they do; kubeadm will just skip writing the file as it's up-to-date,
// otherwise this function returns an error.
func writeCertificateAuthorityFilesIfNotExist(
pkiDir string,
baseName string,
caCert *x509.Certificate,
caKey crypto.Signer) error {
// If cert or key exists, we should try to load them
if pkiutil.CertOrKeyExist(pkiDir, baseName) {
// Try to load .crt and .key from the PKI directory
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkiDir, baseName)
if err != nil {
return errors.Wrapf(err, "failure loading %s certificate", baseName)
}
// Check if the existing cert is a CA
if !caCert.IsCA {
return errors.Errorf("certificate %s is not a CA", baseName)
}
// kubeadm doesn't validate the existing certificate Authority more than this;
// Basically, if we find a certificate file with the same path; and it is a CA
// kubeadm thinks those files are equal and doesn't bother writing a new file
fmt.Printf("[certs] Using the existing %q certificate and key\n", baseName)
} else {
// Write .crt and .key files to disk
fmt.Printf("[certs] Generating %q certificate and key\n", baseName)
if err := pkiutil.WriteCertAndKey(pkiDir, baseName, caCert, caKey); err != nil {
return errors.Wrapf(err, "failure while saving %s certificate and key", baseName)
}
}
return nil
}
// writeCertificateFilesIfNotExist write a new certificate to the given path.
// If there already is a certificate file at the given path; kubeadm tries to load it and check if the values in the
// existing and the expected certificate equals. If they do; kubeadm will just skip writing the file as it's up-to-date,
// otherwise this function returns an error.
func writeCertificateFilesIfNotExist(
pkiDir string,
baseName string,
signingCert *x509.Certificate,
cert *x509.Certificate,
key crypto.Signer,
cfg *certutil.Config) error {
// Checks if the signed certificate exists in the PKI directory
if pkiutil.CertOrKeyExist(pkiDir, baseName) {
// Try to load signed certificate .crt and .key from the PKI directory
signedCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkiDir, baseName)
if err != nil {
return errors.Wrapf(err, "failure loading %s certificate", baseName)
}
// Check if the existing cert is signed by the given CA
if err := signedCert.CheckSignatureFrom(signingCert); err != nil {
return errors.Errorf("certificate %s is not signed by corresponding CA", baseName)
}
// Check if the certificate has the correct attributes
if err := validateCertificateWithConfig(signedCert, baseName, cfg); err != nil {
return err
}
fmt.Printf("[certs] Using the existing %q certificate and key\n", baseName)
} else {
// Write .crt and .key files to disk
fmt.Printf("[certs] Generating %q certificate and key\n", baseName)
if err := pkiutil.WriteCertAndKey(pkiDir, baseName, cert, key); err != nil {
return errors.Wrapf(err, "failure while saving %s certificate and key", baseName)
}
if pkiutil.HasServerAuth(cert) {
fmt.Printf(
"[certs] %s serving cert is signed for DNS names %v and IPs %v\n",
baseName,
cert.DNSNames,
cert.IPAddresses)
}
}
return nil
}
// validateCertificateWithConfig makes sure that a given certificate is valid at
// least for the SANs defined in the configuration.
func validateCertificateWithConfig(cert *x509.Certificate, baseName string, cfg *certutil.Config) error {
for _, dnsName := range cfg.AltNames.DNSNames {
if err := cert.VerifyHostname(dnsName); err != nil {
return errors.Wrapf(err, "certificate %s is invalid", baseName)
}
}
for _, ipAddress := range cfg.AltNames.IPs {
if err := cert.VerifyHostname(ipAddress.String()); err != nil {
return errors.Wrapf(err, "certificate %s is invalid", baseName)
}
}
return nil
}