mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #67208 from liztio/cert-list
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. First pass of cert list **What this PR does / why we need it**: Refactors the cert management code in kubeadm to be more extensible and resiliant. This initial change doesn't change anything on the surface, and in fact appears to add a bunch of complexity. The goal here is to reduce duplication in the certs codebase, which is started in this PR by gutting the New*CertAndKey. Eventually, those functions will be removed altogether. The declarative list will also allow us to build a more explicit renewal function and command line interface and reduce much more duplication in the cert package. **Special notes for your reviewer**: **Release note**: ``` ```
This commit is contained in:
commit
68cfa7ef10
@ -8,7 +8,10 @@ load(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["certs_test.go"],
|
||||
srcs = [
|
||||
"certlist_test.go",
|
||||
"certs_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
@ -16,12 +19,14 @@ go_test(
|
||||
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
|
||||
"//cmd/kubeadm/test:go_default_library",
|
||||
"//cmd/kubeadm/test/certs:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"certlist.go",
|
||||
"certs.go",
|
||||
"doc.go",
|
||||
],
|
||||
|
303
cmd/kubeadm/app/phases/certs/certlist.go
Normal file
303
cmd/kubeadm/app/phases/certs/certlist.go
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
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 certs
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
)
|
||||
|
||||
type configMutatorsFunc func(*kubeadmapi.InitConfiguration, *certutil.Config) error
|
||||
|
||||
// KubeadmCert represents a certificate that Kubeadm will create to function properly.
|
||||
type KubeadmCert struct {
|
||||
Name string
|
||||
BaseName string
|
||||
CAName string
|
||||
// Some attributes will depend on the InitConfiguration, only known at runtime.
|
||||
// These functions will be run in series, passed both the InitConfiguration and a cert Config.
|
||||
configMutators []configMutatorsFunc
|
||||
config certutil.Config
|
||||
}
|
||||
|
||||
// GetConfig returns the definition for the given cert given the provided InitConfiguration
|
||||
func (k *KubeadmCert) GetConfig(ic *kubeadmapi.InitConfiguration) (*certutil.Config, error) {
|
||||
for _, f := range k.configMutators {
|
||||
if err := f(ic, &k.config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &k.config, nil
|
||||
}
|
||||
|
||||
// CreateFromCA makes and writes a certificate using the given CA cert and key.
|
||||
func (k *KubeadmCert) CreateFromCA(ic *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) error {
|
||||
cfg, err := k.GetConfig(ic)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't create %q certificate: %v", k.Name, err)
|
||||
}
|
||||
cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, *cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writeCertificateAuthorithyFilesIfNotExist(
|
||||
ic.CertificatesDir,
|
||||
k.BaseName,
|
||||
cert,
|
||||
key,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CertificateTree is represents a one-level-deep tree, mapping a CA to the certs that depend on it.
|
||||
type CertificateTree map[*KubeadmCert]Certificates
|
||||
|
||||
// CreateTree creates the CAs, certs signed by the CAs, and writes them all to disk.
|
||||
func (t CertificateTree) CreateTree(ic *kubeadmapi.InitConfiguration) error {
|
||||
for ca, leaves := range t {
|
||||
// TODO: NewCACertAndKey should take an ic
|
||||
caCert, caKey, err := NewCACertAndKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, leaf := range leaves {
|
||||
if err := leaf.CreateFromCA(ic, caCert, caKey); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := writeCertificateAuthorithyFilesIfNotExist(
|
||||
ic.CertificatesDir,
|
||||
ca.BaseName,
|
||||
caCert,
|
||||
caKey,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CertificateMap is a flat map of certificates, keyed by Name.
|
||||
type CertificateMap map[string]*KubeadmCert
|
||||
|
||||
// CertTree returns a one-level-deep tree, mapping a CA cert to an array of certificates that should be signed by it.
|
||||
func (m CertificateMap) CertTree() (CertificateTree, error) {
|
||||
caMap := make(CertificateTree)
|
||||
|
||||
for _, cert := range m {
|
||||
if cert.CAName == "" {
|
||||
if _, ok := caMap[cert]; !ok {
|
||||
caMap[cert] = []*KubeadmCert{}
|
||||
}
|
||||
} else {
|
||||
ca, ok := m[cert.CAName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Certificate %q references unknown CA %q", cert.Name, cert.CAName)
|
||||
}
|
||||
caMap[ca] = append(caMap[ca], cert)
|
||||
}
|
||||
}
|
||||
|
||||
return caMap, nil
|
||||
}
|
||||
|
||||
// Certificates is a list of Certificates that Kubeadm should create.
|
||||
type Certificates []*KubeadmCert
|
||||
|
||||
// AsMap returns the list of certificates as a map, keyed by name.
|
||||
func (c Certificates) AsMap() CertificateMap {
|
||||
certMap := make(map[string]*KubeadmCert)
|
||||
for _, cert := range c {
|
||||
certMap[cert.Name] = cert
|
||||
}
|
||||
|
||||
return certMap
|
||||
}
|
||||
|
||||
// GetDefaultCertList returns all of the certificates kubeadm requires to function.
|
||||
func GetDefaultCertList() Certificates {
|
||||
return Certificates{
|
||||
&KubeadmCertRootCA,
|
||||
&KubeadmCertAPIServer,
|
||||
&KubeadmCertKubeletClient,
|
||||
// Front Proxy certs
|
||||
&KubeadmCertFrontProxyCA,
|
||||
&KubeadmCertFrontProxyClient,
|
||||
// etcd certs
|
||||
&KubeadmCertEtcdCA,
|
||||
&KubeadmCertEtcdServer,
|
||||
&KubeadmCertEtcdPeer,
|
||||
&KubeadmCertEtcdHealthcheck,
|
||||
&KubeadmCertEtcdAPIClient,
|
||||
}
|
||||
}
|
||||
|
||||
// GetCertsWithoutEtcd returns all of the certificates kubeadm needs when etcd is hosted externally.
|
||||
func GetCertsWithoutEtcd() Certificates {
|
||||
return Certificates{
|
||||
&KubeadmCertRootCA,
|
||||
&KubeadmCertAPIServer,
|
||||
&KubeadmCertKubeletClient,
|
||||
// Front Proxy certs
|
||||
&KubeadmCertFrontProxyCA,
|
||||
&KubeadmCertFrontProxyClient,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// KubeadmCertRootCA is the definition of the Kubernetes Root CA for the API Server and kubelet.
|
||||
KubeadmCertRootCA = KubeadmCert{
|
||||
Name: "root-ca",
|
||||
BaseName: kubeadmconstants.CACertAndKeyBaseName,
|
||||
config: certutil.Config{
|
||||
CommonName: "kubernetes",
|
||||
},
|
||||
}
|
||||
// KubeadmCertAPIServer is the definition of the cert used to serve the kubernetes API.
|
||||
KubeadmCertAPIServer = KubeadmCert{
|
||||
Name: "api-server",
|
||||
BaseName: kubeadmconstants.APIServerCertAndKeyBaseName,
|
||||
CAName: "root-ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerCertCommonName,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
},
|
||||
configMutators: []configMutatorsFunc{
|
||||
makeAltNamesMutator(pkiutil.GetAPIServerAltNames),
|
||||
},
|
||||
}
|
||||
// KubeadmCertKubeletClient is the definition of the cert used by the API server to access the kubelet.
|
||||
KubeadmCertKubeletClient = KubeadmCert{
|
||||
Name: "api-server-kubelet-client",
|
||||
BaseName: kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
|
||||
CAName: "root-ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerKubeletClientCertCommonName,
|
||||
Organization: []string{kubeadmconstants.MastersGroup},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
}
|
||||
|
||||
// KubeadmCertFrontProxyCA is the definition of the CA used for the front end proxy.
|
||||
KubeadmCertFrontProxyCA = KubeadmCert{
|
||||
Name: "front-proxy-ca",
|
||||
BaseName: kubeadmconstants.FrontProxyCACertAndKeyBaseName,
|
||||
config: certutil.Config{
|
||||
CommonName: "front-proxy-ca",
|
||||
},
|
||||
}
|
||||
|
||||
// KubeadmCertFrontProxyClient is the definition of the cert used by the API server to access the front proxy.
|
||||
KubeadmCertFrontProxyClient = KubeadmCert{
|
||||
Name: "front-proxy-client",
|
||||
BaseName: kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
|
||||
CAName: "front-proxy-ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.FrontProxyClientCertCommonName,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
}
|
||||
|
||||
// KubeadmCertEtcdCA is the definition of the root CA used by the hosted etcd server.
|
||||
KubeadmCertEtcdCA = KubeadmCert{
|
||||
Name: "etcd-ca",
|
||||
BaseName: kubeadmconstants.EtcdCACertAndKeyBaseName,
|
||||
config: certutil.Config{
|
||||
CommonName: "etcd-ca",
|
||||
},
|
||||
}
|
||||
// KubeadmCertEtcdServer is the definition of the cert used to serve etcd to clients.
|
||||
KubeadmCertEtcdServer = KubeadmCert{
|
||||
Name: "etcd-server",
|
||||
BaseName: kubeadmconstants.EtcdServerCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
// TODO: etcd 3.2 introduced an undocumented requirement for ClientAuth usage on the
|
||||
// server cert: https://github.com/coreos/etcd/issues/9785#issuecomment-396715692
|
||||
// Once the upstream issue is resolved, this should be returned to only allowing
|
||||
// ServerAuth usage.
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
configMutators: []configMutatorsFunc{
|
||||
makeAltNamesMutator(pkiutil.GetEtcdAltNames),
|
||||
setCommonNameToNodeName(),
|
||||
},
|
||||
}
|
||||
// KubeadmCertEtcdPeer is the definition of the cert used by etcd peers to access each other.
|
||||
KubeadmCertEtcdPeer = KubeadmCert{
|
||||
Name: "etcd-peer",
|
||||
BaseName: kubeadmconstants.EtcdPeerCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
configMutators: []configMutatorsFunc{
|
||||
makeAltNamesMutator(pkiutil.GetEtcdPeerAltNames),
|
||||
setCommonNameToNodeName(),
|
||||
},
|
||||
}
|
||||
// KubeadmCertEtcdHealthcheck is the definition of the cert used by Kubernetes to check the health of the etcd server.
|
||||
KubeadmCertEtcdHealthcheck = KubeadmCert{
|
||||
Name: "etcd-healthcheck",
|
||||
BaseName: kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.EtcdHealthcheckClientCertCommonName,
|
||||
Organization: []string{kubeadmconstants.MastersGroup},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
}
|
||||
// KubeadmCertEtcdAPIClient is the definition of the cert used by the API server to access etcd.
|
||||
KubeadmCertEtcdAPIClient = KubeadmCert{
|
||||
Name: "etcd-api-client",
|
||||
BaseName: kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerEtcdClientCertCommonName,
|
||||
Organization: []string{kubeadmconstants.MastersGroup},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func makeAltNamesMutator(f func(*kubeadmapi.InitConfiguration) (*certutil.AltNames, error)) configMutatorsFunc {
|
||||
return func(mc *kubeadmapi.InitConfiguration, cc *certutil.Config) error {
|
||||
altNames, err := f(mc)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
cc.AltNames = *altNames
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func setCommonNameToNodeName() configMutatorsFunc {
|
||||
return func(mc *kubeadmapi.InitConfiguration, cc *certutil.Config) error {
|
||||
cc.CommonName = mc.NodeRegistration.Name
|
||||
return nil
|
||||
}
|
||||
}
|
185
cmd/kubeadm/app/phases/certs/certlist_test.go
Normal file
185
cmd/kubeadm/app/phases/certs/certlist_test.go
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
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 certs
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestCAPointersValid(t *testing.T) {
|
||||
tests := []struct {
|
||||
certs Certificates
|
||||
name string
|
||||
}{
|
||||
{
|
||||
name: "Default Certificate List",
|
||||
certs: GetDefaultCertList(),
|
||||
},
|
||||
{
|
||||
name: "Cert list less etcd",
|
||||
certs: GetCertsWithoutEtcd(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
|
||||
certMap := test.certs.AsMap()
|
||||
|
||||
for _, cert := range test.certs {
|
||||
if cert.CAName != "" && certMap[cert.CAName] == nil {
|
||||
t.Errorf("Certificate %q references nonexistent CA %q", cert.Name, cert.CAName)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeCertTree(t *testing.T) {
|
||||
rootCert := &KubeadmCert{
|
||||
Name: "root",
|
||||
}
|
||||
leaf0 := &KubeadmCert{
|
||||
Name: "leaf0",
|
||||
CAName: "root",
|
||||
}
|
||||
leaf1 := &KubeadmCert{
|
||||
Name: "leaf1",
|
||||
CAName: "root",
|
||||
}
|
||||
selfSigned := &KubeadmCert{
|
||||
Name: "self-signed",
|
||||
}
|
||||
|
||||
certMap := CertificateMap{
|
||||
"root": rootCert,
|
||||
"leaf0": leaf0,
|
||||
"leaf1": leaf1,
|
||||
"self-signed": selfSigned,
|
||||
}
|
||||
|
||||
orphanCertMap := CertificateMap{
|
||||
"leaf0": leaf0,
|
||||
}
|
||||
|
||||
if _, err := orphanCertMap.CertTree(); err == nil {
|
||||
t.Error("expected orphan cert map to error, but got nil")
|
||||
}
|
||||
|
||||
certTree, err := certMap.CertTree()
|
||||
t.Logf("cert tree: %v", certTree)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, but got %v", err)
|
||||
}
|
||||
|
||||
if len(certTree) != 2 {
|
||||
t.Errorf("Expected tree to have 2 roots, got %d", len(certTree))
|
||||
}
|
||||
|
||||
if len(certTree[rootCert]) != 2 {
|
||||
t.Errorf("Expected root to have 2 leaves, got %d", len(certTree[rootCert]))
|
||||
}
|
||||
|
||||
if _, ok := certTree[selfSigned]; !ok {
|
||||
t.Error("Expected selfSigned to be present in tree, but missing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateCertificateChain(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
ic := &kubeadmapi.InitConfiguration{
|
||||
CertificatesDir: dir,
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{
|
||||
Name: "test-node",
|
||||
},
|
||||
}
|
||||
|
||||
caCfg := Certificates{
|
||||
{
|
||||
config: certutil.Config{},
|
||||
Name: "test-ca",
|
||||
BaseName: "test-ca",
|
||||
},
|
||||
{
|
||||
config: certutil.Config{
|
||||
AltNames: certutil.AltNames{
|
||||
DNSNames: []string{"test-domain.space"},
|
||||
},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
},
|
||||
configMutators: []configMutatorsFunc{
|
||||
setCommonNameToNodeName(),
|
||||
},
|
||||
CAName: "test-ca",
|
||||
Name: "test-daughter",
|
||||
BaseName: "test-daughter",
|
||||
},
|
||||
}
|
||||
|
||||
certTree, err := caCfg.AsMap().CertTree()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting tree: %v", err)
|
||||
}
|
||||
|
||||
if certTree.CreateTree(ic); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
caCert, _ := parseCertAndKey(path.Join(dir, "test-ca"), t)
|
||||
daughterCert, _ := parseCertAndKey(path.Join(dir, "test-daughter"), t)
|
||||
|
||||
pool := x509.NewCertPool()
|
||||
pool.AddCert(caCert)
|
||||
|
||||
_, err = daughterCert.Verify(x509.VerifyOptions{
|
||||
DNSName: "test-domain.space",
|
||||
Roots: pool,
|
||||
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("couldn't verify daughter cert: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func parseCertAndKey(basePath string, t *testing.T) (*x509.Certificate, crypto.PrivateKey) {
|
||||
certPair, err := tls.LoadX509KeyPair(basePath+".crt", basePath+".key")
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't parse certificate and key: %v", err)
|
||||
}
|
||||
|
||||
parsedCert, err := x509.ParseCertificate(certPair.Certificate[0])
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't parse certificate: %v", err)
|
||||
}
|
||||
|
||||
return parsedCert, certPair.PrivateKey
|
||||
}
|
@ -35,35 +35,34 @@ import (
|
||||
// If the PKI assets already exists in the target folder, they are used only if evaluated equal; otherwise an error is returned.
|
||||
func CreatePKIAssets(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating PKI assets")
|
||||
certActions := []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
CreateCACertAndKeyFiles,
|
||||
CreateAPIServerCertAndKeyFiles,
|
||||
CreateAPIServerKubeletClientCertAndKeyFiles,
|
||||
CreateServiceAccountKeyAndPublicKeyFiles,
|
||||
CreateFrontProxyCACertAndKeyFiles,
|
||||
CreateFrontProxyClientCertAndKeyFiles,
|
||||
}
|
||||
etcdCertActions := []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
CreateEtcdCACertAndKeyFiles,
|
||||
CreateEtcdServerCertAndKeyFiles,
|
||||
CreateEtcdPeerCertAndKeyFiles,
|
||||
CreateEtcdHealthcheckClientCertAndKeyFiles,
|
||||
CreateAPIServerEtcdClientCertAndKeyFiles,
|
||||
|
||||
// This structure cannot handle multilevel CA hierarchies.
|
||||
// This isn't a problem right now, but may become one in the future.
|
||||
|
||||
var certList Certificates
|
||||
|
||||
if cfg.Etcd.Local == nil {
|
||||
certList = GetCertsWithoutEtcd()
|
||||
} else {
|
||||
certList = GetDefaultCertList()
|
||||
}
|
||||
|
||||
if cfg.Etcd.Local != nil {
|
||||
certActions = append(certActions, etcdCertActions...)
|
||||
certTree, err := certList.AsMap().CertTree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, action := range certActions {
|
||||
err := action(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := certTree.CreateTree(cfg); err != nil {
|
||||
return fmt.Errorf("Error creating PKI assets: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("[certificates] valid certificates and keys now exist in %q\n", cfg.CertificatesDir)
|
||||
|
||||
// Service accounts are not x509 certs, so handled separately
|
||||
if err := CreateServiceAccountKeyAndPublicKeyFiles(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -118,7 +117,7 @@ func CreateAPIServerKubeletClientCertAndKeyFiles(cfg *kubeadmapi.InitConfigurati
|
||||
return err
|
||||
}
|
||||
|
||||
apiKubeletClientCert, apiKubeletClientKey, err := NewAPIServerKubeletClientCertAndKey(caCert, caKey)
|
||||
apiKubeletClientCert, apiKubeletClientKey, err := NewAPIServerKubeletClientCertAndKey(cfg, caCert, caKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -209,7 +208,7 @@ func CreateEtcdHealthcheckClientCertAndKeyFiles(cfg *kubeadmapi.InitConfiguratio
|
||||
return err
|
||||
}
|
||||
|
||||
etcdHealthcheckClientCert, etcdHealthcheckClientKey, err := NewEtcdHealthcheckClientCertAndKey(etcdCACert, etcdCAKey)
|
||||
etcdHealthcheckClientCert, etcdHealthcheckClientKey, err := NewEtcdHealthcheckClientCertAndKey(cfg, etcdCACert, etcdCAKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -233,7 +232,7 @@ func CreateAPIServerEtcdClientCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration)
|
||||
return err
|
||||
}
|
||||
|
||||
apiEtcdClientCert, apiEtcdClientKey, err := NewAPIServerEtcdClientCertAndKey(etcdCACert, etcdCAKey)
|
||||
apiEtcdClientCert, apiEtcdClientKey, err := NewAPIServerEtcdClientCertAndKey(cfg, etcdCACert, etcdCAKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -293,7 +292,7 @@ func CreateFrontProxyClientCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) er
|
||||
return err
|
||||
}
|
||||
|
||||
frontProxyClientCert, frontProxyClientKey, err := NewFrontProxyClientCertAndKey(frontProxyCACert, frontProxyCAKey)
|
||||
frontProxyClientCert, frontProxyClientKey, err := NewFrontProxyClientCertAndKey(cfg, frontProxyCACert, frontProxyCAKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -318,41 +317,27 @@ func NewCACertAndKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
return caCert, caKey, nil
|
||||
}
|
||||
|
||||
func newCertAndKeyFromSpec(certSpec *KubeadmCert, cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
certConfig, err := certSpec.GetConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating certificate %s: %v", certSpec.Name, err)
|
||||
}
|
||||
cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, *certConfig)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating %s key and certificate: %v", certSpec.Name, err)
|
||||
}
|
||||
|
||||
return cert, key, err
|
||||
}
|
||||
|
||||
// NewAPIServerCertAndKey generate certificate for apiserver, signed by the given CA.
|
||||
func NewAPIServerCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
altNames, err := pkiutil.GetAPIServerAltNames(cfg)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while composing altnames for API server: %v", err)
|
||||
}
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerCertCommonName,
|
||||
AltNames: *altNames,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
}
|
||||
apiCert, apiKey, err := pkiutil.NewCertAndKey(caCert, caKey, config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating API server key and certificate: %v", err)
|
||||
}
|
||||
|
||||
return apiCert, apiKey, nil
|
||||
return newCertAndKeyFromSpec(&KubeadmCertAPIServer, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// NewAPIServerKubeletClientCertAndKey generate certificate for the apiservers to connect to the kubelets securely, signed by the given CA.
|
||||
func NewAPIServerKubeletClientCertAndKey(caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerKubeletClientCertCommonName,
|
||||
Organization: []string{kubeadmconstants.MastersGroup},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
apiClientCert, apiClientKey, err := pkiutil.NewCertAndKey(caCert, caKey, config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating API server kubelet client key and certificate: %v", err)
|
||||
}
|
||||
|
||||
return apiClientCert, apiClientKey, nil
|
||||
func NewAPIServerKubeletClientCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
return newCertAndKeyFromSpec(&KubeadmCertKubeletClient, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// NewEtcdCACertAndKey generate a self signed etcd CA.
|
||||
@ -368,80 +353,22 @@ func NewEtcdCACertAndKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
// NewEtcdServerCertAndKey generate certificate for etcd, signed by the given CA.
|
||||
func NewEtcdServerCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
altNames, err := pkiutil.GetEtcdAltNames(cfg)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while composing altnames for etcd: %v", err)
|
||||
}
|
||||
|
||||
// TODO: etcd 3.2 introduced an undocumented requirement for ClientAuth usage on the
|
||||
// server cert: https://github.com/coreos/etcd/issues/9785#issuecomment-396715692
|
||||
// Once the upstream issue is resolved, this should be returned to only allowing
|
||||
// ServerAuth usage.
|
||||
config := certutil.Config{
|
||||
CommonName: cfg.NodeRegistration.Name,
|
||||
AltNames: *altNames,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
etcdServerCert, etcdServerKey, err := pkiutil.NewCertAndKey(caCert, caKey, config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating etcd key and certificate: %v", err)
|
||||
}
|
||||
|
||||
return etcdServerCert, etcdServerKey, nil
|
||||
return newCertAndKeyFromSpec(&KubeadmCertEtcdServer, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// NewEtcdPeerCertAndKey generate certificate for etcd peering, signed by the given CA.
|
||||
func NewEtcdPeerCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
altNames, err := pkiutil.GetEtcdPeerAltNames(cfg)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while composing altnames for etcd peering: %v", err)
|
||||
}
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: cfg.NodeRegistration.Name,
|
||||
AltNames: *altNames,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
etcdPeerCert, etcdPeerKey, err := pkiutil.NewCertAndKey(caCert, caKey, config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating etcd peer key and certificate: %v", err)
|
||||
}
|
||||
|
||||
return etcdPeerCert, etcdPeerKey, nil
|
||||
return newCertAndKeyFromSpec(&KubeadmCertEtcdPeer, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// NewEtcdHealthcheckClientCertAndKey generate certificate for liveness probes to healthcheck etcd, signed by the given CA.
|
||||
func NewEtcdHealthcheckClientCertAndKey(caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: kubeadmconstants.EtcdHealthcheckClientCertCommonName,
|
||||
Organization: []string{kubeadmconstants.MastersGroup},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
etcdHealcheckClientCert, etcdHealcheckClientKey, err := pkiutil.NewCertAndKey(caCert, caKey, config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating etcd healthcheck client key and certificate: %v", err)
|
||||
}
|
||||
|
||||
return etcdHealcheckClientCert, etcdHealcheckClientKey, nil
|
||||
func NewEtcdHealthcheckClientCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
return newCertAndKeyFromSpec(&KubeadmCertEtcdHealthcheck, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// NewAPIServerEtcdClientCertAndKey generate certificate for the apiservers to connect to etcd securely, signed by the given CA.
|
||||
func NewAPIServerEtcdClientCertAndKey(caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerEtcdClientCertCommonName,
|
||||
Organization: []string{kubeadmconstants.MastersGroup},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
apiClientCert, apiClientKey, err := pkiutil.NewCertAndKey(caCert, caKey, config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating API server etcd client key and certificate: %v", err)
|
||||
}
|
||||
|
||||
return apiClientCert, apiClientKey, nil
|
||||
func NewAPIServerEtcdClientCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
return newCertAndKeyFromSpec(&KubeadmCertEtcdHealthcheck, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// NewServiceAccountSigningKey generate public/private key pairs for signing service account tokens.
|
||||
@ -468,18 +395,8 @@ func NewFrontProxyCACertAndKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
}
|
||||
|
||||
// NewFrontProxyClientCertAndKey generate certificate for proxy server client, signed by the given front proxy CA.
|
||||
func NewFrontProxyClientCertAndKey(frontProxyCACert *x509.Certificate, frontProxyCAKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: kubeadmconstants.FrontProxyClientCertCommonName,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
frontProxyClientCert, frontProxyClientKey, err := pkiutil.NewCertAndKey(frontProxyCACert, frontProxyCAKey, config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while creating front-proxy client key and certificate: %v", err)
|
||||
}
|
||||
|
||||
return frontProxyClientCert, frontProxyClientKey, nil
|
||||
func NewFrontProxyClientCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
return newCertAndKeyFromSpec(&KubeadmCertFrontProxyClient, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// loadCertificateAuthority loads certificate authority
|
||||
|
@ -60,7 +60,7 @@ func TestWriteCertificateAuthorithyFilesIfNotExist(t *testing.T) {
|
||||
},
|
||||
{ // cert exists, but it is not a ca > err
|
||||
setupFunc: func(pkiDir string) error {
|
||||
cert, key, _ := NewFrontProxyClientCertAndKey(setupCert, setupKey)
|
||||
cert, key, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, setupCert, setupKey)
|
||||
return writeCertificateFilesIfNotExist(pkiDir, "dummy", setupCert, cert, key)
|
||||
},
|
||||
expectedError: true,
|
||||
@ -111,8 +111,8 @@ func TestWriteCertificateAuthorithyFilesIfNotExist(t *testing.T) {
|
||||
func TestWriteCertificateFilesIfNotExist(t *testing.T) {
|
||||
|
||||
caCert, caKey, _ := NewFrontProxyCACertAndKey()
|
||||
setupCert, setupKey, _ := NewFrontProxyClientCertAndKey(caCert, caKey)
|
||||
cert, key, _ := NewFrontProxyClientCertAndKey(caCert, caKey)
|
||||
setupCert, setupKey, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
cert, key, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
|
||||
var tests = []struct {
|
||||
setupFunc func(pkiDir string) error
|
||||
@ -138,7 +138,7 @@ func TestWriteCertificateFilesIfNotExist(t *testing.T) {
|
||||
{ // cert exists, is signed by another ca > err
|
||||
setupFunc: func(pkiDir string) error {
|
||||
anotherCaCert, anotherCaKey, _ := NewFrontProxyCACertAndKey()
|
||||
anotherCert, anotherKey, _ := NewFrontProxyClientCertAndKey(anotherCaCert, anotherCaKey)
|
||||
anotherCert, anotherKey, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, anotherCaCert, anotherCaKey)
|
||||
|
||||
return writeCertificateFilesIfNotExist(pkiDir, "dummy", anotherCaCert, anotherCert, anotherKey)
|
||||
},
|
||||
@ -300,7 +300,7 @@ func TestNewAPIServerKubeletClientCertAndKey(t *testing.T) {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
apiKubeletClientCert, _, err := NewAPIServerKubeletClientCertAndKey(caCert, caKey)
|
||||
apiKubeletClientCert, _, err := NewAPIServerKubeletClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
@ -395,7 +395,7 @@ func TestNewEtcdHealthcheckClientCertAndKey(t *testing.T) {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
etcdHealthcheckClientCert, _, err := NewEtcdHealthcheckClientCertAndKey(caCert, caKey)
|
||||
etcdHealthcheckClientCert, _, err := NewEtcdHealthcheckClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
@ -411,7 +411,7 @@ func TestNewAPIServerEtcdClientCertAndKey(t *testing.T) {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
apiEtcdClientCert, _, err := NewAPIServerEtcdClientCertAndKey(caCert, caKey)
|
||||
apiEtcdClientCert, _, err := NewAPIServerEtcdClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
@ -448,7 +448,7 @@ func TestNewFrontProxyClientCertAndKey(t *testing.T) {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
frontProxyClientCert, _, err := NewFrontProxyClientCertAndKey(frontProxyCACert, frontProxyCAKey)
|
||||
frontProxyClientCert, _, err := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, frontProxyCACert, frontProxyCAKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user