Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubeadm token create using config file #60059

Merged
merged 2 commits into from
Feb 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down
6 changes: 5 additions & 1 deletion cmd/kubeadm/app/apis/kubeadm/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 5 additions & 1 deletion cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cmd/kubeadm/app/apis/kubeadm/validation/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
],
)

Expand Down
37 changes: 37 additions & 0 deletions cmd/kubeadm/app/apis/kubeadm/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"))...)
Expand Down Expand Up @@ -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{}
Expand Down
45 changes: 45 additions & 0 deletions cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion cmd/kubeadm/app/cmd/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
"//vendor/k8s.io/client-go/util/cert:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
Expand All @@ -86,10 +85,12 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
"//vendor/k8s.io/client-go/testing:go_default_library",
Expand Down
2 changes: 1 addition & 1 deletion cmd/kubeadm/app/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion cmd/kubeadm/app/cmd/phases/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
)
Expand Down
41 changes: 13 additions & 28 deletions cmd/kubeadm/app/cmd/phases/bootstraptoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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{
Expand All @@ -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
Expand All @@ -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
}
Expand All @@ -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{
Expand All @@ -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
}
Expand Down Expand Up @@ -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)",
Expand All @@ -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(
Expand All @@ -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
}

Expand Down