mirror of
https://github.com/kubernetes/client-go.git
synced 2025-07-18 17:21:23 +00:00
Merge pull request #64408 from luxas/kubeadm_refactor_bt
Automatic merge from submit-queue (batch tested with PRs 64057, 63223, 64346, 64562, 64408). 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>. kubeadm: Refactor the Bootstrap Tokens usage in the API types **What this PR does / why we need it**: This PR: - Moves some common, generic Bootstrap Token helpers and constants from `k8s.io/kubernetes/cmd/kubeadm/app/util/token` to `k8s.io/client-go/tools/bootstrap/token/` - Breaks out the top-level Bootstrap Token fields to a dedicated `BootstrapToken` struct with helper functions. - Instead of representing the Bootstrap Token as a plain `string`, there is now a wrapper struct `BootstrapTokenString` that can marshal/unmarshal correctly and supports validation on create, and splitting up the full token in the ID/Secret parts automatically. - Makes kubeadm support multiple Bootstrap Tokens automatically by supporting a slice of `BootstrapToken` in the `MasterConfiguration` API object - Consolidates the place for kubeadm to create token-related flags in an `options` package - Supports automatic conversion from the `v1alpha1` to `v1alpha2` API - Adds support to set token expiration directly instead of setting a TTL (Expiration and TTL are mutually exclusive) - Removes the old `TokenDiscovery` struct we're not using anymore inside of kubeadm **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Related to https://github.com/kubernetes/community/pull/2131 **Special notes for your reviewer**: This is work in progress. Please only review the first two commits for now. I will work on splitting up this PR in smaller chunks. I will also write unit tests tomorrow. **Release note**: ```release-note [action required] kubeadm: The Token-related fields in the `MasterConfiguration` object have now been refactored. Instead of the top-level `.Token`, `.TokenTTL`, `.TokenUsages`, `.TokenGroups` fields, there is now a `BootstrapTokens` slice of `BootstrapToken` objects that support the same features under the `.Token`, `.TTL`, `.Usages`, `.Groups` fields. ``` @kubernetes/sig-cluster-lifecycle-pr-reviews @mattmoyer @liztio Kubernetes-commit: c7b71ebca95d9afb5c4adbadf6cde09a0988d5a7
This commit is contained in:
commit
787033cb72
102
Godeps/Godeps.json
generated
102
Godeps/Godeps.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go",
|
||||
"GoVersion": "go1.10",
|
||||
"GoVersion": "go1.9",
|
||||
"GodepVersion": "v80",
|
||||
"Packages": [
|
||||
"./..."
|
||||
@ -388,203 +388,203 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/fields",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/labels",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/selection",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/types",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/version",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/watch",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
|
||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
||||
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package api (pkg/bootstrap/token/api) contains constants and types needed for
|
||||
// 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 pkg/controller/bootstrap)
|
||||
// controllers (in k8s.io/kubernetes/pkg/controller/bootstrap)
|
||||
package api // import "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
|
@ -86,14 +86,26 @@ const (
|
||||
// authenticate as. The full username given is "system:bootstrap:<token-id>".
|
||||
BootstrapUserPrefix = "system:bootstrap:"
|
||||
|
||||
// BootstrapGroupPattern is the valid regex pattern that all groups
|
||||
// assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match.
|
||||
// See also ValidateBootstrapGroupName().
|
||||
BootstrapGroupPattern = "system:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]"
|
||||
|
||||
// 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.
|
||||
|
@ -17,20 +17,101 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/bootstrap/token/api"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/bootstrap/token/api"
|
||||
)
|
||||
|
||||
var bootstrapGroupRegexp = regexp.MustCompile(`\A` + api.BootstrapGroupPattern + `\z`)
|
||||
// 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.
|
||||
// TODO(mattmoyer): this validation should migrate out to client-go (see https://github.com/kubernetes/client-go/issues/114)
|
||||
func ValidateBootstrapGroupName(name string) error {
|
||||
if bootstrapGroupRegexp.Match([]byte(name)) {
|
||||
if BootstrapGroupRegexp.Match([]byte(name)) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, api.BootstrapGroupPattern)
|
||||
@ -46,7 +127,7 @@ func ValidateUsages(usages []string) error {
|
||||
}
|
||||
}
|
||||
if len(invalidUsages) > 0 {
|
||||
return fmt.Errorf("invalide bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ","))
|
||||
return fmt.Errorf("invalid bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ","))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -21,6 +21,143 @@ import (
|
||||
"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
|
||||
|
Loading…
Reference in New Issue
Block a user