Generate client certificates for healthchecking kubeadm etcd static pods

Add new phase command: `certs etcd-healthcheck`
Certs are placed at /etc/kubernetes/pki/etcd/healthcheck-client.{crt,key}
pull/6/head
leigh schrandt 2018-03-02 15:25:38 -07:00
parent ae1fc13aee
commit 7a1a3aa3df
11 changed files with 138 additions and 4 deletions

View File

@ -98,6 +98,13 @@ var (
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName)
etcdHealthcheckClientCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the client certificate for liveness probes to healthcheck etcd and the respective key,
and saves them into %s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName)
apiServerEtcdServerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the client certificate for the API server to connect to etcd securely and the respective key,
and saves them into %s and %s files.
@ -206,6 +213,12 @@ func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command {
long: etcdPeerCertLongDesc,
cmdFunc: certsphase.CreateEtcdPeerCertAndKeyFiles,
},
{
use: "etcd-healthcheck-client",
short: "Generates a client certificate for liveness probes to healthcheck etcd",
long: etcdHealthcheckClientCertLongDesc,
cmdFunc: certsphase.CreateEtcdHealthcheckClientCertAndKeyFiles,
},
{
use: "apiserver-etcd-client",
short: "Generates a client certificate for the API server to connect to etcd securely",

View File

@ -73,6 +73,21 @@ func TestCertsSubCommandsHasFlags(t *testing.T) {
{
command: "apiserver-kubelet-client",
},
{
command: "etcd-ca",
},
{
command: "etcd-server",
},
{
command: "etcd-peer",
},
{
command: "etcd-healthcheck-client",
},
{
command: "apiserver-etcd-client",
},
{
command: "sa",
},
@ -113,6 +128,16 @@ func TestSubCmdCertsCreateFilesWithFlags(t *testing.T) {
subCmds: []string{"ca", "apiserver", "apiserver-kubelet-client"},
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName, kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
},
{
subCmds: []string{"etcd-ca", "etcd-server", "etcd-peer", "etcd-healthcheck-client", "apiserver-etcd-client"},
expectedFiles: []string{
kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName,
kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName,
kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName,
kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName,
kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName,
},
},
{
subCmds: []string{"sa"},
expectedFiles: []string{kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName},
@ -204,6 +229,16 @@ func TestSubCmdCertsCreateFilesWithConfigFile(t *testing.T) {
subCmds: []string{"ca", "apiserver", "apiserver-kubelet-client"},
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName, kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
},
{
subCmds: []string{"etcd-ca", "etcd-server", "etcd-peer", "etcd-healthcheck-client", "apiserver-etcd-client"},
expectedFiles: []string{
kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName,
kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName,
kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName,
kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName,
kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName,
},
},
{
subCmds: []string{"front-proxy-ca", "front-proxy-client"},
expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName, kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName},

View File

@ -90,13 +90,22 @@ const (
// EtcdPeerCertCommonName defines etcd's peer certificate common name (CN)
EtcdPeerCertCommonName = "kube-etcd-peer"
// APIServerEtcdClientCertAndKeyBaseName defines etcd client certificate and key base name
// EtcdHealthcheckClientCertAndKeyBaseName defines etcd's healthcheck client certificate and key base name
EtcdHealthcheckClientCertAndKeyBaseName = "etcd/healthcheck-client"
// EtcdHealthcheckClientCertName defines etcd's healthcheck client certificate name
EtcdHealthcheckClientCertName = "etcd/healthcheck-client.crt"
// EtcdHealthcheckClientKeyName defines etcd's healthcheck client key name
EtcdHealthcheckClientKeyName = "etcd/healthcheck-client.key"
// EtcdHealthcheckClientCertCommonName defines etcd's healthcheck client certificate common name (CN)
EtcdHealthcheckClientCertCommonName = "kube-etcd-healthcheck-client"
// APIServerEtcdClientCertAndKeyBaseName defines apiserver's etcd client certificate and key base name
APIServerEtcdClientCertAndKeyBaseName = "apiserver-etcd-client"
// APIServerEtcdClientCertName defines etcd client certificate name
// APIServerEtcdClientCertName defines apiserver's etcd client certificate name
APIServerEtcdClientCertName = "apiserver-etcd-client.crt"
// APIServerEtcdClientKeyName defines etcd client key name
// APIServerEtcdClientKeyName defines apiserver's etcd client key name
APIServerEtcdClientKeyName = "apiserver-etcd-client.key"
// APIServerEtcdClientCertCommonName defines etcd client certificate common name (CN)
// APIServerEtcdClientCertCommonName defines apiserver's etcd client certificate common name (CN)
APIServerEtcdClientCertCommonName = "kube-apiserver-etcd-client"
// ServiceAccountKeyBaseName defines SA key base name

View File

@ -40,6 +40,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration) error {
CreateEtcdCACertAndKeyFiles,
CreateEtcdServerCertAndKeyFiles,
CreateEtcdPeerCertAndKeyFiles,
CreateEtcdHealthcheckClientCertAndKeyFiles,
CreateAPIServerEtcdClientCertAndKeyFiles,
CreateServiceAccountKeyAndPublicKeyFiles,
CreateFrontProxyCACertAndKeyFiles,
@ -190,6 +191,30 @@ func CreateEtcdPeerCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error {
)
}
// CreateEtcdHealthcheckClientCertAndKeyFiles create a new client certificate for liveness probes to healthcheck etcd
// If the etcd-healthcheck-client certificate and key file already exist in the target folder, they are used only if evaluated equal; otherwise an error is returned.
// It assumes the etcd CA certificate and key file exist in the CertificatesDir
func CreateEtcdHealthcheckClientCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error {
etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName)
if err != nil {
return err
}
etcdHealthcheckClientCert, etcdHealthcheckClientKey, err := NewEtcdHealthcheckClientCertAndKey(etcdCACert, etcdCAKey)
if err != nil {
return err
}
return writeCertificateFilesIfNotExist(
cfg.CertificatesDir,
kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName,
etcdCACert,
etcdHealthcheckClientCert,
etcdHealthcheckClientKey,
)
}
// CreateAPIServerEtcdClientCertAndKeyFiles create a new client certificate for the apiserver calling etcd
// If the apiserver-etcd-client certificate and key file already exist in the target folder, they are used only if evaluated equal; otherwise an error is returned.
// It assumes the etcd CA certificate and key file exist in the CertificatesDir
@ -375,6 +400,22 @@ func NewEtcdPeerCertAndKey(cfg *kubeadmapi.MasterConfiguration, caCert *x509.Cer
return etcdPeerCert, etcdPeerKey, nil
}
// 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
}
// 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) {

View File

@ -382,6 +382,22 @@ func TestNewEtcdPeerCertAndKey(t *testing.T) {
}
}
func TestNewEtcdHealthcheckClientCertAndKey(t *testing.T) {
caCert, caKey, err := NewCACertAndKey()
if err != nil {
t.Fatalf("failed creation of ca cert and key: %v", err)
}
etcdHealthcheckClientCert, _, err := NewEtcdHealthcheckClientCertAndKey(caCert, caKey)
if err != nil {
t.Fatalf("failed creation of cert and key: %v", err)
}
certstestutil.AssertCertificateIsSignedByCa(t, etcdHealthcheckClientCert, caCert)
certstestutil.AssertCertificateHasClientAuthUsage(t, etcdHealthcheckClientCert)
certstestutil.AssertCertificateHasOrganizations(t, etcdHealthcheckClientCert, kubeadmconstants.MastersGroup)
}
func TestNewAPIServerEtcdClientCertAndKey(t *testing.T) {
caCert, caKey, err := NewCACertAndKey()
if err != nil {
@ -595,6 +611,7 @@ func TestCreateCertificateFilesMethods(t *testing.T) {
kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName,
kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName,
kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName,
kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName,
kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName,
kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName,
kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName,
@ -629,6 +646,11 @@ func TestCreateCertificateFilesMethods(t *testing.T) {
createFunc: CreateEtcdPeerCertAndKeyFiles,
expectedFiles: []string{kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName},
},
{
setupFunc: CreateEtcdCACertAndKeyFiles,
createFunc: CreateEtcdHealthcheckClientCertAndKeyFiles,
expectedFiles: []string{kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName},
},
{
setupFunc: CreateEtcdCACertAndKeyFiles,
createFunc: CreateAPIServerEtcdClientCertAndKeyFiles,

View File

@ -46,6 +46,8 @@ package certs
- etcd/server.key
- etcd/peer.crt
- etcd/peer.key
- etcd/healthcheck-client.crt
- etcd/healthcheck-client.key
- sa.pub
- sa.key
- front-proxy-ca.crt

View File

@ -148,6 +148,9 @@ func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticP
if err := certsphase.CreateEtcdPeerCertAndKeyFiles(cfg); err != nil {
return fmt.Errorf("failed to upgrade the %s peer certificate and key: %v", constants.Etcd, err)
}
if err := certsphase.CreateEtcdHealthcheckClientCertAndKeyFiles(cfg); err != nil {
return fmt.Errorf("failed to upgrade the %s healthcheck certificate and key: %v", constants.Etcd, err)
}
}
if component == constants.KubeAPIServer {
if err := certsphase.CreateAPIServerEtcdClientCertAndKeyFiles(cfg); err != nil {

View File

@ -327,6 +327,7 @@ func TestStaticPodControlPlane(t *testing.T) {
// certsphase.CreateEtcdCACertAndKeyFiles,
// certsphase.CreateEtcdServerCertAndKeyFiles,
// certsphase.CreateEtcdPeerCertAndKeyFiles,
// certsphase.CreateEtcdHealthcheckClientCertAndKeyFiles,
// certsphase.CreateAPIServerEtcdClientCertAndKeyFiles,
certsphase.CreateServiceAccountKeyAndPublicKeyFiles,
certsphase.CreateFrontProxyCACertAndKeyFiles,

View File

@ -25,6 +25,7 @@ docs/admin/kubeadm_alpha_phase_certs_apiserver-kubelet-client.md
docs/admin/kubeadm_alpha_phase_certs_apiserver.md
docs/admin/kubeadm_alpha_phase_certs_ca.md
docs/admin/kubeadm_alpha_phase_certs_etcd-ca.md
docs/admin/kubeadm_alpha_phase_certs_etcd-healthcheck-client.md
docs/admin/kubeadm_alpha_phase_certs_etcd-peer.md
docs/admin/kubeadm_alpha_phase_certs_etcd-server.md
docs/admin/kubeadm_alpha_phase_certs_front-proxy-ca.md
@ -92,6 +93,7 @@ docs/man/man1/kubeadm-alpha-phase-certs-apiserver-kubelet-client.1
docs/man/man1/kubeadm-alpha-phase-certs-apiserver.1
docs/man/man1/kubeadm-alpha-phase-certs-ca.1
docs/man/man1/kubeadm-alpha-phase-certs-etcd-ca.1
docs/man/man1/kubeadm-alpha-phase-certs-etcd-healthcheck-client.1
docs/man/man1/kubeadm-alpha-phase-certs-etcd-peer.1
docs/man/man1/kubeadm-alpha-phase-certs-etcd-server.1
docs/man/man1/kubeadm-alpha-phase-certs-front-proxy-ca.1

View File

@ -0,0 +1,3 @@
This file is autogenerated, but we've stopped checking such files into the
repository to reduce the need for rebases. Please run hack/generate-docs.sh to
populate this file.

View File

@ -0,0 +1,3 @@
This file is autogenerated, but we've stopped checking such files into the
repository to reduce the need for rebases. Please run hack/generate-docs.sh to
populate this file.