kubeadm
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
, 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 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.
FEATURE STATE: Kubernetes v1.8
beta
This feature is currently in a beta state, meaning:
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.
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:
Authorization: Bearer 07401b.f395accd246ae52d
Each valid token is backed by a secret in the kube-system
namespace. You can
find the full design doc
here.
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.
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-<token id>
. 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:<Token ID>
. 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.
kubeadm
You can use the kubeadm
tool to manage tokens on a running cluster. See the
kubeadm token
docs for details.
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:
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: <really long certificate 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.