mirror of https://github.com/k3s-io/k3s
kubeadm create token using config file
parent
46dc023f93
commit
e247752ef9
|
@ -36,7 +36,6 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
|
|||
c.FuzzNoCustom(obj)
|
||||
obj.KubernetesVersion = "v10"
|
||||
obj.API.BindPort = 20
|
||||
obj.TokenTTL = &metav1.Duration{Duration: 1 * time.Hour}
|
||||
obj.API.AdvertiseAddress = "foo"
|
||||
obj.Networking.ServiceSubnet = "foo"
|
||||
obj.Networking.DNSDomain = "foo"
|
||||
|
@ -47,6 +46,9 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
|
|||
obj.Etcd.PeerCertSANs = []string{"foo"}
|
||||
obj.Token = "foo"
|
||||
obj.CRISocket = "foo"
|
||||
obj.TokenTTL = &metav1.Duration{Duration: 1 * time.Hour}
|
||||
obj.TokenUsages = []string{"foo"}
|
||||
obj.TokenGroups = []string{"foo"}
|
||||
obj.Etcd.Image = "foo"
|
||||
obj.Etcd.DataDir = "foo"
|
||||
obj.ImageRepository = "foo"
|
||||
|
|
|
@ -64,8 +64,12 @@ type MasterConfiguration struct {
|
|||
// Token is used for establishing bidirectional trust between nodes and masters.
|
||||
// Used for joining nodes in the cluster.
|
||||
Token string
|
||||
// TokenTTL is a ttl for Token. Defaults to 24h.
|
||||
// TokenTTL defines the ttl for Token. Defaults to 24h.
|
||||
TokenTTL *metav1.Duration
|
||||
// TokenUsages describes the ways in which this token can be used.
|
||||
TokenUsages []string
|
||||
// Extra groups that this token will authenticate as when used for authentication
|
||||
TokenGroups []string
|
||||
|
||||
// CRISocket is used to retrieve container runtime info.
|
||||
CRISocket string
|
||||
|
|
|
@ -116,6 +116,14 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
|
|||
obj.CRISocket = DefaultCRISocket
|
||||
}
|
||||
|
||||
if len(obj.TokenUsages) == 0 {
|
||||
obj.TokenUsages = constants.DefaultTokenUsages
|
||||
}
|
||||
|
||||
if len(obj.TokenGroups) == 0 {
|
||||
obj.TokenGroups = constants.DefaultTokenGroups
|
||||
}
|
||||
|
||||
if obj.ImageRepository == "" {
|
||||
obj.ImageRepository = DefaultImageRepository
|
||||
}
|
||||
|
|
|
@ -64,8 +64,12 @@ type MasterConfiguration struct {
|
|||
// Token is used for establishing bidirectional trust between nodes and masters.
|
||||
// Used for joining nodes in the cluster.
|
||||
Token string `json:"token"`
|
||||
// TokenTTL is a ttl for Token. Defaults to 24h.
|
||||
// TokenTTL defines the ttl for Token. Defaults to 24h.
|
||||
TokenTTL *metav1.Duration `json:"tokenTTL,omitempty"`
|
||||
// TokenUsages describes the ways in which this token can be used.
|
||||
TokenUsages []string `json:"tokenUsages,omitempty"`
|
||||
// Extra groups that this token will authenticate as when used for authentication
|
||||
TokenGroups []string `json:"tokenGroups,omitempty"`
|
||||
|
||||
// CRISocket is used to retrieve container runtime info.
|
||||
CRISocket string `json:"criSocket,omitempty"`
|
||||
|
|
|
@ -29,6 +29,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
|
@ -78,6 +80,8 @@ func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList
|
|||
allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificates-dir"))...)
|
||||
allErrs = append(allErrs, ValidateNodeName(c.NodeName, field.NewPath("node-name"))...)
|
||||
allErrs = append(allErrs, ValidateToken(c.Token, field.NewPath("token"))...)
|
||||
allErrs = append(allErrs, ValidateTokenUsages(c.TokenUsages, field.NewPath("tokenUsages"))...)
|
||||
allErrs = append(allErrs, ValidateTokenGroups(c.TokenUsages, c.TokenGroups, field.NewPath("tokenGroups"))...)
|
||||
allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("feature-gates"))...)
|
||||
allErrs = append(allErrs, ValidateAPIEndpoint(c, field.NewPath("api-endpoint"))...)
|
||||
allErrs = append(allErrs, ValidateProxy(c, field.NewPath("kube-proxy"))...)
|
||||
|
@ -230,6 +234,39 @@ func ValidateToken(t string, fldPath *field.Path) field.ErrorList {
|
|||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateTokenGroups validates token groups
|
||||
func ValidateTokenGroups(usages []string, groups []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
// adding groups only makes sense for authentication
|
||||
usagesSet := sets.NewString(usages...)
|
||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||
if len(groups) > 0 && !usagesSet.Has(usageAuthentication) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, groups, fmt.Sprintf("token groups cannot be specified unless --usages includes %q", usageAuthentication)))
|
||||
}
|
||||
|
||||
// validate any extra group names
|
||||
for _, group := range groups {
|
||||
if err := bootstraputil.ValidateBootstrapGroupName(group); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, groups, err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateTokenUsages validates token usages
|
||||
func ValidateTokenUsages(usages []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
// validate usages
|
||||
if err := bootstraputil.ValidateUsages(usages); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, usages, err.Error()))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCertSANs validates alternative names
|
||||
func ValidateCertSANs(altnames []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
|
|
@ -59,6 +59,51 @@ func TestValidateTokenDiscovery(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestValidateValidateTokenUsages(t *testing.T) {
|
||||
var tests = []struct {
|
||||
u []string
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{[]string{}, nil, true}, // supported (no usages)
|
||||
{[]string{"signing", "authentication"}, nil, true}, // supported
|
||||
{[]string{"something else"}, nil, false}, // usage not supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateTokenUsages(rt.u, rt.f)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateTokenUsages:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateTokenGroups(t *testing.T) {
|
||||
var tests = []struct {
|
||||
u []string
|
||||
g []string
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{[]string{"some usage"}, []string{"some group"}, nil, false}, // groups doesn't makes sense if usage authentication
|
||||
{[]string{"authentication"}, []string{"some group"}, nil, false}, // group not supported
|
||||
{[]string{"authentication"}, []string{"system:bootstrappers:anygroup"}, nil, true}, // supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateTokenGroups(rt.u, rt.g, rt.f)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateTokenGroups:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAuthorizationModes(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s []string
|
||||
|
|
|
@ -413,7 +413,7 @@ func (i *Init) Run(out io.Writer) error {
|
|||
|
||||
// Create the default node bootstrap token
|
||||
tokenDescription := "The default bootstrap token generated by 'kubeadm init'."
|
||||
if err := nodebootstraptokenphase.UpdateOrCreateToken(client, i.cfg.Token, false, i.cfg.TokenTTL.Duration, kubeadmconstants.DefaultTokenUsages, []string{kubeadmconstants.NodeBootstrapTokenAuthGroup}, tokenDescription); err != nil {
|
||||
if err := nodebootstraptokenphase.UpdateOrCreateToken(client, i.cfg.Token, false, i.cfg.TokenTTL.Duration, i.cfg.TokenUsages, i.cfg.TokenGroups, tokenDescription); err != nil {
|
||||
return fmt.Errorf("error updating or creating token: %v", err)
|
||||
}
|
||||
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
|
||||
|
|
|
@ -24,10 +24,8 @@ import (
|
|||
"github.com/spf13/pflag"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
|
@ -119,7 +117,6 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command {
|
|||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, description string
|
||||
var usages, extraGroups []string
|
||||
var skipTokenPrint bool
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -135,7 +132,7 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command {
|
|||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Creates the bootstap token
|
||||
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, skipTokenPrint)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Create the cluster-info ConfigMap or update if it already exists
|
||||
|
@ -161,7 +158,7 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command {
|
|||
}
|
||||
|
||||
// Adds flags to the command
|
||||
addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &usages, &extraGroups, &skipTokenPrint)
|
||||
addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &skipTokenPrint)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -178,7 +175,6 @@ func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command {
|
|||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, description string
|
||||
var usages, extraGroups []string
|
||||
var skipTokenPrint bool
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -192,13 +188,13 @@ func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command {
|
|||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, skipTokenPrint)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
// Adds flags to the command
|
||||
addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &usages, &extraGroups, &skipTokenPrint)
|
||||
addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &skipTokenPrint)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -281,7 +277,7 @@ func NewSubCmdNodeBootstrapTokenAutoApprove(kubeConfigFile *string) *cobra.Comma
|
|||
return cmd
|
||||
}
|
||||
|
||||
func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterConfiguration, cfgPath, description *string, usages, extraGroups *[]string, skipTokenPrint *bool) {
|
||||
func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterConfiguration, cfgPath, description *string, skipTokenPrint *bool) {
|
||||
flagSet.StringVar(
|
||||
cfgPath, "config", *cfgPath,
|
||||
"Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)",
|
||||
|
@ -291,15 +287,15 @@ func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterCon
|
|||
"The token to use for establishing bidirectional trust between nodes and masters",
|
||||
)
|
||||
flagSet.DurationVar(
|
||||
&cfg.TokenTTL.Duration, "ttl", kubeadmconstants.DefaultTokenDuration,
|
||||
&cfg.TokenTTL.Duration, "ttl", cfg.TokenTTL.Duration,
|
||||
"The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire",
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
usages, "usages", kubeadmconstants.DefaultTokenUsages,
|
||||
&cfg.TokenUsages, "usages", cfg.TokenUsages,
|
||||
fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s]", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")),
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
extraGroups, "groups", []string{kubeadmconstants.NodeBootstrapTokenAuthGroup},
|
||||
&cfg.TokenGroups, "groups", cfg.TokenGroups,
|
||||
fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern),
|
||||
)
|
||||
flagSet.StringVar(
|
||||
|
@ -312,27 +308,16 @@ func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterCon
|
|||
)
|
||||
}
|
||||
|
||||
func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, usages, extraGroups []string, skipTokenPrint bool) error {
|
||||
// adding groups only makes sense for authentication
|
||||
usagesSet := sets.NewString(usages...)
|
||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||
if len(extraGroups) > 0 && !usagesSet.Has(usageAuthentication) {
|
||||
return fmt.Errorf("--groups cannot be specified unless --usages includes %q", usageAuthentication)
|
||||
}
|
||||
|
||||
// validate any extra group names
|
||||
for _, group := range extraGroups {
|
||||
if err := bootstraputil.ValidateBootstrapGroupName(group); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, skipTokenPrint bool) error {
|
||||
|
||||
// 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
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Creates or updates the token
|
||||
if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, usages, extraGroups, description); err != nil {
|
||||
if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, internalcfg.TokenUsages, internalcfg.TokenGroups, description); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -32,18 +32,20 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/util/duration"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"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"
|
||||
tokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
|
@ -86,10 +88,16 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
|||
tokenCmd.PersistentFlags().BoolVar(&dryRun,
|
||||
"dry-run", dryRun, "Whether to enable dry-run mode or not")
|
||||
|
||||
var usages []string
|
||||
var extraGroups []string
|
||||
var tokenDuration time.Duration
|
||||
var description string
|
||||
cfg := &kubeadmapiext.MasterConfiguration{
|
||||
// KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid
|
||||
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
KubernetesVersion: "v1.9.0",
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, description string
|
||||
var printJoinCommand bool
|
||||
createCmd := &cobra.Command{
|
||||
Use: "create [token]",
|
||||
|
@ -104,23 +112,28 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
|||
If no [token] is given, kubeadm will generate a random token instead.
|
||||
`),
|
||||
Run: func(tokenCmd *cobra.Command, args []string) {
|
||||
token := ""
|
||||
if len(args) != 0 {
|
||||
token = args[0]
|
||||
cfg.Token = args[0]
|
||||
}
|
||||
|
||||
err := validation.ValidateMixedArguments(tokenCmd.Flags())
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
client, err := getClientset(kubeConfigFile, dryRun)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunCreateToken(out, client, token, tokenDuration, usages, extraGroups, description, printJoinCommand, kubeConfigFile)
|
||||
err = RunCreateToken(out, client, cfgPath, cfg, description, printJoinCommand, kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
createCmd.Flags().DurationVar(&tokenDuration,
|
||||
"ttl", kubeadmconstants.DefaultTokenDuration, "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire.")
|
||||
createCmd.Flags().StringSliceVar(&usages,
|
||||
"usages", kubeadmconstants.DefaultTokenUsages, fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s].", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")))
|
||||
createCmd.Flags().StringSliceVar(&extraGroups,
|
||||
"groups", []string{kubeadmconstants.NodeBootstrapTokenAuthGroup},
|
||||
createCmd.Flags().StringVar(&cfgPath,
|
||||
"config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)")
|
||||
createCmd.Flags().DurationVar(&cfg.TokenTTL.Duration,
|
||||
"ttl", cfg.TokenTTL.Duration, "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire.")
|
||||
createCmd.Flags().StringSliceVar(&cfg.TokenUsages,
|
||||
"usages", cfg.TokenUsages, fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s].", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")))
|
||||
createCmd.Flags().StringSliceVar(&cfg.TokenGroups,
|
||||
"groups", cfg.TokenGroups,
|
||||
fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q.", bootstrapapi.BootstrapGroupPattern))
|
||||
createCmd.Flags().StringVar(&description,
|
||||
"description", "", "A human friendly description of how this token is used.")
|
||||
|
@ -196,40 +209,14 @@ func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
|
|||
}
|
||||
|
||||
// RunCreateToken generates a new bootstrap token and stores it as a secret on the server.
|
||||
func RunCreateToken(out io.Writer, client clientset.Interface, token string, tokenDuration time.Duration, usages []string, extraGroups []string, description string, printJoinCommand bool, kubeConfigFile string) error {
|
||||
if len(token) == 0 {
|
||||
var err error
|
||||
token, err = tokenutil.GenerateToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, _, err := tokenutil.ParseToken(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// adding groups only makes sense for authentication
|
||||
usagesSet := sets.NewString(usages...)
|
||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||
if len(extraGroups) > 0 && !usagesSet.Has(usageAuthentication) {
|
||||
return fmt.Errorf("--groups cannot be specified unless --usages includes %q", usageAuthentication)
|
||||
}
|
||||
|
||||
// validate any extra group names
|
||||
for _, group := range extraGroups {
|
||||
if err := bootstraputil.ValidateBootstrapGroupName(group); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// validate usages
|
||||
if err := bootstraputil.ValidateUsages(usages); err != nil {
|
||||
func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, printJoinCommand bool, kubeConfigFile string) error {
|
||||
// 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
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := tokenphase.CreateNewToken(client, token, tokenDuration, usages, extraGroups, description)
|
||||
err = tokenphase.CreateNewToken(client, internalcfg.Token, internalcfg.TokenTTL.Duration, internalcfg.TokenUsages, internalcfg.TokenGroups, description)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -237,13 +224,13 @@ func RunCreateToken(out io.Writer, client clientset.Interface, token string, tok
|
|||
// if --print-join-command was specified, print the full `kubeadm join` command
|
||||
// otherwise, just print the token
|
||||
if printJoinCommand {
|
||||
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, token, false)
|
||||
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.Token, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get join command: %v", err)
|
||||
}
|
||||
fmt.Fprintln(out, joinCommand)
|
||||
} else {
|
||||
fmt.Fprintln(out, token)
|
||||
fmt.Fprintln(out, internalcfg.Token)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -23,9 +23,11 @@ import (
|
|||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -123,7 +125,18 @@ func TestRunCreateToken(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
err := RunCreateToken(&buf, fakeClient, tc.token, 0, tc.usages, tc.extraGroups, "", false, "")
|
||||
|
||||
cfg := &kubeadmapiext.MasterConfiguration{
|
||||
// KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid
|
||||
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
KubernetesVersion: "v1.9.0",
|
||||
Token: tc.token,
|
||||
TokenTTL: &metav1.Duration{Duration: 0},
|
||||
TokenUsages: tc.usages,
|
||||
TokenGroups: tc.extraGroups,
|
||||
}
|
||||
|
||||
err := RunCreateToken(&buf, fakeClient, "", cfg, "", false, "")
|
||||
if (err != nil) != tc.expectedError {
|
||||
t.Errorf("Test case %s: RunCreateToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil))
|
||||
}
|
||||
|
|
|
@ -266,6 +266,9 @@ var (
|
|||
// DefaultTokenUsages specifies the default functions a token will get
|
||||
DefaultTokenUsages = bootstrapapi.KnownTokenUsages
|
||||
|
||||
// DefaultTokenGroups specifies the default groups that this token will authenticate as when used for authentication
|
||||
DefaultTokenGroups = []string{NodeBootstrapTokenAuthGroup}
|
||||
|
||||
// MasterComponents defines the master component names
|
||||
MasterComponents = []string{KubeAPIServer, KubeControllerManager, KubeScheduler}
|
||||
|
||||
|
|
Loading…
Reference in New Issue