Merge pull request #100907 from SataQiu/kubeadm-20210408

kubeadm: add --validity-period flag for 'kubeadm kubeconfig user' command
This commit is contained in:
Kubernetes Prow Robot 2021-04-12 23:40:49 -07:00 committed by GitHub
commit 61641a0640
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 20 deletions

View File

@ -18,12 +18,15 @@ package alpha
import (
"io"
"time"
"github.com/spf13/cobra"
"k8s.io/klog/v2"
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
)
@ -64,6 +67,7 @@ func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
var (
token, clientName, cfgPath string
organizations []string
validityPeriod time.Duration
)
// Creates the UX Command
@ -79,13 +83,20 @@ func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
return err
}
if validityPeriod > kubeadmconstants.CertificateValidity {
klog.Warningf("WARNING: the specified certificate validity period %v is longer than the default duration %v, this may increase security risks.",
validityPeriod, kubeadmconstants.CertificateValidity)
}
notAfter := time.Now().Add(validityPeriod).UTC()
// if the kubeconfig file for an additional user has to use a token, use it
if token != "" {
return kubeconfigphase.WriteKubeConfigWithToken(out, internalCfg, clientName, token)
return kubeconfigphase.WriteKubeConfigWithToken(out, internalCfg, clientName, token, &notAfter)
}
// Otherwise, write a kubeconfig file with a generate client cert
return kubeconfigphase.WriteKubeConfigWithClientCert(out, internalCfg, clientName, organizations)
return kubeconfigphase.WriteKubeConfigWithClientCert(out, internalCfg, clientName, organizations, &notAfter)
},
Args: cobra.NoArgs,
}
@ -96,6 +107,7 @@ func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&token, options.TokenStr, token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
cmd.Flags().DurationVar(&validityPeriod, "validity-period", kubeadmconstants.CertificateValidity, "The validity period of the client certificate. It is an offset from the current time.")
cmd.MarkFlagRequired(options.CfgPath)
cmd.MarkFlagRequired("client-name")

View File

@ -24,6 +24,7 @@ import (
"io"
"os"
"path/filepath"
"time"
"github.com/pkg/errors"
@ -120,7 +121,7 @@ func createKubeConfigFiles(outDir string, cfg *kubeadmapi.InitConfiguration, kub
}
// builds the KubeConfig object
config, err := buildKubeConfigFromSpec(spec, cfg.ClusterName)
config, err := buildKubeConfigFromSpec(spec, cfg.ClusterName, nil)
if err != nil {
return err
}
@ -156,7 +157,7 @@ func getKubeConfigSpecs(cfg *kubeadmapi.InitConfiguration) (map[string]*kubeConf
}
// buildKubeConfigFromSpec creates a kubeconfig object for the given kubeConfigSpec
func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string) (*clientcmdapi.Config, error) {
func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string, notAfter *time.Time) (*clientcmdapi.Config, error) {
// If this kubeconfig should use token
if spec.TokenAuth != nil {
@ -171,7 +172,7 @@ func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string) (*clientc
}
// otherwise, create a client certs
clientCertConfig := newClientCertConfigFromKubeConfigSpec(spec)
clientCertConfig := newClientCertConfigFromKubeConfigSpec(spec, notAfter)
clientCert, clientKey, err := pkiutil.NewCertAndKey(spec.CACert, spec.ClientCertAuth.CAKey, &clientCertConfig)
if err != nil {
@ -193,13 +194,14 @@ func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string) (*clientc
), nil
}
func newClientCertConfigFromKubeConfigSpec(spec *kubeConfigSpec) pkiutil.CertConfig {
func newClientCertConfigFromKubeConfigSpec(spec *kubeConfigSpec, notAfter *time.Time) pkiutil.CertConfig {
return pkiutil.CertConfig{
Config: certutil.Config{
CommonName: spec.ClientName,
Organization: spec.ClientCertAuth.Organizations,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
NotAfter: notAfter,
}
}
@ -279,7 +281,7 @@ func createKubeConfigFileIfNotExists(outDir, filename string, config *clientcmda
}
// WriteKubeConfigWithClientCert writes a kubeconfig file - with a client certificate as authentication info - to the given writer.
func WriteKubeConfigWithClientCert(out io.Writer, cfg *kubeadmapi.InitConfiguration, clientName string, organizations []string) error {
func WriteKubeConfigWithClientCert(out io.Writer, cfg *kubeadmapi.InitConfiguration, clientName string, organizations []string, notAfter *time.Time) error {
// creates the KubeConfigSpecs, actualized for the current InitConfiguration
caCert, caKey, err := pkiutil.TryLoadCertAndKeyFromDisk(cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
@ -304,11 +306,11 @@ func WriteKubeConfigWithClientCert(out io.Writer, cfg *kubeadmapi.InitConfigurat
},
}
return writeKubeConfigFromSpec(out, spec, cfg.ClusterName)
return writeKubeConfigFromSpec(out, spec, cfg.ClusterName, notAfter)
}
// WriteKubeConfigWithToken writes a kubeconfig file - with a token as client authentication info - to the given writer.
func WriteKubeConfigWithToken(out io.Writer, cfg *kubeadmapi.InitConfiguration, clientName, token string) error {
func WriteKubeConfigWithToken(out io.Writer, cfg *kubeadmapi.InitConfiguration, clientName, token string, notAfter *time.Time) error {
// creates the KubeConfigSpecs, actualized for the current InitConfiguration
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
@ -332,14 +334,14 @@ func WriteKubeConfigWithToken(out io.Writer, cfg *kubeadmapi.InitConfiguration,
},
}
return writeKubeConfigFromSpec(out, spec, cfg.ClusterName)
return writeKubeConfigFromSpec(out, spec, cfg.ClusterName, notAfter)
}
// writeKubeConfigFromSpec creates a kubeconfig object from a kubeConfigSpec and writes it to the given writer.
func writeKubeConfigFromSpec(out io.Writer, spec *kubeConfigSpec, clustername string) error {
func writeKubeConfigFromSpec(out io.Writer, spec *kubeConfigSpec, clustername string, notAfter *time.Time) error {
// builds the KubeConfig object
config, err := buildKubeConfigFromSpec(spec, clustername)
config, err := buildKubeConfigFromSpec(spec, clustername, notAfter)
if err != nil {
return err
}
@ -465,7 +467,7 @@ func createKubeConfigAndCSR(kubeConfigDir string, kubeadmConfig *kubeadmapi.Init
return errors.Errorf("%s: csr: %s", errExist, kubeConfigPath)
}
clientCertConfig := newClientCertConfigFromKubeConfigSpec(spec)
clientCertConfig := newClientCertConfigFromKubeConfigSpec(spec, nil)
clientKey, err := pkiutil.NewPrivateKey(clientCertConfig.PublicKeyAlgorithm)
if err != nil {

View File

@ -374,13 +374,13 @@ func TestWriteKubeConfigFailsIfCADoesntExists(t *testing.T) {
{
name: "WriteKubeConfigWithClientCert",
writeKubeConfigFunction: func(out io.Writer) error {
return WriteKubeConfigWithClientCert(out, cfg, "myUser", []string{"myOrg"})
return WriteKubeConfigWithClientCert(out, cfg, "myUser", []string{"myOrg"}, nil)
},
},
{
name: "WriteKubeConfigWithToken",
writeKubeConfigFunction: func(out io.Writer) error {
return WriteKubeConfigWithToken(out, cfg, "myUser", "12345")
return WriteKubeConfigWithToken(out, cfg, "myUser", "12345", nil)
},
},
}
@ -428,14 +428,14 @@ func TestWriteKubeConfig(t *testing.T) {
{
name: "WriteKubeConfigWithClientCert",
writeKubeConfigFunction: func(out io.Writer) error {
return WriteKubeConfigWithClientCert(out, cfg, "myUser", []string{"myOrg"})
return WriteKubeConfigWithClientCert(out, cfg, "myUser", []string{"myOrg"}, nil)
},
withClientCert: true,
},
{
name: "WriteKubeConfigWithToken",
writeKubeConfigFunction: func(out io.Writer) error {
return WriteKubeConfigWithToken(out, cfg, "myUser", "12345")
return WriteKubeConfigWithToken(out, cfg, "myUser", "12345", nil)
},
withToken: true,
},
@ -664,7 +664,7 @@ func setupdKubeConfigWithClientAuth(t *testing.T, caCert *x509.Certificate, caKe
},
}
config, err := buildKubeConfigFromSpec(spec, clustername)
config, err := buildKubeConfigFromSpec(spec, clustername, nil)
if err != nil {
t.Fatal("buildKubeConfigFromSpec failed!")
}
@ -683,7 +683,7 @@ func setupdKubeConfigWithTokenAuth(t *testing.T, caCert *x509.Certificate, APISe
},
}
config, err := buildKubeConfigFromSpec(spec, clustername)
config, err := buildKubeConfigFromSpec(spec, clustername, nil)
if err != nil {
t.Fatal("buildKubeConfigFromSpec failed!")
}

View File

@ -62,6 +62,7 @@ const (
// CertConfig is a wrapper around certutil.Config extending it with PublicKeyAlgorithm.
type CertConfig struct {
certutil.Config
NotAfter *time.Time
PublicKeyAlgorithm x509.PublicKeyAlgorithm
}
@ -647,6 +648,11 @@ func NewSignedCert(cfg *CertConfig, key crypto.Signer, caCert *x509.Certificate,
RemoveDuplicateAltNames(&cfg.AltNames)
notAfter := time.Now().Add(kubeadmconstants.CertificateValidity).UTC()
if cfg.NotAfter != nil {
notAfter = *cfg.NotAfter
}
certTmpl := x509.Certificate{
Subject: pkix.Name{
CommonName: cfg.CommonName,
@ -656,7 +662,7 @@ func NewSignedCert(cfg *CertConfig, key crypto.Signer, caCert *x509.Certificate,
IPAddresses: cfg.AltNames.IPs,
SerialNumber: serial,
NotBefore: caCert.NotBefore,
NotAfter: time.Now().Add(kubeadmconstants.CertificateValidity).UTC(),
NotAfter: notAfter,
KeyUsage: keyUsage,
ExtKeyUsage: cfg.Usages,
BasicConstraintsValid: true,