Kubernetes authentication

Kubernetes authentication mechanisms

view on github

Table of contents

  1. Initial assessments
  2. kube-apiserver users management
  3. kubeadm authentication strategies
  4. kubeconfig files
  5. PKI provisioning with kubeadm

Initial assessments

  • For simplicity's sake, this document will focus on built-in authentication strategies provided by kubeadm init.
  • For advanced use cases, here is a guide detailing the security aspects of all supported authentication strategies.
  • Authentication strategies used by complex organizations in large clusters (ex. OIDC) are considered out of scope.

kube-apiserver users management

User identification

  • kube-apiserver only recognizes users: no difference is made between admins and components requests.

  • Successful authentication of a request produces a set of informations identifying the user :

    field type managed by
    username String admin
    uid UUID k8s
    groups String array admin + k8s
    extra String list map admin
  • system:authenticated is automatically added to the groups array for all authenticated requests.

  • Those informations are then associated with the request for subsequent evaluation by authorization policies.

User type

  1. Normal users
    • Normal users are external processes (components or admins) authenticated to kube-apiserver.
    • They have to authenticate using a configured authentication strategy.
    • They are not managed as part of the cluster state and do not exist in the K8s API.
    • Examples : etcd, kubelet, kubernetes-admin, etc ...
  2. ServiceAccount users
    • ServiceAccount users are cluster workloads (pods) authenticated to kube-apiserver.
    • They have to authenticate using the ServiceAccount authentication strategy.
    • They are managed automatically by kube-apiserver and exist in the K8s API.
    • Examples : kube-proxy, kubernetes-dashboard, etc ...
  3. Anonymous users
    • Any request not validated by the configured authentication strategies is considered anonymous.
    • Anonymous authentication should be explicitly disabled using the --anonymous-auth=false command line option.

Best practices

  • Compliant to the K8s model, user provisioning and management is granular and unopinionated.

  • kubeadm init automatically provisions users for components and admins at bootstrapping time (see below).

  • Outside of that, user provisioning is largely dependent on admins, through state updates or packages installation.

  • As a result, admins have to consider the following rules when manually provisioning users :

    1. username should be unique for the cluster and not conflict with existing users.
    2. groups is unopinionated : it identifies and characterizes users the same way labels does with workloads.
    3. extra has to be supported by dedicated authorization policies and usually can be left blank.
  • Notes :

    • K8s does not support User objects : user information is never written to the cluster state.
    • Authentication strategies provide ways to "encode" user information inside authentication assets.

kubeadm authentication strategies

Authentication strategies for kube-apiserver can be configured using command line options.

  • This strategy uses PKI for requests authentication : this is the kubeadm default for provisioning normal users.
  • Requests are authenticated using mutual certificate validation :
    1. Validate that the certificate was issued by the cluster CA (for instance CN = kubernetes).
    2. Read the certificate's subject to identify the user (for instance O = kubeadm:cluster-admins, CN = kubernetes-admin).
  • New users are provisioned automatically or manually through issuance of *.crt certificate files.
  • Sets of certificates can be stored in kubeconfig files (see below).
  • This strategy uses JWTs for requests authentication : this is the sole strategy available for ServiceAccount users.
  • Requests are authenticated using bearer tokens :
    1. Validate that the token was signed by a dedicated private key (usually /etc/kubernetes/pki/sa.key).
    2. Decode the token claims to identify the user (for instance system:serviceaccount:kubernetes-dashboard:administrator).
  • New users are provisioned by creating ServiceAccount objects bound to specific Secret objects that store the JWT.
  • Tokens will be mounted into pods to allow workload processes to interact with kube-apiserver.

Bootstrap tokens

  • Bootstrap tokens are used by kubeadm to provision PKI assets for kubelet when a node joins a cluster.
  • Requests are authenticated using bearer tokens :
    1. Match the token ID and secret against the Secret data.
    2. User identity will be established once kubelet updates the cluster state with information about the new node.
  • kubeadm init provisions specific Secret objects in the kube-system namespace to store bootstrap tokens.
  • Management of bootstrap tokens by admins isn't required as long as the token secret is not compromised.

Authentication proxy

  • This strategy allows for delegation of request authentication to an external service.
  • Proxied requests are authenticated using certificate validation :
    1. Validate that the certificate was issued by the authentication proxy CA (for instance CN = front-proxy-ca).
    2. Read the certificate's subject to identify the external service (for instance CN = front-proxy-client).
    3. User identity will be established by reading specific request headers.
  • Multiple external services can be configured with --requestheader-allowed-names provided they present valid certificates.
  • kubeadm init provisions a specific chain of trust for front-proxy (see below).
  • However, it is not relevant to basic use cases since it is used for extending the kubernetes API.

kubeconfig files

  • kubeconfig files are YAML files storing identities for users and clusters, and contexts to associate them.
  • K8s clients wishing to authenticate as normal users with x509 certificates receive such a file as a parameter with --kubeconfig :
apiVersion: v1
kind: Config
# current context for client using this config
current-context: user-name@cluster-name
# contexts list, include for each :
# name -> username@cluster
# context -> binds cluster to user
contexts:
  - name: user-name@cluster-name
    context:
      cluster: cluster-name
      user: user-name
# clusters list, include for each :
# name -> configured cluster name
# cluster -> control plane + cluster CA certificate
clusters:
  - name: cluster-name
    cluster:
      certificate-authority-data: CLUSTER_CA_CRT
      server: https://control.plane.endpoint.com:6443
# users list, include for each :
# name -> optionally prefixed with colon separated groups
# user -> private key + client certificate (issued by cluster CA)
users:
  - name: user-name
    user:
      client-certificate: APISERVER_CLIENT_CRT
      client-key: APISERVER_CLIENT_KEY
  • Here, the client authenticates to https://control.plane.endpoint.com:6443 using certificate APISERVER_CLIENT_CRT.
  • kubeconfig certificates and private keys can either be base64 encoded files or file paths.
  • kubeadm init provisions kubeconfig files for components and admins (see below).

PKI provisioning with kubeadm

kubeadm init provisions multiple chains of trust as well as client and server certificates for components and admins.

Control plane components

  • Provisioned certificates and private keys are stored in /etc/kubernetes/pki :

    certificate type authenticates to CA certificate
    apiserver.crt Server kube-apiserver all API clients ca.crt
    apiserver-kubelet-client.crt Client kube-apiserver kubelet ca.crt
    apiserver-etcd-client.crt Client kube-apiserver etcd etcd/ca.crt
    front-proxy-client.crt Client kube-apiserver front-proxy front-proxy-ca.crt
    etcd/server.crt Server etcd all API clients etcd/ca.crt
    etcd/peer.crt Client etcd etcd peer nodes etcd/ca.crt
    etcd/healthcheck-client.crt Client etcd etcd etcd/ca.crt
    sa.pub N/A ServiceAccount kube-apiserver N/A
  • sa.pub is used to verify that ServiceAccount tokens were signed using sa.key.

Node components

  • Provisioned certificates and private keys are stored in /var/lib/kubelet/pki :

    certificate type authenticates to CA certificate
    kubelet-client-current.pem Client kubelet kube-apiserver ca.crt
    kubelet-server-current.crt Server kubelet all API clients ca.crt
  • kubelet-client-current.pem authenticates kubelet requests to kube-apiserver.

  • kubelet-server-current.pem authenticates requests to the kubelet API.

kubeconfig files for control plane components and admins

  • Certificates and private keys provisioned in kubeconfig files are stored in /etc/kubernetes :

    file type authenticates to CA certificate
    controller-manager.conf Client kube-controller-manager kube-apiserver ca.crt
    scheduler.conf Client kube-scheduler kube-apiserver ca.crt
    kubelet.conf Client kubelet kube-apiserver ca.crt
    admin.conf Client kubernetes-admin kube-apiserver ca.crt
    super-admin.conf Client kubernetes-super-admin kube-apiserver ca.crt
  • Using ServiceAccount to authenticate control plane components is not possible since kubeadm runs them as static pods.

  • As a result, kube-controller-manager and kube-scheduler will be passed the relevant kubeconfig as a command line option.

  • Command line options can be inspected for static pods to review actual config or PKI settings :

# print the kube-scheduler command arguments when running as a static pod
kubectl get -n kube-system pod "kube-scheduler-$(hostname)" -o jsonpath='{.spec.containers[0].command}' | jq -r '.[] | @text'