Commit cc90d34f authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #50691 from fabriziopandini/kubeadm-phases-certs3

Automatic merge from submit-queue (batch tested with PRs 50904, 50691) Make Kubeadm phase certs codebase consistent with other phases **What this PR does / why we need it:** This PR is a refactoring of [#48196](https://github.com/kubernetes/kubernetes/pull/48196), that makes this part of kubeadm more consistent with other parts of kubeadm recently changed, e.g. [controlplane & etcd phase #50302](https://github.com/kubernetes/kubernetes/pull/50302) and [kubeconfig phase #49419](https://github.com/kubernetes/kubernetes/pull/49419) **Which issue this PR fixes:** none **Special notes for your reviewer:** cc @luxas
parents 26eb7c94 c6bb8fbb
...@@ -30,6 +30,7 @@ go_library( ...@@ -30,6 +30,7 @@ go_library(
"//cmd/kubeadm/app/phases/apiconfig:go_default_library", "//cmd/kubeadm/app/phases/apiconfig:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library", "//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library", "//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library", "//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
"//cmd/kubeadm/app/phases/controlplane:go_default_library", "//cmd/kubeadm/app/phases/controlplane:go_default_library",
"//cmd/kubeadm/app/phases/etcd:go_default_library", "//cmd/kubeadm/app/phases/etcd:go_default_library",
......
...@@ -31,13 +31,13 @@ import ( ...@@ -31,13 +31,13 @@ import (
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/features" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/features"
cmdphases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
dnsaddonphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns" dnsaddonphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
proxyaddonphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy" proxyaddonphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
apiconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/apiconfig" apiconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/apiconfig"
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd" etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
...@@ -234,7 +234,7 @@ func (i *Init) Run(out io.Writer) error { ...@@ -234,7 +234,7 @@ func (i *Init) Run(out io.Writer) error {
} }
// PHASE 1: Generate certificates // PHASE 1: Generate certificates
if err := cmdphases.CreatePKIAssets(i.cfg); err != nil { if err := certsphase.CreatePKIAssets(i.cfg); err != nil {
return err return err
} }
......
...@@ -29,7 +29,6 @@ go_library( ...@@ -29,7 +29,6 @@ go_library(
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library", "//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library", "//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library", "//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
"//cmd/kubeadm/app/phases/controlplane:go_default_library", "//cmd/kubeadm/app/phases/controlplane:go_default_library",
"//cmd/kubeadm/app/phases/etcd:go_default_library", "//cmd/kubeadm/app/phases/etcd:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library", "//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
......
...@@ -33,7 +33,61 @@ import ( ...@@ -33,7 +33,61 @@ import (
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd" cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
) )
func TestSubCmdCertsCreateFiles(t *testing.T) { func TestCertsSubCommandsHasFlags(t *testing.T) {
subCmds := getCertsSubCommands()
commonFlags := []string{
"cert-dir",
"config",
}
var tests = []struct {
command string
additionalFlags []string
}{
{
command: "all",
additionalFlags: []string{
"apiserver-advertise-address",
"apiserver-cert-extra-sans",
"service-cidr",
"service-dns-domain",
},
},
{
command: "ca",
},
{
command: "apiserver",
additionalFlags: []string{
"apiserver-advertise-address",
"apiserver-cert-extra-sans",
"service-cidr",
"service-dns-domain",
},
},
{
command: "apiserver-kubelet-client",
},
{
command: "sa",
},
{
command: "front-proxy-ca",
},
{
command: "front-proxy-client",
},
}
for _, test := range tests {
expectedFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
}
}
func TestSubCmdCertsCreateFilesWithFlags(t *testing.T) {
subCmds := getCertsSubCommands() subCmds := getCertsSubCommands()
...@@ -53,26 +107,14 @@ func TestSubCmdCertsCreateFiles(t *testing.T) { ...@@ -53,26 +107,14 @@ func TestSubCmdCertsCreateFiles(t *testing.T) {
}, },
}, },
{ {
subCmds: []string{"ca"}, subCmds: []string{"ca", "apiserver", "apiserver-kubelet-client"},
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName}, expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName, kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
},
{
subCmds: []string{"ca", "apiserver"},
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName},
},
{
subCmds: []string{"ca", "apiserver-kubelet-client"},
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
}, },
{ {
subCmds: []string{"sa"}, subCmds: []string{"sa"},
expectedFiles: []string{kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName}, expectedFiles: []string{kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName},
}, },
{ {
subCmds: []string{"front-proxy-ca"},
expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName},
},
{
subCmds: []string{"front-proxy-ca", "front-proxy-client"}, subCmds: []string{"front-proxy-ca", "front-proxy-client"},
expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName, kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName}, expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName, kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName},
}, },
...@@ -94,7 +136,7 @@ func TestSubCmdCertsCreateFiles(t *testing.T) { ...@@ -94,7 +136,7 @@ func TestSubCmdCertsCreateFiles(t *testing.T) {
} }
} }
func TestSubCmdApiServerFlags(t *testing.T) { func TestSubCmdCertsApiServerForwardsFlags(t *testing.T) {
subCmds := getCertsSubCommands() subCmds := getCertsSubCommands()
...@@ -116,6 +158,7 @@ func TestSubCmdApiServerFlags(t *testing.T) { ...@@ -116,6 +158,7 @@ func TestSubCmdApiServerFlags(t *testing.T) {
} }
cmdtestutil.RunSubCommand(t, subCmds, "apiserver", apiserverFlags...) cmdtestutil.RunSubCommand(t, subCmds, "apiserver", apiserverFlags...)
// asserts created cert has values from CLI flags
APIserverCert, err := pkiutil.TryLoadCertFromDisk(tmpdir, kubeadmconstants.APIServerCertAndKeyBaseName) APIserverCert, err := pkiutil.TryLoadCertFromDisk(tmpdir, kubeadmconstants.APIServerCertAndKeyBaseName)
if err != nil { if err != nil {
t.Fatalf("Error loading API server certificate: %v", err) t.Fatalf("Error loading API server certificate: %v", err)
...@@ -135,29 +178,36 @@ func TestSubCmdApiServerFlags(t *testing.T) { ...@@ -135,29 +178,36 @@ func TestSubCmdApiServerFlags(t *testing.T) {
} }
} }
func TestSubCmdCertsReadsConfig(t *testing.T) { func TestSubCmdCertsCreateFilesWithConfigFile(t *testing.T) {
subCmds := getCertsSubCommands() subCmds := getCertsSubCommands()
var tests = []struct { var tests = []struct {
subCmds []string subCmds []string
expectedFileCount int expectedFiles []string
}{ }{
{ {
subCmds: []string{"sa"}, subCmds: []string{"all"},
expectedFileCount: 2, expectedFiles: []string{
kubeadmconstants.CACertName, kubeadmconstants.CAKeyName,
kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName,
kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName,
kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName,
kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName,
kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName,
},
}, },
{ {
subCmds: []string{"front-proxy-ca", "front-proxy-client"}, subCmds: []string{"ca", "apiserver", "apiserver-kubelet-client"},
expectedFileCount: 4, expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName, kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
}, },
{ {
subCmds: []string{"ca", "apiserver", "apiserver-kubelet-client"}, subCmds: []string{"front-proxy-ca", "front-proxy-client"},
expectedFileCount: 6, expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName, kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName},
}, },
{ {
subCmds: []string{"all"}, subCmds: []string{"sa"},
expectedFileCount: 12, expectedFiles: []string{kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName},
}, },
} }
...@@ -182,6 +232,6 @@ func TestSubCmdCertsReadsConfig(t *testing.T) { ...@@ -182,6 +232,6 @@ func TestSubCmdCertsReadsConfig(t *testing.T) {
} }
// verify expected files are there // verify expected files are there
testutil.AssertFilesCount(t, tmpdir, test.expectedFileCount) testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
} }
} }
...@@ -13,6 +13,9 @@ go_test( ...@@ -13,6 +13,9 @@ go_test(
deps = [ deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
"//cmd/kubeadm/test:go_default_library",
"//cmd/kubeadm/test/certs:go_default_library",
], ],
) )
...@@ -27,7 +30,7 @@ go_library( ...@@ -27,7 +30,7 @@ go_library(
"//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library", "//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
"//pkg/registry/core/service/ipallocator:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/client-go/util/cert:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library",
], ],
) )
......
...@@ -19,6 +19,7 @@ package certs ...@@ -19,6 +19,7 @@ package certs
import ( import (
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
"net"
"testing" "testing"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
...@@ -35,6 +36,13 @@ func SetupCertificateAuthorithy(t *testing.T) (*x509.Certificate, *rsa.PrivateKe ...@@ -35,6 +36,13 @@ func SetupCertificateAuthorithy(t *testing.T) (*x509.Certificate, *rsa.PrivateKe
return caCert, caKey return caCert, caKey
} }
// AssertCertificateIsCa is a utility function for kubeadm testing that asserts if a given certificate is a CA
func AssertCertificateIsCa(t *testing.T, cert *x509.Certificate) {
if !cert.IsCA {
t.Error("cert is not a valida CA")
}
}
// AssertCertificateIsSignedByCa is a utility function for kubeadm testing that asserts if a given certificate is signed // AssertCertificateIsSignedByCa is a utility function for kubeadm testing that asserts if a given certificate is signed
// by the expected CA // by the expected CA
func AssertCertificateIsSignedByCa(t *testing.T, cert *x509.Certificate, signingCa *x509.Certificate) { func AssertCertificateIsSignedByCa(t *testing.T, cert *x509.Certificate, signingCa *x509.Certificate) {
...@@ -77,3 +85,50 @@ func AssertCertificateHasClientAuthUsage(t *testing.T, cert *x509.Certificate) { ...@@ -77,3 +85,50 @@ func AssertCertificateHasClientAuthUsage(t *testing.T, cert *x509.Certificate) {
} }
t.Error("cert has not ClientAuth usage as expected") t.Error("cert has not ClientAuth usage as expected")
} }
// AssertCertificateHasServerAuthUsage is a utility function for kubeadm testing that asserts if a given certificate has
// the expected ExtKeyUsageServerAuth
func AssertCertificateHasServerAuthUsage(t *testing.T, cert *x509.Certificate) {
for i := range cert.ExtKeyUsage {
if cert.ExtKeyUsage[i] == x509.ExtKeyUsageServerAuth {
return
}
}
t.Error("cert is not a ServerAuth")
}
// AssertCertificateHasDNSNames is a utility function for kubeadm testing that asserts if a given certificate has
// the expected DNSNames
func AssertCertificateHasDNSNames(t *testing.T, cert *x509.Certificate, DNSNames ...string) {
for _, DNSName := range DNSNames {
found := false
for _, val := range cert.DNSNames {
if val == DNSName {
found = true
break
}
}
if !found {
t.Errorf("cert does not contain DNSName %s", DNSName)
}
}
}
// AssertCertificateHasIPAddresses is a utility function for kubeadm testing that asserts if a given certificate has
// the expected IPAddresses
func AssertCertificateHasIPAddresses(t *testing.T, cert *x509.Certificate, IPAddresses ...net.IP) {
for _, IPAddress := range IPAddresses {
found := false
for _, val := range cert.IPAddresses {
if val.Equal(IPAddress) {
found = true
break
}
}
if !found {
t.Errorf("cert does not contain IPAddress %s", IPAddress)
}
}
}
...@@ -76,6 +76,17 @@ func SetupMasterConfigurationFile(t *testing.T, tmpdir string, cfg *kubeadmapi.M ...@@ -76,6 +76,17 @@ func SetupMasterConfigurationFile(t *testing.T, tmpdir string, cfg *kubeadmapi.M
return cfgPath return cfgPath
} }
// SetupEmptyFiles is a utility function for kubeadm testing that creates one or more empty files (touch)
func SetupEmptyFiles(t *testing.T, tmpdir string, fileNames ...string) {
for _, fileName := range fileNames {
newFile, err := os.Create(filepath.Join(tmpdir, fileName))
if err != nil {
t.Fatalf("Error creating file %s in %s: %v", fileName, tmpdir, err)
}
newFile.Close()
}
}
// SetupPkiDirWithCertificateAuthorithy is a utility function for kubeadm testing that creates a // SetupPkiDirWithCertificateAuthorithy is a utility function for kubeadm testing that creates a
// CertificateAuthorithy cert/key pair into /pki subfolder of a given temporary directory. // CertificateAuthorithy cert/key pair into /pki subfolder of a given temporary directory.
// The funtion returns the path of the created pki. // The funtion returns the path of the created pki.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment