mirror of https://github.com/k3s-io/k3s
Merge pull request #67605 from liztio/cert-list-2
Automatic merge from submit-queue (batch tested with PRs 67596, 67520, 67605). 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>. Cert list 2 **What this PR does / why we need it**: Continuation of #67208. Uses the newly created declarative list of certificates kubeadm requires for the certs phase and upgrade steps. **Special notes for your reviewer**: **Release note**: ```release-note ```pull/8/head
commit
6d76e35b39
|
@ -18,13 +18,13 @@ package phases
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
|
@ -38,12 +38,12 @@ var (
|
|||
Generates a self-signed CA to provision identities for each component in the cluster (including nodes)
|
||||
and client certificates to be used by various components.
|
||||
|
||||
If a given certificate and private key pair both exist, kubeadm skips the generation step and
|
||||
If a given certificate and private key pair both exist, kubeadm skips the generation step and
|
||||
existing files will be used.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
allCertsExample = normalizer.Examples(`
|
||||
# Creates all PKI assets necessary to establish the control plane,
|
||||
# Creates all PKI assets necessary to establish the control plane,
|
||||
# functionally equivalent to what generated by kubeadm init.
|
||||
kubeadm alpha phase certs all
|
||||
|
||||
|
@ -51,85 +51,17 @@ var (
|
|||
kubeadm alpha phase certs all --config masterconfiguration.yaml
|
||||
`)
|
||||
|
||||
caCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the self-signed kubernetes certificate authority and related 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.CACertName, kubeadmconstants.CAKeyName)
|
||||
|
||||
apiServerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the API server serving certificate and key and saves them into %s and %s files.
|
||||
|
||||
The certificate includes default subject alternative names and additional SANs provided by the user;
|
||||
default SANs are: <node-name>, <apiserver-advertise-address>, kubernetes, kubernetes.default, kubernetes.default.svc,
|
||||
kubernetes.default.svc.<service-dns-domain>, <internalAPIServerVirtualIP> (that is the .10 address in <service-cidr> address space).
|
||||
|
||||
If both files already exist, kubeadm skips the generation step and existing files will be used.
|
||||
`+cmdutil.AlphaDisclaimer), kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName)
|
||||
|
||||
apiServerKubeletCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the client certificate for the API server to connect to the kubelet securely 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.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName)
|
||||
|
||||
etcdCaCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the self-signed etcd certificate authority and related 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.EtcdCACertName, kubeadmconstants.EtcdCAKeyName)
|
||||
|
||||
etcdServerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the etcd serving certificate and key and saves them into %s and %s files.
|
||||
|
||||
The certificate includes default subject alternative names and additional SANs provided by the user;
|
||||
default SANs are: localhost, 127.0.0.1.
|
||||
|
||||
If both files already exist, kubeadm skips the generation step and existing files will be used.
|
||||
`+cmdutil.AlphaDisclaimer), kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName)
|
||||
|
||||
etcdPeerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the etcd peer certificate and key and saves them into %s and %s files.
|
||||
|
||||
The certificate includes default subject alternative names and additional SANs provided by the user;
|
||||
default SANs are: <node-name>, <apiserver-advertise-address>.
|
||||
|
||||
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.
|
||||
|
||||
If both files already exist, kubeadm skips the generation step and existing files will be used.
|
||||
`+cmdutil.AlphaDisclaimer), kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName)
|
||||
|
||||
saKeyLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the private key for signing service account tokens along with its public 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.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName)
|
||||
|
||||
frontProxyCaCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the front proxy CA certificate and key and saves them into %s and %s files.
|
||||
genericLongDesc = normalizer.LongDesc(`
|
||||
Generates the %[1]s, and saves them into %[2]s.cert and %[2]s.key files.%[3]s
|
||||
|
||||
If both files already exist, kubeadm skips the generation step and existing files will be used.
|
||||
`+cmdutil.AlphaDisclaimer), kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName)
|
||||
|
||||
frontProxyClientCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the front proxy client certificate and 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.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName)
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
)
|
||||
|
||||
// NewCmdCerts returns main command for certs phase
|
||||
|
@ -154,147 +86,146 @@ func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command {
|
|||
kubeadmscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath string
|
||||
var subCmds []*cobra.Command
|
||||
|
||||
subCmdProperties := []struct {
|
||||
use string
|
||||
short string
|
||||
long string
|
||||
examples string
|
||||
cmdFunc func(cfg *kubeadmapi.InitConfiguration) error
|
||||
}{
|
||||
{
|
||||
use: "all",
|
||||
short: "Generates all PKI assets necessary to establish the control plane",
|
||||
long: allCertsLongDesc,
|
||||
examples: allCertsExample,
|
||||
cmdFunc: certsphase.CreatePKIAssets,
|
||||
},
|
||||
{
|
||||
use: "ca",
|
||||
short: "Generates a self-signed kubernetes CA to provision identities for components of the cluster",
|
||||
long: caCertLongDesc,
|
||||
cmdFunc: certsphase.CreateCACertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "apiserver",
|
||||
short: "Generates an API server serving certificate and key",
|
||||
long: apiServerCertLongDesc,
|
||||
cmdFunc: certsphase.CreateAPIServerCertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "apiserver-kubelet-client",
|
||||
short: "Generates a client certificate for the API server to connect to the kubelets securely",
|
||||
long: apiServerKubeletCertLongDesc,
|
||||
cmdFunc: certsphase.CreateAPIServerKubeletClientCertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "etcd-ca",
|
||||
short: "Generates a self-signed CA to provision identities for etcd",
|
||||
long: etcdCaCertLongDesc,
|
||||
cmdFunc: certsphase.CreateEtcdCACertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "etcd-server",
|
||||
short: "Generates an etcd serving certificate and key",
|
||||
long: etcdServerCertLongDesc,
|
||||
cmdFunc: certsphase.CreateEtcdServerCertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "etcd-peer",
|
||||
short: "Generates an etcd peer certificate and key",
|
||||
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",
|
||||
long: apiServerEtcdServerCertLongDesc,
|
||||
cmdFunc: certsphase.CreateAPIServerEtcdClientCertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "sa",
|
||||
short: "Generates a private key for signing service account tokens along with its public key",
|
||||
long: saKeyLongDesc,
|
||||
cmdFunc: certsphase.CreateServiceAccountKeyAndPublicKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "front-proxy-ca",
|
||||
short: "Generates a front proxy CA certificate and key for a Kubernetes cluster",
|
||||
long: frontProxyCaCertLongDesc,
|
||||
cmdFunc: certsphase.CreateFrontProxyCACertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "front-proxy-client",
|
||||
short: "Generates a front proxy CA client certificate and key for a Kubernetes cluster",
|
||||
long: frontProxyClientCertLongDesc,
|
||||
cmdFunc: certsphase.CreateFrontProxyClientCertAndKeyFiles,
|
||||
// Special case commands
|
||||
// All runs CreatePKIAssets, which isn't a particular certificate
|
||||
allCmd := &cobra.Command{
|
||||
Use: "all",
|
||||
Short: "Generates all PKI assets necessary to establish the control plane",
|
||||
Long: allCertsLongDesc,
|
||||
Example: allCertsExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = certsphase.CreatePKIAssets(internalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
addFlags(allCmd, &cfgPath, cfg, true)
|
||||
|
||||
for _, properties := range subCmdProperties {
|
||||
// Creates the UX Command
|
||||
cmd := &cobra.Command{
|
||||
Use: properties.use,
|
||||
Short: properties.short,
|
||||
Long: properties.long,
|
||||
Example: properties.examples,
|
||||
Run: runCmdFunc(properties.cmdFunc, &cfgPath, cfg, defaultKubernetesVersion),
|
||||
}
|
||||
// SA creates the private/public key pair, which doesn't use x509 at all
|
||||
saCmd := &cobra.Command{
|
||||
Use: "sa",
|
||||
Short: "Generates a private key for signing service account tokens along with its public key",
|
||||
Long: saKeyLongDesc,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Add flags to the command
|
||||
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
|
||||
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where to save the certificates")
|
||||
if properties.use == "all" || properties.use == "apiserver" {
|
||||
cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, "Alternative domain for services, to use for the API server serving cert")
|
||||
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "Alternative range of IP address for service VIPs, from which derives the internal API server VIP that will be added to the API Server serving cert")
|
||||
cmd.Flags().StringSliceVar(&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", []string{}, "Optional extra altnames to use for the API server serving cert. Can be both IP addresses and DNS names")
|
||||
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address the API server is accessible on, to use for the API server serving cert")
|
||||
}
|
||||
err = certsphase.CreateServiceAccountKeyAndPublicKeyFiles(internalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
addFlags(saCmd, &cfgPath, cfg, false)
|
||||
|
||||
subCmds = append(subCmds, cmd)
|
||||
subCmds := []*cobra.Command{allCmd, saCmd}
|
||||
|
||||
certTree, err := certsphase.GetDefaultCertList().AsMap().CertTree()
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
for ca, certList := range certTree {
|
||||
// Don't use pointers from for loops, they will be rewrittenb
|
||||
caCmds := makeCommandsForCA(ca, certList, &cfgPath, cfg)
|
||||
subCmds = append(subCmds, caCmds...)
|
||||
}
|
||||
|
||||
return subCmds
|
||||
}
|
||||
|
||||
// runCmdFunc creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters)
|
||||
func runCmdFunc(cmdFunc func(cfg *kubeadmapi.InitConfiguration) error, cfgPath *string, cfg *kubeadmapiv1alpha3.InitConfiguration, defaultKubernetesVersion string) func(cmd *cobra.Command, args []string) {
|
||||
func makeCmd(certSpec *certsphase.KubeadmCert, cfgPath *string, cfg *kubeadmapiv1alpha3.InitConfiguration) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: certSpec.Name,
|
||||
Short: fmt.Sprintf("Generates the %s", certSpec.LongName),
|
||||
Long: fmt.Sprintf(
|
||||
genericLongDesc,
|
||||
certSpec.LongName,
|
||||
certSpec.BaseName,
|
||||
getSANDescription(certSpec),
|
||||
),
|
||||
}
|
||||
addFlags(cmd, cfgPath, cfg, certSpec.Name == "apiserver")
|
||||
// Add flags to the command
|
||||
return cmd
|
||||
}
|
||||
|
||||
// the following statement build a closure that wraps a call to a cmdFunc, binding
|
||||
// the function itself with the specific parameters of each sub command.
|
||||
// Please note that specific parameter should be passed as value, while other parameters - passed as reference -
|
||||
// are shared between sub commands and gets access to current value e.g. flags value.
|
||||
func getSANDescription(certSpec *certsphase.KubeadmCert) string {
|
||||
//Defaulted config we will use to get SAN certs
|
||||
defaultConfig := &kubeadmapiv1alpha3.InitConfiguration{
|
||||
API: kubeadmapiv1alpha3.API{
|
||||
// GetAPIServerAltNames errors without an AdvertiseAddress; this is as good as any.
|
||||
AdvertiseAddress: "127.0.0.1",
|
||||
},
|
||||
}
|
||||
defaultInternalConfig := &kubeadmapi.InitConfiguration{}
|
||||
|
||||
return func(cmd *cobra.Command, args []string) {
|
||||
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmscheme.Scheme.Default(defaultConfig)
|
||||
kubeadmscheme.Scheme.Convert(defaultConfig, defaultInternalConfig, nil)
|
||||
|
||||
certConfig, err := certSpec.GetConfig(defaultInternalConfig)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if len(certConfig.AltNames.DNSNames) == 0 && len(certConfig.AltNames.IPs) == 0 {
|
||||
return ""
|
||||
}
|
||||
// This mutates the certConfig, but we're throwing it after we construct the command anyway
|
||||
sans := []string{}
|
||||
|
||||
for _, dnsName := range certConfig.AltNames.DNSNames {
|
||||
if dnsName != "" {
|
||||
sans = append(sans, dnsName)
|
||||
}
|
||||
}
|
||||
|
||||
// This is used for unit testing only...
|
||||
// If we wouldn't set this to something, the code would dynamically look up the version from the internet
|
||||
// By setting this explicitly for tests workarounds that
|
||||
if defaultKubernetesVersion != "" {
|
||||
cfg.KubernetesVersion = defaultKubernetesVersion
|
||||
} else {
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
err := SetKubernetesVersion(nil, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
for _, ip := range certConfig.AltNames.IPs {
|
||||
sans = append(sans, ip.String())
|
||||
}
|
||||
return fmt.Sprintf("\n\nDefault SANs are %s", strings.Join(sans, ", "))
|
||||
}
|
||||
|
||||
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
|
||||
func addFlags(cmd *cobra.Command, cfgPath *string, cfg *kubeadmapiv1alpha3.InitConfiguration, addAPIFlags bool) {
|
||||
cmd.Flags().StringVar(cfgPath, "config", *cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
|
||||
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where to save the certificates")
|
||||
if addAPIFlags {
|
||||
cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, "Alternative domain for services, to use for the API server serving cert")
|
||||
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "Alternative range of IP address for service VIPs, from which derives the internal API server VIP that will be added to the API Server serving cert")
|
||||
cmd.Flags().StringSliceVar(&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", []string{}, "Optional extra altnames to use for the API server serving cert. Can be both IP addresses and DNS names")
|
||||
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address the API server is accessible on, to use for the API server serving cert")
|
||||
}
|
||||
}
|
||||
|
||||
func makeCommandsForCA(ca *certsphase.KubeadmCert, certList []*certsphase.KubeadmCert, cfgPath *string, cfg *kubeadmapiv1alpha3.InitConfiguration) []*cobra.Command {
|
||||
subCmds := []*cobra.Command{}
|
||||
|
||||
caCmd := makeCmd(ca, cfgPath, cfg)
|
||||
caCmd.Run = func(cmd *cobra.Command, args []string) {
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Execute the cmdFunc
|
||||
err = cmdFunc(internalcfg)
|
||||
err = certsphase.CreateCACertAndKeyFiles(ca, internalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
subCmds = append(subCmds, caCmd)
|
||||
|
||||
for _, cert := range certList {
|
||||
certCmd := makeCommandForCert(cert, ca, cfgPath, cfg)
|
||||
subCmds = append(subCmds, certCmd)
|
||||
}
|
||||
|
||||
return subCmds
|
||||
}
|
||||
|
||||
func makeCommandForCert(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert, cfgPath *string, cfg *kubeadmapiv1alpha3.InitConfiguration) *cobra.Command {
|
||||
certCmd := makeCmd(cert, cfgPath, cfg)
|
||||
|
||||
certCmd.Run = func(cmd *cobra.Command, args []string) {
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = certsphase.CreateCertAndKeyFilesWithCA(cert, caCert, internalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
return certCmd
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package phases
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
|
@ -146,18 +147,21 @@ func TestSubCmdCertsCreateFilesWithFlags(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
// Create temp folder for the test case
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
t.Run(strings.Join(test.subCmds, ","), func(t *testing.T) {
|
||||
// Create temp folder for the test case
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// executes given sub commands
|
||||
for _, subCmdName := range test.subCmds {
|
||||
certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, subCmdName, certDirFlag)
|
||||
}
|
||||
// executes given sub commands
|
||||
for _, subCmdName := range test.subCmds {
|
||||
fmt.Printf("running command %q\n", subCmdName)
|
||||
certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, subCmdName, certDirFlag)
|
||||
}
|
||||
|
||||
// verify expected files are there
|
||||
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
|
||||
// verify expected files are there
|
||||
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,8 +230,12 @@ 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{"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"},
|
||||
|
@ -250,26 +258,28 @@ func TestSubCmdCertsCreateFilesWithConfigFile(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
// Create temp folder for the test case
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
t.Run(strings.Join(test.subCmds, ","), func(t *testing.T) {
|
||||
// Create temp folder for the test case
|
||||
|
||||
certdir := tmpdir
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
|
||||
CertificatesDir: certdir,
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
|
||||
}
|
||||
configPath := testutil.SetupInitConfigurationFile(t, tmpdir, cfg)
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
|
||||
CertificatesDir: tmpdir,
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
|
||||
}
|
||||
configPath := testutil.SetupInitConfigurationFile(t, tmpdir, cfg)
|
||||
|
||||
// executes given sub commands
|
||||
for _, subCmdName := range test.subCmds {
|
||||
configFlag := fmt.Sprintf("--config=%s", configPath)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, subCmdName, configFlag)
|
||||
}
|
||||
// executes given sub commands
|
||||
for _, subCmdName := range test.subCmds {
|
||||
t.Logf("running subcommand %q", subCmdName)
|
||||
configFlag := fmt.Sprintf("--config=%s", configPath)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, subCmdName, configFlag)
|
||||
}
|
||||
|
||||
// verify expected files are there
|
||||
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
|
||||
// verify expected files are there
|
||||
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ type configMutatorsFunc func(*kubeadmapi.InitConfiguration, *certutil.Config) er
|
|||
// KubeadmCert represents a certificate that Kubeadm will create to function properly.
|
||||
type KubeadmCert struct {
|
||||
Name string
|
||||
LongName string
|
||||
BaseName string
|
||||
CAName string
|
||||
// Some attributes will depend on the InitConfiguration, only known at runtime.
|
||||
|
@ -57,13 +58,14 @@ func (k *KubeadmCert) CreateFromCA(ic *kubeadmapi.InitConfiguration, caCert *x50
|
|||
if err != nil {
|
||||
return fmt.Errorf("couldn't create %q certificate: %v", k.Name, err)
|
||||
}
|
||||
cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, *cfg)
|
||||
cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writeCertificateAuthorithyFilesIfNotExist(
|
||||
writeCertificateFilesIfNotExist(
|
||||
ic.CertificatesDir,
|
||||
k.BaseName,
|
||||
caCert,
|
||||
cert,
|
||||
key,
|
||||
)
|
||||
|
@ -71,14 +73,42 @@ func (k *KubeadmCert) CreateFromCA(ic *kubeadmapi.InitConfiguration, caCert *x50
|
|||
return nil
|
||||
}
|
||||
|
||||
// CreateAsCA creates a certificate authority, writing the files to disk and also returning the created CA so it can be used to sign child certs.
|
||||
func (k *KubeadmCert) CreateAsCA(ic *kubeadmapi.InitConfiguration) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
cfg, err := k.GetConfig(ic)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("couldn't get configuration for %q CA certificate: %v", k.Name, err)
|
||||
}
|
||||
caCert, caKey, err := NewCACertAndKey(cfg)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("couldn't generate %q CA certificate: %v", k.Name, err)
|
||||
}
|
||||
|
||||
err = writeCertificateAuthorithyFilesIfNotExist(
|
||||
ic.CertificatesDir,
|
||||
k.BaseName,
|
||||
caCert,
|
||||
caKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("couldn't write out %q CA certificate: %v", k.Name, err)
|
||||
}
|
||||
|
||||
return caCert, caKey, 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()
|
||||
cfg, err := ca.GetConfig(ic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
caCert, caKey, err := NewCACertAndKey(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -89,12 +119,13 @@ func (t CertificateTree) CreateTree(ic *kubeadmapi.InitConfiguration) error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := writeCertificateAuthorithyFilesIfNotExist(
|
||||
err = writeCertificateAuthorithyFilesIfNotExist(
|
||||
ic.CertificatesDir,
|
||||
ca.BaseName,
|
||||
caCert,
|
||||
caKey,
|
||||
); err != nil {
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +202,8 @@ func GetCertsWithoutEtcd() Certificates {
|
|||
var (
|
||||
// KubeadmCertRootCA is the definition of the Kubernetes Root CA for the API Server and kubelet.
|
||||
KubeadmCertRootCA = KubeadmCert{
|
||||
Name: "root-ca",
|
||||
Name: "ca",
|
||||
LongName: "self-signed kubernetes CA to provision identities for other kuberenets components",
|
||||
BaseName: kubeadmconstants.CACertAndKeyBaseName,
|
||||
config: certutil.Config{
|
||||
CommonName: "kubernetes",
|
||||
|
@ -179,9 +211,10 @@ var (
|
|||
}
|
||||
// KubeadmCertAPIServer is the definition of the cert used to serve the kubernetes API.
|
||||
KubeadmCertAPIServer = KubeadmCert{
|
||||
Name: "api-server",
|
||||
Name: "apiserver",
|
||||
LongName: "certificate for serving the kubernetes API",
|
||||
BaseName: kubeadmconstants.APIServerCertAndKeyBaseName,
|
||||
CAName: "root-ca",
|
||||
CAName: "ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerCertCommonName,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
|
@ -192,9 +225,10 @@ var (
|
|||
}
|
||||
// KubeadmCertKubeletClient is the definition of the cert used by the API server to access the kubelet.
|
||||
KubeadmCertKubeletClient = KubeadmCert{
|
||||
Name: "api-server-kubelet-client",
|
||||
Name: "apiserver-kubelet-client",
|
||||
LongName: "Client certificate for the API server to connect to kubelet",
|
||||
BaseName: kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
|
||||
CAName: "root-ca",
|
||||
CAName: "ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.APIServerKubeletClientCertCommonName,
|
||||
Organization: []string{kubeadmconstants.MastersGroup},
|
||||
|
@ -205,6 +239,7 @@ var (
|
|||
// KubeadmCertFrontProxyCA is the definition of the CA used for the front end proxy.
|
||||
KubeadmCertFrontProxyCA = KubeadmCert{
|
||||
Name: "front-proxy-ca",
|
||||
LongName: "self-signed CA to provision identities for front proxy",
|
||||
BaseName: kubeadmconstants.FrontProxyCACertAndKeyBaseName,
|
||||
config: certutil.Config{
|
||||
CommonName: "front-proxy-ca",
|
||||
|
@ -215,6 +250,7 @@ var (
|
|||
KubeadmCertFrontProxyClient = KubeadmCert{
|
||||
Name: "front-proxy-client",
|
||||
BaseName: kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
|
||||
LongName: "client for the front proxy",
|
||||
CAName: "front-proxy-ca",
|
||||
config: certutil.Config{
|
||||
CommonName: kubeadmconstants.FrontProxyClientCertCommonName,
|
||||
|
@ -225,6 +261,7 @@ var (
|
|||
// KubeadmCertEtcdCA is the definition of the root CA used by the hosted etcd server.
|
||||
KubeadmCertEtcdCA = KubeadmCert{
|
||||
Name: "etcd-ca",
|
||||
LongName: "self-signed CA to provision identities for etcd",
|
||||
BaseName: kubeadmconstants.EtcdCACertAndKeyBaseName,
|
||||
config: certutil.Config{
|
||||
CommonName: "etcd-ca",
|
||||
|
@ -233,6 +270,7 @@ var (
|
|||
// KubeadmCertEtcdServer is the definition of the cert used to serve etcd to clients.
|
||||
KubeadmCertEtcdServer = KubeadmCert{
|
||||
Name: "etcd-server",
|
||||
LongName: "certificate for serving etcd",
|
||||
BaseName: kubeadmconstants.EtcdServerCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
|
@ -250,6 +288,7 @@ var (
|
|||
// KubeadmCertEtcdPeer is the definition of the cert used by etcd peers to access each other.
|
||||
KubeadmCertEtcdPeer = KubeadmCert{
|
||||
Name: "etcd-peer",
|
||||
LongName: "credentials for etcd nodes to communicate with each other",
|
||||
BaseName: kubeadmconstants.EtcdPeerCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
|
@ -262,7 +301,8 @@ var (
|
|||
}
|
||||
// KubeadmCertEtcdHealthcheck is the definition of the cert used by Kubernetes to check the health of the etcd server.
|
||||
KubeadmCertEtcdHealthcheck = KubeadmCert{
|
||||
Name: "etcd-healthcheck",
|
||||
Name: "etcd-healthcheck-client",
|
||||
LongName: "client certificate for liveness probes to healtcheck etcd",
|
||||
BaseName: kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
|
@ -273,7 +313,8 @@ var (
|
|||
}
|
||||
// KubeadmCertEtcdAPIClient is the definition of the cert used by the API server to access etcd.
|
||||
KubeadmCertEtcdAPIClient = KubeadmCert{
|
||||
Name: "etcd-api-client",
|
||||
Name: "apiserver-etcd-client",
|
||||
LongName: "client apiserver uses to access etcd",
|
||||
BaseName: kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName,
|
||||
CAName: "etcd-ca",
|
||||
config: certutil.Config{
|
||||
|
@ -288,7 +329,7 @@ func makeAltNamesMutator(f func(*kubeadmapi.InitConfiguration) (*certutil.AltNam
|
|||
return func(mc *kubeadmapi.InitConfiguration, cc *certutil.Config) error {
|
||||
altNames, err := f(mc)
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
cc.AltNames = *altNames
|
||||
return nil
|
||||
|
|
|
@ -66,186 +66,6 @@ func CreatePKIAssets(cfg *kubeadmapi.InitConfiguration) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// CreateCACertAndKeyFiles create a new self signed cluster CA certificate and key files.
|
||||
// If the CA certificate and key files already exists in the target folder, they are used only if evaluated equal; otherwise an error is returned.
|
||||
func CreateCACertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("create a new self signed cluster CA certificate and key files")
|
||||
caCert, caKey, err := NewCACertAndKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateAuthorithyFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.CACertAndKeyBaseName,
|
||||
caCert,
|
||||
caKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateAPIServerCertAndKeyFiles create a new certificate and key files for the apiserver.
|
||||
// If the apiserver certificate and key files already exists in the target folder, they are used only if evaluated equal; otherwise an error is returned.
|
||||
// It assumes the cluster CA certificate and key files exist in the CertificatesDir.
|
||||
func CreateAPIServerCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a new certificate and key files for the apiserver")
|
||||
caCert, caKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
apiCert, apiKey, err := NewAPIServerCertAndKey(cfg, caCert, caKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.APIServerCertAndKeyBaseName,
|
||||
caCert,
|
||||
apiCert,
|
||||
apiKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateAPIServerKubeletClientCertAndKeyFiles create a new certificate for kubelets calling apiserver.
|
||||
// If the apiserver-kubelet-client certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned.
|
||||
// It assumes the cluster CA certificate and key files exist in the CertificatesDir.
|
||||
func CreateAPIServerKubeletClientCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a new certificate for kubelets calling apiserver")
|
||||
caCert, caKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
apiKubeletClientCert, apiKubeletClientKey, err := NewAPIServerKubeletClientCertAndKey(cfg, caCert, caKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
|
||||
caCert,
|
||||
apiKubeletClientCert,
|
||||
apiKubeletClientKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateEtcdCACertAndKeyFiles create a self signed etcd CA certificate and key files.
|
||||
// The etcd CA and client certs are used to secure communication between etcd peers and connections to etcd from the API server.
|
||||
// This is a separate CA, so that kubernetes client identities cannot connect to etcd directly or peer with the etcd cluster.
|
||||
// If the etcd CA certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned.
|
||||
func CreateEtcdCACertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a self signed etcd CA certificate and key files")
|
||||
etcdCACert, etcdCAKey, err := NewEtcdCACertAndKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateAuthorithyFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.EtcdCACertAndKeyBaseName,
|
||||
etcdCACert,
|
||||
etcdCAKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateEtcdServerCertAndKeyFiles create a new certificate and key file for etcd.
|
||||
// If the etcd serving 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 CreateEtcdServerCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a new server certificate and key files for etcd")
|
||||
etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
etcdServerCert, etcdServerKey, err := NewEtcdServerCertAndKey(cfg, etcdCACert, etcdCAKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.EtcdServerCertAndKeyBaseName,
|
||||
etcdCACert,
|
||||
etcdServerCert,
|
||||
etcdServerKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateEtcdPeerCertAndKeyFiles create a new certificate and key file for etcd peering.
|
||||
// If the etcd peer 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 CreateEtcdPeerCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a new certificate and key files for etcd peering")
|
||||
etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
etcdPeerCert, etcdPeerKey, err := NewEtcdPeerCertAndKey(cfg, etcdCACert, etcdCAKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.EtcdPeerCertAndKeyBaseName,
|
||||
etcdCACert,
|
||||
etcdPeerCert,
|
||||
etcdPeerKey,
|
||||
)
|
||||
}
|
||||
|
||||
// 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.InitConfiguration) error {
|
||||
|
||||
etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
etcdHealthcheckClientCert, etcdHealthcheckClientKey, err := NewEtcdHealthcheckClientCertAndKey(cfg, 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
|
||||
func CreateAPIServerEtcdClientCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a new client certificate for the apiserver calling etcd")
|
||||
etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
apiEtcdClientCert, apiEtcdClientKey, err := NewAPIServerEtcdClientCertAndKey(cfg, etcdCACert, etcdCAKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName,
|
||||
etcdCACert,
|
||||
apiEtcdClientCert,
|
||||
apiEtcdClientKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateServiceAccountKeyAndPublicKeyFiles create a new public/private key files for signing service account users.
|
||||
// If the sa public/private key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned.
|
||||
func CreateServiceAccountKeyAndPublicKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
|
@ -262,118 +82,8 @@ func CreateServiceAccountKeyAndPublicKeyFiles(cfg *kubeadmapi.InitConfiguration)
|
|||
)
|
||||
}
|
||||
|
||||
// CreateFrontProxyCACertAndKeyFiles create a self signed front proxy CA certificate and key files.
|
||||
// Front proxy CA and client certs are used to secure a front proxy authenticator which is used to assert identity
|
||||
// without the client cert; This is a separate CA, so that front proxy identities cannot hit the API and normal client certs cannot be used
|
||||
// as front proxies.
|
||||
// If the front proxy CA certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned.
|
||||
func CreateFrontProxyCACertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a self signed front proxy CA certificate and key files")
|
||||
frontProxyCACert, frontProxyCAKey, err := NewFrontProxyCACertAndKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateAuthorithyFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.FrontProxyCACertAndKeyBaseName,
|
||||
frontProxyCACert,
|
||||
frontProxyCAKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateFrontProxyClientCertAndKeyFiles create a new certificate for proxy server client.
|
||||
// If the front-proxy-client certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned.
|
||||
// It assumes the front proxy CA certificate and key files exist in the CertificatesDir.
|
||||
func CreateFrontProxyClientCertAndKeyFiles(cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a new certificate for proxy server client")
|
||||
frontProxyCACert, frontProxyCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
frontProxyClientCert, frontProxyClientKey, err := NewFrontProxyClientCertAndKey(cfg, frontProxyCACert, frontProxyCAKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
|
||||
frontProxyCACert,
|
||||
frontProxyClientCert,
|
||||
frontProxyClientKey,
|
||||
)
|
||||
}
|
||||
|
||||
// NewCACertAndKey will generate a self signed CA.
|
||||
func NewCACertAndKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
caCert, caKey, err := pkiutil.NewCertificateAuthority()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while generating CA certificate and key: %v", err)
|
||||
}
|
||||
|
||||
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) {
|
||||
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(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.
|
||||
func NewEtcdCACertAndKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
etcdCACert, etcdCAKey, err := pkiutil.NewCertificateAuthority()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while generating etcd CA certificate and key: %v", err)
|
||||
}
|
||||
|
||||
return etcdCACert, etcdCAKey, nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
return newCertAndKeyFromSpec(&KubeadmCertEtcdPeer, cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
// NewEtcdHealthcheckClientCertAndKey generate certificate for liveness probes to healthcheck etcd, signed by the given CA.
|
||||
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(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.
|
||||
func NewServiceAccountSigningKey() (*rsa.PrivateKey, error) {
|
||||
|
||||
// The key does NOT exist, let's generate it now
|
||||
saSigningKey, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
|
@ -383,23 +93,71 @@ func NewServiceAccountSigningKey() (*rsa.PrivateKey, error) {
|
|||
return saSigningKey, nil
|
||||
}
|
||||
|
||||
// NewFrontProxyCACertAndKey generate a self signed front proxy CA.
|
||||
func NewFrontProxyCACertAndKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
// NewCACertAndKey will generate a self signed CA.
|
||||
func NewCACertAndKey(certSpec *certutil.Config) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
||||
frontProxyCACert, frontProxyCAKey, err := pkiutil.NewCertificateAuthority()
|
||||
caCert, caKey, err := pkiutil.NewCertificateAuthority(certSpec)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failure while generating front-proxy CA certificate and key: %v", err)
|
||||
return nil, nil, fmt.Errorf("failure while generating CA certificate and key: %v", err)
|
||||
}
|
||||
|
||||
return frontProxyCACert, frontProxyCAKey, nil
|
||||
return caCert, caKey, nil
|
||||
}
|
||||
|
||||
// NewFrontProxyClientCertAndKey generate certificate for proxy server client, signed by the given front proxy CA.
|
||||
func NewFrontProxyClientCertAndKey(cfg *kubeadmapi.InitConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
return newCertAndKeyFromSpec(&KubeadmCertFrontProxyClient, cfg, caCert, caKey)
|
||||
// CreateCACertAndKeyFiles generates and writes out a given certificate authority.
|
||||
// The certSpec should be one of the variables from this package.
|
||||
func CreateCACertAndKeyFiles(certSpec *KubeadmCert, cfg *kubeadmapi.InitConfiguration) error {
|
||||
if certSpec.CAName != "" {
|
||||
return fmt.Errorf("This function should only be used for CAs, but cert %s has CA %s", certSpec.Name, certSpec.CAName)
|
||||
}
|
||||
glog.V(1).Infoln("creating a new certificate authority for %s", certSpec.Name)
|
||||
|
||||
certConfig, err := certSpec.GetConfig(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
caCert, caKey, err := NewCACertAndKey(certConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeCertificateAuthorithyFilesIfNotExist(
|
||||
cfg.CertificatesDir,
|
||||
certSpec.BaseName,
|
||||
caCert,
|
||||
caKey,
|
||||
)
|
||||
}
|
||||
|
||||
// CreateCertAndKeyFilesWithCA loads the given certificate authority from disk, then generates and writes out the given certificate and key.
|
||||
// The certSpec and caCertSpec should both be one of the variables from this package.
|
||||
func CreateCertAndKeyFilesWithCA(certSpec *KubeadmCert, caCertSpec *KubeadmCert, cfg *kubeadmapi.InitConfiguration) error {
|
||||
if certSpec.CAName != caCertSpec.Name {
|
||||
return fmt.Errorf("Expected CAname for %s to be %q, but was %s", certSpec.Name, certSpec.CAName, caCertSpec.Name)
|
||||
}
|
||||
|
||||
caCert, caKey, err := loadCertificateAuthority(cfg.CertificatesDir, caCertSpec.BaseName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't load CA certificate %s: %v", caCertSpec.Name, err)
|
||||
}
|
||||
|
||||
return certSpec.CreateFromCA(cfg, caCert, caKey)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// loadCertificateAuthority loads certificate authority
|
||||
func loadCertificateAuthority(pkiDir string, baseName string) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
// Checks if certificate authority exists in the PKI directory
|
||||
if !pkiutil.CertOrKeyExist(pkiDir, baseName) {
|
||||
|
@ -422,7 +180,7 @@ func loadCertificateAuthority(pkiDir string, baseName string) (*x509.Certificate
|
|||
|
||||
// writeCertificateAuthorithyFilesIfNotExist 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,
|
||||
// existing and the eexpected 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 writeCertificateAuthorithyFilesIfNotExist(pkiDir string, baseName string, caCert *x509.Certificate, caKey *rsa.PrivateKey) error {
|
||||
|
||||
|
|
|
@ -20,11 +20,12 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
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"
|
||||
|
@ -32,10 +33,30 @@ import (
|
|||
certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs"
|
||||
)
|
||||
|
||||
func TestWriteCertificateAuthorithyFilesIfNotExist(t *testing.T) {
|
||||
func createCACert(t *testing.T) (*x509.Certificate, *rsa.PrivateKey) {
|
||||
certCfg := &certutil.Config{CommonName: "kubernetes"}
|
||||
cert, key, err := NewCACertAndKey(certCfg)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't create CA: %v", err)
|
||||
}
|
||||
return cert, key
|
||||
}
|
||||
|
||||
setupCert, setupKey, _ := NewCACertAndKey()
|
||||
caCert, caKey, _ := NewCACertAndKey()
|
||||
func createTestCert(t *testing.T, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey) {
|
||||
cert, key, err := pkiutil.NewCertAndKey(caCert, caKey,
|
||||
&certutil.Config{
|
||||
CommonName: "testCert",
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't create test cert: %v", err)
|
||||
}
|
||||
return cert, key
|
||||
}
|
||||
|
||||
func TestWriteCertificateAuthorithyFilesIfNotExist(t *testing.T) {
|
||||
setupCert, setupKey := createCACert(t)
|
||||
caCert, caKey := createCACert(t)
|
||||
|
||||
var tests = []struct {
|
||||
setupFunc func(pkiDir string) error
|
||||
|
@ -60,7 +81,7 @@ func TestWriteCertificateAuthorithyFilesIfNotExist(t *testing.T) {
|
|||
},
|
||||
{ // cert exists, but it is not a ca > err
|
||||
setupFunc: func(pkiDir string) error {
|
||||
cert, key, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, setupCert, setupKey)
|
||||
cert, key := createTestCert(t, setupCert, setupKey)
|
||||
return writeCertificateFilesIfNotExist(pkiDir, "dummy", setupCert, cert, key)
|
||||
},
|
||||
expectedError: true,
|
||||
|
@ -110,9 +131,9 @@ func TestWriteCertificateAuthorithyFilesIfNotExist(t *testing.T) {
|
|||
|
||||
func TestWriteCertificateFilesIfNotExist(t *testing.T) {
|
||||
|
||||
caCert, caKey, _ := NewFrontProxyCACertAndKey()
|
||||
setupCert, setupKey, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
cert, key, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
caCert, caKey := createCACert(t)
|
||||
setupCert, setupKey := createTestCert(t, caCert, caKey)
|
||||
cert, key := createTestCert(t, caCert, caKey)
|
||||
|
||||
var tests = []struct {
|
||||
setupFunc func(pkiDir string) error
|
||||
|
@ -137,8 +158,8 @@ func TestWriteCertificateFilesIfNotExist(t *testing.T) {
|
|||
},
|
||||
{ // cert exists, is signed by another ca > err
|
||||
setupFunc: func(pkiDir string) error {
|
||||
anotherCaCert, anotherCaKey, _ := NewFrontProxyCACertAndKey()
|
||||
anotherCert, anotherKey, _ := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, anotherCaCert, anotherCaKey)
|
||||
anotherCaCert, anotherCaKey := createCACert(t)
|
||||
anotherCert, anotherKey := createTestCert(t, anotherCaCert, anotherCaKey)
|
||||
|
||||
return writeCertificateFilesIfNotExist(pkiDir, "dummy", anotherCaCert, anotherCert, anotherKey)
|
||||
},
|
||||
|
@ -259,7 +280,8 @@ func TestWriteKeyFilesIfNotExist(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewCACertAndKey(t *testing.T) {
|
||||
caCert, _, err := NewCACertAndKey()
|
||||
certCfg := &certutil.Config{CommonName: "kubernetes"}
|
||||
caCert, _, err := NewCACertAndKey(certCfg)
|
||||
if err != nil {
|
||||
t.Fatalf("failed call NewCACertAndKey: %v", err)
|
||||
}
|
||||
|
@ -267,269 +289,90 @@ func TestNewCACertAndKey(t *testing.T) {
|
|||
certstestutil.AssertCertificateIsCa(t, caCert)
|
||||
}
|
||||
|
||||
func TestNewAPIServerCertAndKey(t *testing.T) {
|
||||
hostname := "valid-hostname"
|
||||
|
||||
advertiseAddresses := []string{"1.2.3.4", "1:2:3::4"}
|
||||
for _, addr := range advertiseAddresses {
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddress: addr},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"},
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname},
|
||||
}
|
||||
caCert, caKey, err := NewCACertAndKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
apiServerCert, _, err := NewAPIServerCertAndKey(cfg, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsSignedByCa(t, apiServerCert, caCert)
|
||||
certstestutil.AssertCertificateHasServerAuthUsage(t, apiServerCert)
|
||||
certstestutil.AssertCertificateHasDNSNames(t, apiServerCert, hostname, "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local")
|
||||
certstestutil.AssertCertificateHasIPAddresses(t, apiServerCert, net.ParseIP("10.96.0.1"), net.ParseIP(addr))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAPIServerKubeletClientCertAndKey(t *testing.T) {
|
||||
caCert, caKey, err := NewCACertAndKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
apiKubeletClientCert, _, err := NewAPIServerKubeletClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsSignedByCa(t, apiKubeletClientCert, caCert)
|
||||
certstestutil.AssertCertificateHasClientAuthUsage(t, apiKubeletClientCert)
|
||||
certstestutil.AssertCertificateHasOrganizations(t, apiKubeletClientCert, kubeadmconstants.MastersGroup)
|
||||
}
|
||||
|
||||
func TestNewEtcdCACertAndKey(t *testing.T) {
|
||||
etcdCACert, _, err := NewEtcdCACertAndKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsCa(t, etcdCACert)
|
||||
}
|
||||
|
||||
func TestNewEtcdServerCertAndKey(t *testing.T) {
|
||||
proxy := "user-etcd-proxy"
|
||||
proxyIP := "10.10.10.100"
|
||||
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{
|
||||
Name: "etcd-server-cert",
|
||||
},
|
||||
Etcd: kubeadmapi.Etcd{
|
||||
Local: &kubeadmapi.LocalEtcd{
|
||||
ServerCertSANs: []string{
|
||||
proxy,
|
||||
proxyIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
caCert, caKey, err := NewCACertAndKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
etcdServerCert, _, err := NewEtcdServerCertAndKey(cfg, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsSignedByCa(t, etcdServerCert, caCert)
|
||||
certstestutil.AssertCertificateHasServerAuthUsage(t, etcdServerCert)
|
||||
certstestutil.AssertCertificateHasDNSNames(t, etcdServerCert, "localhost", proxy)
|
||||
certstestutil.AssertCertificateHasIPAddresses(t, etcdServerCert, net.ParseIP("127.0.0.1"), net.ParseIP(proxyIP))
|
||||
}
|
||||
|
||||
func TestNewEtcdPeerCertAndKey(t *testing.T) {
|
||||
hostname := "valid-hostname"
|
||||
proxy := "user-etcd-proxy"
|
||||
proxyIP := "10.10.10.100"
|
||||
|
||||
advertiseAddresses := []string{"1.2.3.4", "1:2:3::4"}
|
||||
for _, addr := range advertiseAddresses {
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddress: addr},
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname},
|
||||
Etcd: kubeadmapi.Etcd{
|
||||
Local: &kubeadmapi.LocalEtcd{
|
||||
PeerCertSANs: []string{
|
||||
proxy,
|
||||
proxyIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
caCert, caKey, err := NewCACertAndKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
etcdPeerCert, _, err := NewEtcdPeerCertAndKey(cfg, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsSignedByCa(t, etcdPeerCert, caCert)
|
||||
certstestutil.AssertCertificateHasServerAuthUsage(t, etcdPeerCert)
|
||||
certstestutil.AssertCertificateHasClientAuthUsage(t, etcdPeerCert)
|
||||
certstestutil.AssertCertificateHasDNSNames(t, etcdPeerCert, hostname, proxy)
|
||||
certstestutil.AssertCertificateHasIPAddresses(t, etcdPeerCert, net.ParseIP(addr), net.ParseIP(proxyIP))
|
||||
}
|
||||
}
|
||||
|
||||
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(&kubeadmapi.InitConfiguration{}, 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 {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
apiEtcdClientCert, _, err := NewAPIServerEtcdClientCertAndKey(&kubeadmapi.InitConfiguration{}, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsSignedByCa(t, apiEtcdClientCert, caCert)
|
||||
certstestutil.AssertCertificateHasClientAuthUsage(t, apiEtcdClientCert)
|
||||
certstestutil.AssertCertificateHasOrganizations(t, apiEtcdClientCert, kubeadmconstants.MastersGroup)
|
||||
}
|
||||
|
||||
func TestNewNewServiceAccountSigningKey(t *testing.T) {
|
||||
|
||||
key, err := NewServiceAccountSigningKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of key: %v", err)
|
||||
}
|
||||
|
||||
if key.N.BitLen() < 2048 {
|
||||
t.Error("Service account signing key has less than 2048 bits size")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFrontProxyCACertAndKey(t *testing.T) {
|
||||
frontProxyCACert, _, err := NewFrontProxyCACertAndKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsCa(t, frontProxyCACert)
|
||||
}
|
||||
|
||||
func TestNewFrontProxyClientCertAndKey(t *testing.T) {
|
||||
frontProxyCACert, frontProxyCAKey, err := NewFrontProxyCACertAndKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
|
||||
frontProxyClientCert, _, err := NewFrontProxyClientCertAndKey(&kubeadmapi.InitConfiguration{}, frontProxyCACert, frontProxyCAKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of cert and key: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsSignedByCa(t, frontProxyClientCert, frontProxyCACert)
|
||||
certstestutil.AssertCertificateHasClientAuthUsage(t, frontProxyClientCert)
|
||||
}
|
||||
|
||||
func TestSharedCertificateExists(t *testing.T) {
|
||||
caCert, caKey := createCACert(t)
|
||||
_, key := createTestCert(t, caCert, caKey)
|
||||
publicKey := &key.PublicKey
|
||||
|
||||
var tests = []struct {
|
||||
setupFunc func(cfg *kubeadmapi.InitConfiguration)
|
||||
name string
|
||||
files pkiFiles
|
||||
expectedError bool
|
||||
}{
|
||||
{ // expected certs exist, pass
|
||||
setupFunc: func(cfg *kubeadmapi.InitConfiguration) {
|
||||
CreateCACertAndKeyFiles(cfg)
|
||||
CreateServiceAccountKeyAndPublicKeyFiles(cfg)
|
||||
CreateFrontProxyCACertAndKeyFiles(cfg)
|
||||
{
|
||||
name: "success",
|
||||
files: pkiFiles{
|
||||
"ca.crt": caCert,
|
||||
"ca.key": caKey,
|
||||
"front-proxy-ca.crt": caCert,
|
||||
"front-proxy-ca.key": caKey,
|
||||
"sa.pub": publicKey,
|
||||
"sa.key": key,
|
||||
},
|
||||
expectedError: false,
|
||||
},
|
||||
{ // expected ca.crt missing
|
||||
setupFunc: func(cfg *kubeadmapi.InitConfiguration) {
|
||||
// start from the condition created by the previous tests
|
||||
os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName))
|
||||
{
|
||||
name: "missing ca.crt",
|
||||
files: pkiFiles{
|
||||
"ca.key": caKey,
|
||||
"front-proxy-ca.crt": caCert,
|
||||
"front-proxy-ca.key": caKey,
|
||||
"sa.pub": publicKey,
|
||||
"sa.key": key,
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
{ // expected sa.key missing
|
||||
setupFunc: func(cfg *kubeadmapi.InitConfiguration) {
|
||||
// start from the condition created by the previous tests
|
||||
CreateCACertAndKeyFiles(cfg)
|
||||
os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName))
|
||||
{
|
||||
name: "missing sa.key",
|
||||
files: pkiFiles{
|
||||
"ca.crt": caCert,
|
||||
"ca.key": caKey,
|
||||
"front-proxy-ca.crt": caCert,
|
||||
"front-proxy-ca.key": caKey,
|
||||
"sa.pub": publicKey,
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
{ // expected front-proxy.crt missing
|
||||
setupFunc: func(cfg *kubeadmapi.InitConfiguration) {
|
||||
// start from the condition created by the previous tests
|
||||
CreateServiceAccountKeyAndPublicKeyFiles(cfg)
|
||||
os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName))
|
||||
{
|
||||
name: "expected front-proxy.crt missing",
|
||||
files: pkiFiles{
|
||||
"ca.crt": caCert,
|
||||
"ca.key": caKey,
|
||||
"front-proxy-ca.key": caKey,
|
||||
"sa.pub": publicKey,
|
||||
"sa.key": key,
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
CertificatesDir: tmpdir,
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
// executes setup func (if necessary)
|
||||
if test.setupFunc != nil {
|
||||
test.setupFunc(cfg)
|
||||
}
|
||||
t.Run("", func(t *testing.T) {
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// executes create func
|
||||
ret, err := SharedCertificateExists(cfg)
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
CertificatesDir: tmpdir,
|
||||
}
|
||||
|
||||
if !test.expectedError && err != nil {
|
||||
t.Errorf("error SharedCertificateExists failed when not expected to fail: %v", err)
|
||||
continue
|
||||
} else if test.expectedError && err == nil {
|
||||
t.Error("error SharedCertificateExists didn't failed when expected")
|
||||
continue
|
||||
} else if test.expectedError {
|
||||
continue
|
||||
}
|
||||
// created expected keys
|
||||
writePKIFiles(t, tmpdir, test.files)
|
||||
|
||||
if ret != (err == nil) {
|
||||
t.Errorf("error SharedCertificateExists returned %v when expected to return %v", ret, err == nil)
|
||||
}
|
||||
// executes create func
|
||||
ret, err := SharedCertificateExists(cfg)
|
||||
|
||||
switch {
|
||||
case !test.expectedError && err != nil:
|
||||
t.Errorf("error SharedCertificateExists failed when not expected to fail: %v", err)
|
||||
case test.expectedError && err == nil:
|
||||
t.Errorf("error SharedCertificateExists didn't failed when expected")
|
||||
case ret != (err == nil):
|
||||
t.Errorf("error SharedCertificateExists returned %v when expected to return %v", ret, err == nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsingExternalCA(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
setupFuncs []func(cfg *kubeadmapi.InitConfiguration) error
|
||||
expected bool
|
||||
|
@ -575,17 +418,20 @@ func TestUsingExternalCA(t *testing.T) {
|
|||
|
||||
func TestValidateMethods(t *testing.T) {
|
||||
|
||||
caCert, caKey := createCACert(t)
|
||||
cert, key := createTestCert(t, caCert, caKey)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setupFuncs []func(cfg *kubeadmapi.InitConfiguration) error
|
||||
files pkiFiles
|
||||
validateFunc func(l certKeyLocation) error
|
||||
loc certKeyLocation
|
||||
expectedSuccess bool
|
||||
}{
|
||||
{
|
||||
name: "validateCACert",
|
||||
setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
CreateCACertAndKeyFiles,
|
||||
files: pkiFiles{
|
||||
"ca.crt": caCert,
|
||||
},
|
||||
validateFunc: validateCACert,
|
||||
loc: certKeyLocation{caBaseName: "ca", baseName: "", uxName: "CA"},
|
||||
|
@ -593,28 +439,30 @@ func TestValidateMethods(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "validateCACertAndKey (files present)",
|
||||
setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
CreateCACertAndKeyFiles,
|
||||
files: pkiFiles{
|
||||
"ca.crt": caCert,
|
||||
"ca.key": caKey,
|
||||
},
|
||||
validateFunc: validateCACertAndKey,
|
||||
loc: certKeyLocation{caBaseName: "ca", baseName: "", uxName: "CA"},
|
||||
expectedSuccess: true,
|
||||
},
|
||||
{
|
||||
name: "validateCACertAndKey (key missing)",
|
||||
setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
CreatePKIAssets,
|
||||
deleteCAKey,
|
||||
files: pkiFiles{
|
||||
"ca.crt": caCert,
|
||||
},
|
||||
name: "validateCACertAndKey (key missing)",
|
||||
validateFunc: validateCACertAndKey,
|
||||
loc: certKeyLocation{caBaseName: "ca", baseName: "", uxName: "CA"},
|
||||
expectedSuccess: false,
|
||||
},
|
||||
{
|
||||
name: "validateSignedCert",
|
||||
setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
CreateCACertAndKeyFiles,
|
||||
CreateAPIServerCertAndKeyFiles,
|
||||
files: pkiFiles{
|
||||
"ca.crt": caCert,
|
||||
"ca.key": caKey,
|
||||
"apiserver.crt": cert,
|
||||
"apiserver.key": key,
|
||||
},
|
||||
validateFunc: validateSignedCert,
|
||||
loc: certKeyLocation{caBaseName: "ca", baseName: "apiserver", uxName: "apiserver"},
|
||||
|
@ -622,8 +470,9 @@ func TestValidateMethods(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "validatePrivatePublicKey",
|
||||
setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
CreateServiceAccountKeyAndPublicKeyFiles,
|
||||
files: pkiFiles{
|
||||
"sa.pub": &key.PublicKey,
|
||||
"sa.key": key,
|
||||
},
|
||||
validateFunc: validatePrivatePublicKey,
|
||||
loc: certKeyLocation{baseName: "sa", uxName: "service account"},
|
||||
|
@ -632,25 +481,11 @@ func TestValidateMethods(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
dir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(dir)
|
||||
test.loc.pkiDir = dir
|
||||
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"},
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"},
|
||||
CertificatesDir: dir,
|
||||
}
|
||||
|
||||
fmt.Println("Testing", test.name)
|
||||
|
||||
for _, f := range test.setupFuncs {
|
||||
if err := f(cfg); err != nil {
|
||||
t.Errorf("error executing setup function: %v", err)
|
||||
}
|
||||
}
|
||||
writePKIFiles(t, dir, test.files)
|
||||
|
||||
err := test.validateFunc(test.loc)
|
||||
if test.expectedSuccess && err != nil {
|
||||
|
@ -661,18 +496,29 @@ func TestValidateMethods(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func deleteCAKey(cfg *kubeadmapi.InitConfiguration) error {
|
||||
if err := os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName)); err != nil {
|
||||
return fmt.Errorf("failed removing %s: %v", kubeadmconstants.CAKeyName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
type pkiFiles map[string]interface{}
|
||||
|
||||
func deleteFrontProxyCAKey(cfg *kubeadmapi.InitConfiguration) error {
|
||||
if err := os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCAKeyName)); err != nil {
|
||||
return fmt.Errorf("failed removing %s: %v", kubeadmconstants.FrontProxyCAKeyName, err)
|
||||
func writePKIFiles(t *testing.T, dir string, files pkiFiles) {
|
||||
for filename, body := range files {
|
||||
switch body := body.(type) {
|
||||
case *x509.Certificate:
|
||||
if err := certutil.WriteCert(path.Join(dir, filename), certutil.EncodeCertPEM(body)); err != nil {
|
||||
t.Errorf("unable to write certificate to file %q: [%v]", dir, err)
|
||||
}
|
||||
case *rsa.PublicKey:
|
||||
publicKeyBytes, err := certutil.EncodePublicKeyPEM(body)
|
||||
if err != nil {
|
||||
t.Errorf("unable to write public key to file %q: [%v]", filename, err)
|
||||
}
|
||||
if err := certutil.WriteKey(path.Join(dir, filename), publicKeyBytes); err != nil {
|
||||
t.Errorf("unable to write public key to file %q: [%v]", filename, err)
|
||||
}
|
||||
case *rsa.PrivateKey:
|
||||
if err := certutil.WriteKey(path.Join(dir, filename), certutil.EncodePrivateKeyPEM(body)); err != nil {
|
||||
t.Errorf("unable to write private key to file %q: [%v]", filename, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestCreateCertificateFilesMethods(t *testing.T) {
|
||||
|
@ -711,57 +557,6 @@ func TestCreateCertificateFilesMethods(t *testing.T) {
|
|||
kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName,
|
||||
},
|
||||
},
|
||||
{
|
||||
createFunc: CreateCACertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName},
|
||||
},
|
||||
{
|
||||
setupFunc: CreateCACertAndKeyFiles,
|
||||
createFunc: CreateAPIServerCertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName},
|
||||
},
|
||||
{
|
||||
setupFunc: CreateCACertAndKeyFiles,
|
||||
createFunc: CreateAPIServerKubeletClientCertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
|
||||
},
|
||||
{
|
||||
createFunc: CreateEtcdCACertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName},
|
||||
},
|
||||
{
|
||||
setupFunc: CreateEtcdCACertAndKeyFiles,
|
||||
createFunc: CreateEtcdServerCertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName},
|
||||
},
|
||||
{
|
||||
setupFunc: CreateEtcdCACertAndKeyFiles,
|
||||
createFunc: CreateEtcdPeerCertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName},
|
||||
},
|
||||
{
|
||||
setupFunc: CreateEtcdCACertAndKeyFiles,
|
||||
createFunc: CreateEtcdHealthcheckClientCertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName},
|
||||
},
|
||||
{
|
||||
setupFunc: CreateEtcdCACertAndKeyFiles,
|
||||
createFunc: CreateAPIServerEtcdClientCertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName},
|
||||
},
|
||||
{
|
||||
createFunc: CreateServiceAccountKeyAndPublicKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName},
|
||||
},
|
||||
{
|
||||
createFunc: CreateFrontProxyCACertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName},
|
||||
},
|
||||
{
|
||||
setupFunc: CreateFrontProxyCACertAndKeyFiles,
|
||||
createFunc: CreateFrontProxyClientCertAndKeyFiles,
|
||||
expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
@ -785,14 +580,6 @@ func TestCreateCertificateFilesMethods(t *testing.T) {
|
|||
cfg.Etcd.External.Endpoints = []string{"192.168.1.1:2379"}
|
||||
}
|
||||
|
||||
// executes setup func (if necessary)
|
||||
if test.setupFunc != nil {
|
||||
if err := test.setupFunc(cfg); err != nil {
|
||||
t.Errorf("error executing setupFunc: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// executes create func
|
||||
if err := test.createFunc(cfg); err != nil {
|
||||
t.Errorf("error executing createFunc: %v", err)
|
||||
|
@ -803,3 +590,17 @@ func TestCreateCertificateFilesMethods(t *testing.T) {
|
|||
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
|
||||
}
|
||||
}
|
||||
|
||||
func deleteCAKey(cfg *kubeadmapi.InitConfiguration) error {
|
||||
if err := os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName)); err != nil {
|
||||
return fmt.Errorf("failed removing %s: %v", kubeadmconstants.CAKeyName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteFrontProxyCAKey(cfg *kubeadmapi.InitConfiguration) error {
|
||||
if err := os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCAKeyName)); err != nil {
|
||||
return fmt.Errorf("failed removing %s: %v", kubeadmconstants.FrontProxyCAKeyName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -34,16 +34,13 @@ import (
|
|||
)
|
||||
|
||||
// NewCertificateAuthority creates new certificate and private key for the certificate authority
|
||||
func NewCertificateAuthority() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
func NewCertificateAuthority(config *certutil.Config) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create private key [%v]", err)
|
||||
}
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: "kubernetes",
|
||||
}
|
||||
cert, err := certutil.NewSelfSignedCACert(config, key)
|
||||
cert, err := certutil.NewSelfSignedCACert(*config, key)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create self-signed certificate [%v]", err)
|
||||
}
|
||||
|
@ -52,13 +49,13 @@ func NewCertificateAuthority() (*x509.Certificate, *rsa.PrivateKey, error) {
|
|||
}
|
||||
|
||||
// NewCertAndKey creates new certificate and key by passing the certificate authority certificate and key
|
||||
func NewCertAndKey(caCert *x509.Certificate, caKey *rsa.PrivateKey, config certutil.Config) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
func NewCertAndKey(caCert *x509.Certificate, caKey *rsa.PrivateKey, config *certutil.Config) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create private key [%v]", err)
|
||||
}
|
||||
|
||||
cert, err := certutil.NewSignedCert(config, key, caCert, caKey)
|
||||
cert, err := certutil.NewSignedCert(*config, key, caCert, caKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to sign certificate [%v]", err)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
func TestNewCertificateAuthority(t *testing.T) {
|
||||
cert, key, err := NewCertificateAuthority()
|
||||
cert, key, err := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"})
|
||||
|
||||
if cert == nil {
|
||||
t.Errorf(
|
||||
|
@ -73,7 +73,7 @@ func TestNewCertAndKey(t *testing.T) {
|
|||
t.Fatalf("Couldn't create rsa Private Key")
|
||||
}
|
||||
caCert := &x509.Certificate{}
|
||||
config := certutil.Config{
|
||||
config := &certutil.Config{
|
||||
CommonName: "test",
|
||||
Organization: []string{"test"},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
|
@ -90,7 +90,7 @@ func TestNewCertAndKey(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHasServerAuth(t *testing.T) {
|
||||
caCert, caKey, _ := NewCertificateAuthority()
|
||||
caCert, caKey, _ := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"})
|
||||
|
||||
var tests = []struct {
|
||||
config certutil.Config
|
||||
|
@ -113,7 +113,7 @@ func TestHasServerAuth(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
cert, _, err := NewCertAndKey(caCert, caKey, rt.config)
|
||||
cert, _, err := NewCertAndKey(caCert, caKey, &rt.config)
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create cert: %v", err)
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ func TestTryLoadCertAndKeyFromDisk(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
caCert, caKey, err := NewCertificateAuthority()
|
||||
caCert, caKey, err := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"})
|
||||
if err != nil {
|
||||
t.Errorf(
|
||||
"failed to create cert and key with an error: %v",
|
||||
|
@ -311,7 +311,7 @@ func TestTryLoadCertFromDisk(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
caCert, _, err := NewCertificateAuthority()
|
||||
caCert, _, err := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"})
|
||||
if err != nil {
|
||||
t.Errorf(
|
||||
"failed to create cert and key with an error: %v",
|
||||
|
@ -361,7 +361,7 @@ func TestTryLoadKeyFromDisk(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
_, caKey, err := NewCertificateAuthority()
|
||||
_, caKey, err := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"})
|
||||
if err != nil {
|
||||
t.Errorf(
|
||||
"failed to create cert and key with an error: %v",
|
||||
|
|
|
@ -222,7 +222,7 @@ func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string) (*clientc
|
|||
Organization: spec.ClientCertAuth.Organizations,
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
clientCert, clientKey, err := pkiutil.NewCertAndKey(spec.CACert, spec.ClientCertAuth.CAKey, clientCertConfig)
|
||||
clientCert, clientKey, err := pkiutil.NewCertAndKey(spec.CACert, spec.ClientCertAuth.CAKey, &clientCertConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failure while creating %s client certificate: %v", spec.ClientName, err)
|
||||
}
|
||||
|
|
|
@ -80,7 +80,6 @@ go_test(
|
|||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library",
|
||||
"//cmd/kubeadm/app/constants: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/etcd:go_default_library",
|
||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
|
|
|
@ -195,7 +195,11 @@ func backupAPIServerCertIfNeeded(cfg *kubeadmapi.InitConfiguration, dryRun bool)
|
|||
if err := backupAPIServerCertAndKey(certAndKeyDir); err != nil {
|
||||
fmt.Printf("[postupgrade] WARNING: failed to backup kube-apiserver cert and key: %v", err)
|
||||
}
|
||||
return certsphase.CreateAPIServerCertAndKeyFiles(cfg)
|
||||
return certsphase.CreateCertAndKeyFilesWithCA(
|
||||
&certsphase.KubeadmCertAPIServer,
|
||||
&certsphase.KubeadmCertRootCA,
|
||||
cfg,
|
||||
)
|
||||
}
|
||||
|
||||
func writeKubeletConfigFiles(client clientset.Interface, cfg *kubeadmapi.InitConfiguration, newK8sVer *version.Version, dryRun bool) error {
|
||||
|
|
|
@ -27,7 +27,6 @@ import (
|
|||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
|
||||
)
|
||||
|
||||
|
@ -148,23 +147,21 @@ func TestShouldBackupAPIServerCertAndKey(t *testing.T) {
|
|||
expected: true,
|
||||
},
|
||||
} {
|
||||
caCert, caKey, err := certsphase.NewCACertAndKey()
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
cfg.CertificatesDir = tmpdir
|
||||
|
||||
caCert, caKey, err := certsphase.KubeadmCertRootCA.CreateAsCA(cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("failed creation of ca cert and key: %v", err)
|
||||
}
|
||||
caCert.NotBefore = caCert.NotBefore.Add(-test.adjustedExpiry).UTC()
|
||||
apiCert, apiKey, err := certsphase.NewAPIServerCertAndKey(cfg, caCert, caKey)
|
||||
|
||||
err = certsphase.KubeadmCertAPIServer.CreateFromCA(cfg, caCert, caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Test %s: failed creation of cert and key: %v", desc, err)
|
||||
}
|
||||
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
if err := pkiutil.WriteCertAndKey(tmpdir, constants.APIServerCertAndKeyBaseName, apiCert, apiKey); err != nil {
|
||||
t.Fatalf("Test %s: failure while saving %s certificate and key: %v", desc, constants.APIServerCertAndKeyBaseName, err)
|
||||
}
|
||||
|
||||
certAndKey := []string{filepath.Join(tmpdir, constants.APIServerCertName), filepath.Join(tmpdir, constants.APIServerKeyName)}
|
||||
for _, path := range certAndKey {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
|
|
|
@ -187,24 +187,27 @@ func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticP
|
|||
|
||||
// ensure etcd certs are generated for etcd and kube-apiserver
|
||||
if component == constants.Etcd || component == constants.KubeAPIServer {
|
||||
if err := certsphase.CreateEtcdCACertAndKeyFiles(cfg); err != nil {
|
||||
|
||||
caCert, caKey, err := certsphase.KubeadmCertEtcdCA.CreateAsCA(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to upgrade the %s CA certificate and key: %v", constants.Etcd, err)
|
||||
}
|
||||
}
|
||||
if component == constants.Etcd {
|
||||
if err := certsphase.CreateEtcdServerCertAndKeyFiles(cfg); err != nil {
|
||||
return fmt.Errorf("failed to upgrade the %s certificate and key: %v", constants.Etcd, err)
|
||||
|
||||
if component == constants.Etcd {
|
||||
if err := certsphase.KubeadmCertEtcdServer.CreateFromCA(cfg, caCert, caKey); err != nil {
|
||||
return fmt.Errorf("failed to upgrade the %s certificate and key: %v", constants.Etcd, err)
|
||||
}
|
||||
if err := certsphase.KubeadmCertEtcdPeer.CreateFromCA(cfg, caCert, caKey); err != nil {
|
||||
return fmt.Errorf("failed to upgrade the %s peer certificate and key: %v", constants.Etcd, err)
|
||||
}
|
||||
if err := certsphase.KubeadmCertEtcdHealthcheck.CreateFromCA(cfg, caCert, caKey); err != nil {
|
||||
return fmt.Errorf("failed to upgrade the %s healthcheck certificate and key: %v", constants.Etcd, err)
|
||||
}
|
||||
}
|
||||
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 {
|
||||
return fmt.Errorf("failed to upgrade the %s %s-client certificate and key: %v", constants.KubeAPIServer, constants.Etcd, err)
|
||||
if component == constants.KubeAPIServer {
|
||||
if err := certsphase.KubeadmCertEtcdAPIClient.CreateFromCA(cfg, caCert, caKey); err != nil {
|
||||
return fmt.Errorf("failed to upgrade the %s %s-client certificate and key: %v", constants.KubeAPIServer, constants.Etcd, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -420,27 +420,16 @@ func TestStaticPodControlPlane(t *testing.T) {
|
|||
t.Fatalf("couldn't create config: %v", err)
|
||||
}
|
||||
|
||||
// Initialize PKI minus any etcd certificates to simulate etcd PKI upgrade
|
||||
certActions := []func(cfg *kubeadmapi.InitConfiguration) error{
|
||||
certsphase.CreateCACertAndKeyFiles,
|
||||
certsphase.CreateAPIServerCertAndKeyFiles,
|
||||
certsphase.CreateAPIServerKubeletClientCertAndKeyFiles,
|
||||
// certsphase.CreateEtcdCACertAndKeyFiles,
|
||||
// certsphase.CreateEtcdServerCertAndKeyFiles,
|
||||
// certsphase.CreateEtcdPeerCertAndKeyFiles,
|
||||
// certsphase.CreateEtcdHealthcheckClientCertAndKeyFiles,
|
||||
// certsphase.CreateAPIServerEtcdClientCertAndKeyFiles,
|
||||
certsphase.CreateServiceAccountKeyAndPublicKeyFiles,
|
||||
certsphase.CreateFrontProxyCACertAndKeyFiles,
|
||||
certsphase.CreateFrontProxyClientCertAndKeyFiles,
|
||||
tree, err := certsphase.GetCertsWithoutEtcd().AsMap().CertTree()
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't get cert tree: %v", err)
|
||||
}
|
||||
for _, action := range certActions {
|
||||
err := action(oldcfg)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't initialize pre-upgrade certificate: %v", err)
|
||||
}
|
||||
|
||||
if err := tree.CreateTree(oldcfg); err != nil {
|
||||
t.Fatalf("couldn't get create cert tree: %v", err)
|
||||
}
|
||||
fmt.Printf("Wrote certs to %s\n", oldcfg.CertificatesDir)
|
||||
|
||||
t.Logf("Wrote certs to %s\n", oldcfg.CertificatesDir)
|
||||
|
||||
// Initialize the directory with v1.7 manifests; should then be upgraded to v1.8 using the method
|
||||
err = controlplanephase.CreateInitStaticPodManifestFiles(pathMgr.RealManifestDir(), oldcfg)
|
||||
|
|
|
@ -9,7 +9,10 @@ go_library(
|
|||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/test/certs",
|
||||
deps = ["//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
@ -22,13 +22,14 @@ import (
|
|||
"net"
|
||||
"testing"
|
||||
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
)
|
||||
|
||||
// SetupCertificateAuthorithy is a utility function for kubeadm testing that creates a
|
||||
// CertificateAuthorithy cert/key pair
|
||||
func SetupCertificateAuthorithy(t *testing.T) (*x509.Certificate, *rsa.PrivateKey) {
|
||||
caCert, caKey, err := pkiutil.NewCertificateAuthority()
|
||||
caCert, caKey, err := pkiutil.NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"})
|
||||
if err != nil {
|
||||
t.Fatalf("failure while generating CA certificate and key: %v", err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue