mirror of
https://github.com/kubernetes/client-go.git
synced 2025-07-18 09:11:10 +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",
|
"ImportPath": "k8s.io/client-go",
|
||||||
"GoVersion": "go1.10",
|
"GoVersion": "go1.9",
|
||||||
"GodepVersion": "v80",
|
"GodepVersion": "v80",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./..."
|
"./..."
|
||||||
@ -388,203 +388,203 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
|
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
|
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
|
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
|
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
|
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
|
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/fields",
|
"ImportPath": "k8s.io/apimachinery/pkg/fields",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/labels",
|
"ImportPath": "k8s.io/apimachinery/pkg/labels",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
|
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/selection",
|
"ImportPath": "k8s.io/apimachinery/pkg/selection",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/types",
|
"ImportPath": "k8s.io/apimachinery/pkg/types",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/version",
|
"ImportPath": "k8s.io/apimachinery/pkg/version",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/watch",
|
"ImportPath": "k8s.io/apimachinery/pkg/watch",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
|
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
|
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
|
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
|
||||||
"Rev": "5204d3828432611e41488a8042bc1d16a7c12e05"
|
"Rev": "1e6ce0f30d47d3c48634eabcc5b25a594654e7a5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
"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.
|
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
|
// 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"
|
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>".
|
// authenticate as. The full username given is "system:bootstrap:<token-id>".
|
||||||
BootstrapUserPrefix = "system:bootstrap:"
|
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
|
// BootstrapDefaultGroup is the default group for bootstrapping bearer
|
||||||
// tokens (in addition to any groups from BootstrapTokenExtraGroupsKey).
|
// tokens (in addition to any groups from BootstrapTokenExtraGroupsKey).
|
||||||
BootstrapDefaultGroup = "system:bootstrappers"
|
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.
|
// KnownTokenUsages specifies the known functions a token will get.
|
||||||
|
@ -17,20 +17,101 @@ limitations under the License.
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
"k8s.io/client-go/tools/bootstrap/token/api"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"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
|
// ValidateBootstrapGroupName checks if the provided group name is a valid
|
||||||
// bootstrap group name. Returns nil if valid or a validation error if invalid.
|
// 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 {
|
func ValidateBootstrapGroupName(name string) error {
|
||||||
if bootstrapGroupRegexp.Match([]byte(name)) {
|
if BootstrapGroupRegexp.Match([]byte(name)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, api.BootstrapGroupPattern)
|
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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,143 @@ import (
|
|||||||
"testing"
|
"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) {
|
func TestValidateBootstrapGroupName(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
Loading…
Reference in New Issue
Block a user