--- approvers: - jbeda title: Authenticating with Bootstrap Tokens --- * TOC {:toc} ## Overview Bootstrap tokens are a simple bearer token that is meant to be used when creating new clusters or joining new nodes to an existing cluster. It was built to support [`kubeadm`](/docs/admin/kubeadm/), but can be used in other contexts for users that wish to start clusters without `kubeadm`. It is also built to work, via RBAC policy, with the [Kubelet TLS Bootstrapping](/docs/admin/kubelet-tls-bootstrapping/) system. Bootstrap Tokens are defined with a specific type (`bootstrap.kubernetes.io/token`) of secrets that lives in the `kube-system` namespace. These Secrets are then read by the Bootstrap Authenticator in the API Server. Expired tokens are removed with the TokenCleaner controller in the Controller Manager. The tokens are also used to create a signature for a specific ConfigMap used in a "discovery" process through a BootstrapSigner controller. {% include feature-state-beta.md %} ## Token Format Bootstrap Tokens take the form of `abcdef.0123456789abcdef`. More formally, they must match the regular expression `[a-z0-9]{6}\.[a-z0-9]{16}`. The first part of the token is the "Token ID" and is considered public information. It is used when referring to a token without leaking the secret part used for authentication. The second part is the "Token Secret" and should only be shared with trusted parties. ## Enabling Bootstrap Tokens All features for Bootstrap Tokens are disabled by default in Kubernetes v1.8. You can enable the Bootstrap Token authenticator with the `--enable-bootstrap-token-auth` flag on the API server. You can enable the Bootstrap controllers by specifying them with the `--controllers` flag on the controller manager with something like `--controllers=*,tokencleaner,bootstrapsigner`. This is done automatically when using `kubeadm`. Tokens are used in an HTTPS call as follows: ```http Authorization: Bearer 07401b.f395accd246ae52d ``` ## Bootstrap Token Secret Format Each valid token is backed by a secret in the `kube-system` namespace. You can find the full design doc [here](https://github.com/kubernetes/community/blob/{{page.githubbranch}}/contributors/design-proposals/cluster-lifecycle/bootstrap-discovery.md). Here is what the secret looks like. Note that `base64(string)` indicates the value should be base64 encoded. The undecoded version is provided here for readability. ```yaml apiVersion: v1 kind: Secret metadata: name: bootstrap-token-07401b namespace: kube-system type: bootstrap.kubernetes.io/token data: description: base64(The default bootstrap token generated by 'kubeadm init'.) token-id: base64(07401b) token-secret: base64(f395accd246ae52d) expiration: base64(2017-03-10T03:22:11Z) usage-bootstrap-authentication: base64(true) usage-bootstrap-signing: base64(true) auth-extra-groups: base64(system:bootstrappers:group1,system:bootstrappers:group2) ``` The type of the secret must be `bootstrap.kubernetes.io/token` and the name must be `bootstrap-token-`. It must also exist in the `kube-system` namespace. `description` is a human readable description that should not be used for machine readable information. The Token ID and Secret are included in the data dictionary. The `usage-bootstrap-*` members indicate what this secret is intended to be used for. A value must be set to `true` to be enabled. `usage-bootstrap-authentication` indicates that the token can be used to authenticate to the API server. The authenticator authenticates as `system:bootstrap:`. It is included in the `system:bootstrappers` group. `auth-extra-groups` indicates that it will also be included in the `system:bootstrappers:group1`, and `system:bootstrappers:group2` groups. The naming and groups are intentionally limited to discourage users from using these tokens past bootstrapping. Extra bootstrap token groups must start with `system:bootstrappers:`. `usage-bootstrap-signing` indicates that the token should be used to sign the `cluster-info` ConfigMap as described below. The `expiration` data member lists a time after which the token is no longer valid. This is encoded as an absolute UTC time using RFC3339. The TokenCleaner controller will delete expired tokens. ## Token Management with `kubeadm` You can use the `kubeadm` tool to manage tokens on a running cluster. See the [`kubeadm token` docs](/docs/admin/kubeadm/#manage-tokens) for details. ## ConfigMap Signing In addition to authentication, the tokens can be used to sign a ConfigMap. This is used early in a cluster bootstrap process before the client trusts the API server. The signed ConfigMap can be authenticated by the shared token. The ConfigMap that is signed is `cluster-info` in the `kube-public` namespace. The typical flow is that a client reads this ConfigMap while unauthenticated and ignoring TLS errors. It then validates the payload of the ConfigMap by looking at a signature embedded in the ConfigMap. The ConfigMap may look like this: ```yaml apiVersion: v1 kind: ConfigMap metadata: name: cluster-info namespace: kube-public data: jws-kubeconfig-07401b: eyJhbGciOiJIUzI1NiIsImtpZCI6IjA3NDAxYiJ9..tYEfbo6zDNo40MQE07aZcQX2m3EB2rO3NuXtxVMYm9U kubeconfig: | apiVersion: v1 clusters: - cluster: certificate-authority-data: server: https://10.138.0.2:6443 name: "" contexts: [] current-context: "" kind: Config preferences: {} users: [] ``` The `kubeconfig` member of the ConfigMap is a config file with just the cluster information filled out. The key thing being communicated here is the `certificate-authority-data`. This may be expanded in the future. The signature is a JWS signature using the "detached" mode. To validate the signature, the user should encode the `kubeconfig` payload according to JWS rules (base64 encoded while discarding any trailing `=`). That encoded payload is then used to form a whole JWS by inserting it between the 2 dots. You can verify the JWS using the `HS256` scheme (HMAC-SHA256) with the full token (e.g. `07401b.f395accd246ae52d`) as the shared secret. Users _must_ verify that HS256 is used.