From b35fd0f035dc49714832dc22789236e99110ee16 Mon Sep 17 00:00:00 2001 From: Yu Liao Date: Mon, 13 Aug 2018 17:22:57 -0700 Subject: [PATCH] Moved staging/src/k8s.io/client-go/tools/bootstrap to staging/src/k8s.io/cluster-bootstrap Kubernetes-commit: fc21115c3fb14e3eec4d57c1b813111fb2efd5c3 --- tools/bootstrap/token/OWNERS | 5 - tools/bootstrap/token/api/doc.go | 20 -- tools/bootstrap/token/api/types.go | 112 ----------- tools/bootstrap/token/util/helpers.go | 133 ------------- tools/bootstrap/token/util/helpers_test.go | 213 --------------------- 5 files changed, 483 deletions(-) delete mode 100644 tools/bootstrap/token/OWNERS delete mode 100644 tools/bootstrap/token/api/doc.go delete mode 100644 tools/bootstrap/token/api/types.go delete mode 100644 tools/bootstrap/token/util/helpers.go delete mode 100644 tools/bootstrap/token/util/helpers_test.go diff --git a/tools/bootstrap/token/OWNERS b/tools/bootstrap/token/OWNERS deleted file mode 100644 index 8a2f5b59..00000000 --- a/tools/bootstrap/token/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -approvers: -- jbeda -- luxas -reviewers: -- mattmoyer diff --git a/tools/bootstrap/token/api/doc.go b/tools/bootstrap/token/api/doc.go deleted file mode 100644 index 249e0a05..00000000 --- a/tools/bootstrap/token/api/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package api (k8s.io/client-go/tools/bootstrap/token/api) contains constants and types needed for -// bootstrap tokens as maintained by the BootstrapSigner and TokenCleaner -// controllers (in k8s.io/kubernetes/pkg/controller/bootstrap) -package api // import "k8s.io/client-go/tools/bootstrap/token/api" diff --git a/tools/bootstrap/token/api/types.go b/tools/bootstrap/token/api/types.go deleted file mode 100644 index 3bea78b1..00000000 --- a/tools/bootstrap/token/api/types.go +++ /dev/null @@ -1,112 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package api - -import ( - "k8s.io/api/core/v1" -) - -const ( - // BootstrapTokenSecretPrefix is the prefix for bootstrap token names. - // Bootstrap tokens secrets must be named in the form - // `bootstrap-token-`. This is the prefix to be used before the - // token ID. - BootstrapTokenSecretPrefix = "bootstrap-token-" - - // SecretTypeBootstrapToken is used during the automated bootstrap process (first - // implemented by kubeadm). It stores tokens that are used to sign well known - // ConfigMaps. They may also eventually be used for authentication. - SecretTypeBootstrapToken v1.SecretType = "bootstrap.kubernetes.io/token" - - // BootstrapTokenIDKey is the id of this token. This can be transmitted in the - // clear and encoded in the name of the secret. It must be a random 6 character - // string that matches the regexp `^([a-z0-9]{6})$`. Required. - BootstrapTokenIDKey = "token-id" - - // BootstrapTokenSecretKey is the actual secret. It must be a random 16 character - // string that matches the regexp `^([a-z0-9]{16})$`. Required. - BootstrapTokenSecretKey = "token-secret" - - // BootstrapTokenExpirationKey is when this token should be expired and no - // longer used. A controller will delete this resource after this time. This - // is an absolute UTC time using RFC3339. If this cannot be parsed, the token - // should be considered invalid. Optional. - BootstrapTokenExpirationKey = "expiration" - - // BootstrapTokenDescriptionKey is a description in human-readable format that - // describes what the bootstrap token is used for. Optional. - BootstrapTokenDescriptionKey = "description" - - // BootstrapTokenExtraGroupsKey is a comma-separated list of group names. - // The bootstrap token will authenticate as these groups in addition to the - // "system:bootstrappers" group. - BootstrapTokenExtraGroupsKey = "auth-extra-groups" - - // BootstrapTokenUsagePrefix is the prefix for the other usage constants that specifies different - // functions of a bootstrap token - BootstrapTokenUsagePrefix = "usage-bootstrap-" - - // BootstrapTokenUsageSigningKey signals that this token should be used to - // sign configs as part of the bootstrap process. Value must be "true". Any - // other value is assumed to be false. Optional. - BootstrapTokenUsageSigningKey = "usage-bootstrap-signing" - - // BootstrapTokenUsageAuthentication signals that this token should be used - // as a bearer token to authenticate against the Kubernetes API. The bearer - // token takes the form "." and authenticates as the - // user "system:bootstrap:" in the "system:bootstrappers" group - // as well as any groups specified using BootstrapTokenExtraGroupsKey. - // Value must be "true". Any other value is assumed to be false. Optional. - BootstrapTokenUsageAuthentication = "usage-bootstrap-authentication" - - // ConfigMapClusterInfo defines the name for the ConfigMap where the information how to connect and trust the cluster exist - ConfigMapClusterInfo = "cluster-info" - - // KubeConfigKey defines at which key in the Data object of the ConfigMap the KubeConfig object is stored - KubeConfigKey = "kubeconfig" - - // JWSSignatureKeyPrefix defines what key prefix the JWS-signed tokens have - JWSSignatureKeyPrefix = "jws-kubeconfig-" - - // BootstrapUserPrefix is the username prefix bootstrapping bearer tokens - // authenticate as. The full username given is "system:bootstrap:". - BootstrapUserPrefix = "system:bootstrap:" - - // BootstrapDefaultGroup is the default group for bootstrapping bearer - // tokens (in addition to any groups from BootstrapTokenExtraGroupsKey). - BootstrapDefaultGroup = "system:bootstrappers" - - // BootstrapGroupPattern is the valid regex pattern that all groups - // assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match. - // See also util.ValidateBootstrapGroupName() - BootstrapGroupPattern = `\Asystem:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]\z` - - // BootstrapTokenPattern defines the {id}.{secret} regular expression pattern - BootstrapTokenPattern = `\A([a-z0-9]{6})\.([a-z0-9]{16})\z` - - // BootstrapTokenIDPattern defines token's id regular expression pattern - BootstrapTokenIDPattern = `\A([a-z0-9]{6})\z` - - // BootstrapTokenIDBytes defines the number of bytes used for the Bootstrap Token's ID field - BootstrapTokenIDBytes = 6 - - // BootstrapTokenSecretBytes defines the number of bytes used the Bootstrap Token's Secret field - BootstrapTokenSecretBytes = 16 -) - -// KnownTokenUsages specifies the known functions a token will get. -var KnownTokenUsages = []string{"signing", "authentication"} diff --git a/tools/bootstrap/token/util/helpers.go b/tools/bootstrap/token/util/helpers.go deleted file mode 100644 index bb1fbeb6..00000000 --- a/tools/bootstrap/token/util/helpers.go +++ /dev/null @@ -1,133 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "bufio" - "crypto/rand" - "fmt" - "regexp" - "strings" - - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/client-go/tools/bootstrap/token/api" -) - -// validBootstrapTokenChars defines the characters a bootstrap token can consist of -const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz" - -var ( - // BootstrapTokenRegexp is a compiled regular expression of TokenRegexpString - BootstrapTokenRegexp = regexp.MustCompile(api.BootstrapTokenPattern) - // BootstrapTokenIDRegexp is a compiled regular expression of TokenIDRegexpString - BootstrapTokenIDRegexp = regexp.MustCompile(api.BootstrapTokenIDPattern) - // BootstrapGroupRegexp is a compiled regular expression of BootstrapGroupPattern - BootstrapGroupRegexp = regexp.MustCompile(api.BootstrapGroupPattern) -) - -// GenerateBootstrapToken generates a new, random Bootstrap Token. -func GenerateBootstrapToken() (string, error) { - tokenID, err := randBytes(api.BootstrapTokenIDBytes) - if err != nil { - return "", err - } - - tokenSecret, err := randBytes(api.BootstrapTokenSecretBytes) - if err != nil { - return "", err - } - - return TokenFromIDAndSecret(tokenID, tokenSecret), nil -} - -// randBytes returns a random string consisting of the characters in -// validBootstrapTokenChars, with the length customized by the parameter -func randBytes(length int) (string, error) { - // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide - // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we - // read that are >= 252 so the bytes we evenly divide the character set. - const maxByteValue = 252 - - var ( - b byte - err error - token = make([]byte, length) - ) - - reader := bufio.NewReaderSize(rand.Reader, length*2) - for i := range token { - for { - if b, err = reader.ReadByte(); err != nil { - return "", err - } - if b < maxByteValue { - break - } - } - - token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)] - } - - return string(token), nil -} - -// TokenFromIDAndSecret returns the full token which is of the form "{id}.{secret}" -func TokenFromIDAndSecret(id, secret string) string { - return fmt.Sprintf("%s.%s", id, secret) -} - -// IsValidBootstrapToken returns whether the given string is valid as a Bootstrap Token and -// in other words satisfies the BootstrapTokenRegexp -func IsValidBootstrapToken(token string) bool { - return BootstrapTokenRegexp.MatchString(token) -} - -// IsValidBootstrapTokenID returns whether the given string is valid as a Bootstrap Token ID and -// in other words satisfies the BootstrapTokenIDRegexp -func IsValidBootstrapTokenID(tokenID string) bool { - return BootstrapTokenIDRegexp.MatchString(tokenID) -} - -// BootstrapTokenSecretName returns the expected name for the Secret storing the -// Bootstrap Token in the Kubernetes API. -func BootstrapTokenSecretName(tokenID string) string { - return fmt.Sprintf("%s%s", api.BootstrapTokenSecretPrefix, tokenID) -} - -// ValidateBootstrapGroupName checks if the provided group name is a valid -// bootstrap group name. Returns nil if valid or a validation error if invalid. -func ValidateBootstrapGroupName(name string) error { - if BootstrapGroupRegexp.Match([]byte(name)) { - return nil - } - return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, api.BootstrapGroupPattern) -} - -// ValidateUsages validates that the passed in string are valid usage strings for bootstrap tokens. -func ValidateUsages(usages []string) error { - validUsages := sets.NewString(api.KnownTokenUsages...) - invalidUsages := sets.NewString() - for _, usage := range usages { - if !validUsages.Has(usage) { - invalidUsages.Insert(usage) - } - } - if len(invalidUsages) > 0 { - return fmt.Errorf("invalid bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ",")) - } - return nil -} diff --git a/tools/bootstrap/token/util/helpers_test.go b/tools/bootstrap/token/util/helpers_test.go deleted file mode 100644 index a1fe6092..00000000 --- a/tools/bootstrap/token/util/helpers_test.go +++ /dev/null @@ -1,213 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "strings" - "testing" -) - -func TestGenerateBootstrapToken(t *testing.T) { - token, err := GenerateBootstrapToken() - if err != nil { - t.Fatalf("GenerateBootstrapToken returned an unexpected error: %+v", err) - } - if !IsValidBootstrapToken(token) { - t.Errorf("GenerateBootstrapToken didn't generate a valid token: %q", token) - } -} - -func TestRandBytes(t *testing.T) { - var randTest = []int{ - 0, - 1, - 2, - 3, - 100, - } - - for _, rt := range randTest { - actual, err := randBytes(rt) - if err != nil { - t.Errorf("failed randBytes: %v", err) - } - if len(actual) != rt { - t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual)) - } - } -} - -func TestTokenFromIDAndSecret(t *testing.T) { - var tests = []struct { - id string - secret string - expected string - }{ - {"foo", "bar", "foo.bar"}, // should use default - {"abcdef", "abcdef0123456789", "abcdef.abcdef0123456789"}, - {"h", "b", "h.b"}, - } - for _, rt := range tests { - actual := TokenFromIDAndSecret(rt.id, rt.secret) - if actual != rt.expected { - t.Errorf( - "failed TokenFromIDAndSecret:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } - } -} - -func TestIsValidBootstrapToken(t *testing.T) { - var tests = []struct { - token string - expected bool - }{ - {token: "", expected: false}, - {token: ".", expected: false}, - {token: "1234567890123456789012", expected: false}, // invalid parcel size - {token: "12345.1234567890123456", expected: false}, // invalid parcel size - {token: ".1234567890123456", expected: false}, // invalid parcel size - {token: "123456.", expected: false}, // invalid parcel size - {token: "123456:1234567890.123456", expected: false}, // invalid separation - {token: "abcdef:1234567890123456", expected: false}, // invalid separation - {token: "Abcdef.1234567890123456", expected: false}, // invalid token id - {token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret - {token: "123456.AABBCCD-EEFFGGHH", expected: false}, // invalid character - {token: "abc*ef.1234567890123456", expected: false}, // invalid character - {token: "abcdef.1234567890123456", expected: true}, - {token: "123456.aabbccddeeffgghh", expected: true}, - {token: "ABCDEF.abcdef0123456789", expected: false}, - {token: "abcdef.abcdef0123456789", expected: true}, - {token: "123456.1234560123456789", expected: true}, - } - for _, rt := range tests { - actual := IsValidBootstrapToken(rt.token) - if actual != rt.expected { - t.Errorf( - "failed IsValidBootstrapToken for the token %q\n\texpected: %t\n\t actual: %t", - rt.token, - rt.expected, - actual, - ) - } - } -} - -func TestIsValidBootstrapTokenID(t *testing.T) { - var tests = []struct { - tokenID string - expected bool - }{ - {tokenID: "", expected: false}, - {tokenID: "1234567890123456789012", expected: false}, - {tokenID: "12345", expected: false}, - {tokenID: "Abcdef", expected: false}, - {tokenID: "ABCDEF", expected: false}, - {tokenID: "abcdef.", expected: false}, - {tokenID: "abcdef", expected: true}, - {tokenID: "123456", expected: true}, - } - for _, rt := range tests { - actual := IsValidBootstrapTokenID(rt.tokenID) - if actual != rt.expected { - t.Errorf( - "failed IsValidBootstrapTokenID for the token %q\n\texpected: %t\n\t actual: %t", - rt.tokenID, - rt.expected, - actual, - ) - } - } -} - -func TestBootstrapTokenSecretName(t *testing.T) { - var tests = []struct { - tokenID string - expected string - }{ - {"foo", "bootstrap-token-foo"}, - {"bar", "bootstrap-token-bar"}, - {"", "bootstrap-token-"}, - {"abcdef", "bootstrap-token-abcdef"}, - } - for _, rt := range tests { - actual := BootstrapTokenSecretName(rt.tokenID) - if actual != rt.expected { - t.Errorf( - "failed BootstrapTokenSecretName:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } - } -} - -func TestValidateBootstrapGroupName(t *testing.T) { - tests := []struct { - name string - input string - valid bool - }{ - {"valid", "system:bootstrappers:foo", true}, - {"valid nested", "system:bootstrappers:foo:bar:baz", true}, - {"valid with dashes and number", "system:bootstrappers:foo-bar-42", true}, - {"invalid uppercase", "system:bootstrappers:Foo", false}, - {"missing prefix", "foo", false}, - {"prefix with no body", "system:bootstrappers:", false}, - {"invalid spaces", "system:bootstrappers: ", false}, - {"invalid asterisk", "system:bootstrappers:*", false}, - {"trailing colon", "system:bootstrappers:foo:", false}, - {"trailing dash", "system:bootstrappers:foo-", false}, - {"script tags", "system:bootstrappers:", false}, - {"too long", "system:bootstrappers:" + strings.Repeat("x", 300), false}, - } - for _, test := range tests { - err := ValidateBootstrapGroupName(test.input) - if err != nil && test.valid { - t.Errorf("test %q: ValidateBootstrapGroupName(%q) returned unexpected error: %v", test.name, test.input, err) - } - if err == nil && !test.valid { - t.Errorf("test %q: ValidateBootstrapGroupName(%q) was supposed to return an error but didn't", test.name, test.input) - } - } -} - -func TestValidateUsages(t *testing.T) { - tests := []struct { - name string - input []string - valid bool - }{ - {"valid of signing", []string{"signing"}, true}, - {"valid of authentication", []string{"authentication"}, true}, - {"all valid", []string{"authentication", "signing"}, true}, - {"single invalid", []string{"authentication", "foo"}, false}, - {"all invalid", []string{"foo", "bar"}, false}, - } - - for _, test := range tests { - err := ValidateUsages(test.input) - if err != nil && test.valid { - t.Errorf("test %q: ValidateUsages(%v) returned unexpected error: %v", test.name, test.input, err) - } - if err == nil && !test.valid { - t.Errorf("test %q: ValidateUsages(%v) was supposed to return an error but didn't", test.name, test.input) - } - } -}