kubernetes Users and RBAC
1. Users in Kubernetes
Users access the Kubernetes API using kubectl
, client libraries, or by making REST requests, through several stages, illustrated in the following diagram: [1]
All Kubernetes clusters have two categories of users: service accounts managed by Kubernetes, and normal users. [2]
It is assumed that a cluster-independent service manages normal users in the following ways:
-
an administrator distributing private keys
-
a user store like Keystone or Google Accounts
-
a file with a list of usernames and passwords
Kubernetes does not have objects which represent normal user accounts. |
Any user that presents a valid certificate signed by the cluster’s certificate authority (CA) is considered authenticated. API requests are tied to either a normal user or a service account, or are treated as anonymous requests.
-
Kubernetes determines the username from the common name and groups from organization name in the 'subject' of the cert (e.g., "/CN=bob/O=group1/O=group2").
-
The role based access control (RBAC) sub-system would determine whether the user or group is authorized to perform a specific operation on a resource.
In contrast, service accounts are users managed by the Kubernetes API.
-
They are bound to specific namespaces, and created automatically by the API server or manually through API calls.
-
Service accounts are tied to a set of credentials stored as
Secrets
, mounted into pods allowing in-cluster processes to talk to the Kubernetes API.
2. Authentication
Kubernetes uses client certificates, bearer tokens, an authenticating proxy to authenticate API requests through authentication plugins. [2]
As HTTP requests are made to the API server, plugins attempt to associate the following attributes with the request:
-
Username: a string which identifies the end user.
Common values might be
kube-admin
orjane@example.com
. -
UID: a string which identifies the end user and attempts to be more consistent and unique than username.
-
Groups
: a set of strings, each of which indicates the user’s membership in a named logical collection of users.Common values might be
system:masters
ordevops-team
. -
Extra fields
: a map of strings to list of strings which holds additional information authorizers may find useful. -
The
system:authenticated
group is included in the list of groups for all authenticated users.
2.1. X509 client certificates
Client certificate authentication is enabled by passing the --client-ca-file=SOMEFILE
option to API server. The referenced file must contain one or more certificate authorities to use to validate client certificates presented to the API server.
-
If a client certificate is presented and verified, the common name of the subject is used as the user name for the request.
-
Client certificates can also indicate a user’s group memberships using the certificate’s organization fields.
For example, using the openssl
command line tool to generate a certificate signing request:
openssl req \
-nodes -newkey rsa -keyout jbeda.pem \
-out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2"
This would create a CSR for the username "jbeda", belonging to two groups, "app1" and "app2".
2.2. Service Account Tokens
A service account is an automatically enabled authenticator that uses signed bearer tokens to verify requests.
The plugin takes two optional flags:
-
--service-account-key-file
File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify ServiceAccount tokens.
The specified file can contain multiple keys, and the flag can be specified multiple times with different files. If unspecified,
--tls-private-key-file
is used. -
--service-account-lookup
If enabled, tokens which are deleted from the API will be revoked.
Service accounts are usually created automatically by the API server and associated with pods running in the cluster through the ServiceAccount
Admission Controller.
-
Bearer tokens are mounted into pods at well-known locations, and allow in-cluster processes to talk to the API server.
-
Accounts may be explicitly associated with pods using the
serviceAccountName
field of aPodSpec
.$ kubectl get -n kube-system po coredns-7b44686977-vlt44 -oyaml ... spec: containers: - args: volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: kube-api-access-7xmwj readOnly: true serviceAccount: coredns serviceAccountName: coredns volumes: - name: kube-api-access-7xmwj projected: defaultMode: 420 sources: - serviceAccountToken: expirationSeconds: 3607 path: token - configMap: items: - key: ca.crt path: ca.crt name: kube-root-ca.crt - downwardAPI: items: - fieldRef: apiVersion: v1 fieldPath: metadata.namespace path: namespace ...
Service account bearer tokens are perfectly valid to use outside the cluster and can be used to create identities for long standing jobs that wish to talk to the Kubernetes API.
To manually create a service account, use the kubectl create serviceaccount (NAME)
command.
# creates a service account in the current namespace.
kubectl create serviceaccount jenkins
# create an associated token, a signed JSON Web Token (JWT).
kubectl create token jenkins
The signed JWT can be used as a bearer token (i.e., Authorization: Bearer <token>
) to authenticate as the given service account.
JSON Web Tokens consist of three parts separated by dots (.), which are:
|
Service accounts authenticate with the username system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT) , and are assigned to the groups system:serviceaccounts and system:serviceaccounts:(NAMESPACE) .
|
2.3. User impersonation
A user can act as another user through impersonation headers, which can let requests manually override the user info a request authenticates as. For example, an admin could use this feature to debug an authorization policy by temporarily impersonating another user and seeing if a request was denied.
Impersonation requests first authenticate as the requesting user, then switch to the impersonated user info.
-
A user makes an API call with their credentials and impersonation headers.
-
API server authenticates the user.
-
API server ensures the authenticated users have impersonation privileges.
-
Request user info is replaced with impersonation values.
-
Request is evaluated, authorization acts on impersonated user info.
When using kubectl
set the --as
flag to configure the Impersonate-User
header, set the --as-group
flag to configure the Impersonate-Group
header.
$ kubectl get pod --as nobody
Error from server (Forbidden): pods is forbidden: User "nobody" cannot list resource "pods" in API group "" in the namespace "default"
2.4. API access to authentication information for a client
FEATURE STATE: Kubernetes v1.28 [stable]
If your cluster has the API enabled, you can use the SelfSubjectReview
API to find out how your Kubernetes cluster maps your authentication information to identify you as a client.
POST /apis/authentication.k8s.io/v1/selfsubjectreviews
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "SelfSubjectReview"
}
For convenience, the kubectl auth whoami
command is present.
$ kubectl auth whoami -oyaml
apiVersion: authentication.k8s.io/v1
kind: SelfSubjectReview
metadata:
creationTimestamp: "2024-03-05T05:31:48Z"
status:
userInfo:
groups:
- kubeadm:cluster-admins
- system:authenticated
username: kubernetes-admin
3. Authorization
Kubernetes authorizes API requests using the API server, and evaluates all of the authenticated request attributes against all policies and allows or denies the request. [3]
-
user - The
user
string provided during authentication. -
group - The list of group names to which the authenticated user belongs.
-
extra - A map of arbitrary string keys to string values, provided by the authentication layer.
-
API - Indicates whether the request is for an API resource.
-
Request path - Path to miscellaneous non-resource endpoints like
/api
or/healthz
. -
API request verb - API verbs like
get
,list
,create
,update
,patch
,watch
,delete
, anddeletecollection
are used for resource requests. -
HTTP request verb - Lowercased HTTP methods like
get
,post
,put
, anddelete
are used for non-resource requests. -
Resource - The ID or name of the resource that is being accessed (for resource requests only) — For resource requests using
get
,update
,patch
, anddelete
verbs, you must provide the resource name. -
Subresource - The subresource that is being accessed (for resource requests only).
-
Namespace - The namespace of the object that is being accessed (for namespaced resource requests only).
-
API group - The API Group being accessed (for resource requests only). An empty string designates the core API group.
3.1. Determine the Request Verb
-
Non-resource requests
Requests to endpoints other than
/api/v1/…
or/apis/<group>/<version>/…
are considered "non-resource requests", and use the lower-cased HTTP method of the request as the verb.For example, a GET request to endpoints like
/api
or/healthz
would useget
as the verb. -
Resource requests
To determine the request verb for a resource API endpoint, review the HTTP verb used and whether or not the request acts on an individual resource or a collection of resources:
HTTP verb request verb POST
create
GET, HEAD
get (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources)
PUT
update
PATCH
patch
DELETE
delete (for individual resources), deletecollection (for collections)
Kubernetes sometimes checks authorization for additional permissions using specialized verbs. For example:
-
RBAC
bind
andescalate
verbs onroles
andclusterroles
resources in therbac.authorization.k8s.io
API group. -
Authentication
impersonate
verb onusers
,groups
, andserviceaccounts
in the core API group, and theuserextras
in theauthentication.k8s.io
API group.
3.2. Authorization Modes
The Kubernetes API server may authorize a request using one of several authorization modes:
-
Node - A special-purpose authorization mode that grants permissions to kubelets based on the pods they are scheduled to run.
-
ABAC - Attribute-based access control (ABAC) defines an access control paradigm whereby access rights are granted to users through the use of policies which combine attributes together.
-
RBAC - Role-based access control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within an enterprise.
-
Webhook - A WebHook is an HTTP callback: an HTTP POST that occurs when something happens; a simple event-notification via HTTP POST.
3.3. Checking API Access
The command kubectl
provides the auth can-i
subcommand for quickly querying the API authorization layer, that uses the SelfSubjectAccessReview
API to determine if the current user can perform a given action, and works regardless of the authorization mode used.
kubectl auth can-i create deployments --namespace dev
yes
kubectl auth can-i create deployments --namespace prod
no
kubectl auth can-i list secrets --namespace dev --as dave
no
kubectl auth can-i list pods \
--namespace target \
--as system:serviceaccount:dev:dev-sa
yes
These SelfSubjectRulesReview
API can be queried by creating normal Kubernetes resources, where the response "status" field of the returned object is the result of the query.
kubectl create -f - -o yaml << EOF
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
spec:
resourceAttributes:
group: apps
resource: deployments
verb: create
namespace: dev
EOF
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
...
status:
allowed: true
reason: 'RBAC: allowed by ClusterRoleBinding "kubeadm:cluster-admins" of ClusterRole
"cluster-admin" to Group "kubeadm:cluster-admins"'
3.4. RBAC Authorization
Role-based access control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within your organization.
RBAC authorization uses the rbac.authorization.k8s.io
API group to drive authorization decisions, allowing you to dynamically configure policies through the Kubernetes API.
3.4.1. Role and ClusterRole
An RBAC Role
or ClusterRole
contains rules that represent a set of permissions. Permissions are purely additive (there are no "deny" rules).
-
A Role always sets permissions within a particular namespace; when you create a Role, you have to specify the namespace it belongs in.
-
By contrast, ClusterRole, is a non-namespaced resource.
The resources have different names (Role and ClusterRole) because a Kubernetes object always has to be either namespaced or not namespaced; it can’t be both.
Here’s an example Role in the "default" namespace that can be used to grant read access to pods:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
Because ClusterRoles are cluster-scoped, they can also used to grant access to:
-
cluster-scoped resources (like
nodes
) -
non-resource endpoints (like
/healthz
) -
namespaced resources (like
Pods
), across all namespacesFor example: use a ClusterRole to allow a particular user to run
kubectl get pods --all-namespaces
.
Here is an example of a ClusterRole that can be used to grant read access to secrets in any particular namespace, or across all namespaces (depending on how it is bound):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" omitted since ClusterRoles are not namespaced
name: secret-reader
rules:
- apiGroups: [""]
#
# at the HTTP level, the name of the resource for accessing Secret
# objects is "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]
3.4.2. RoleBinding and ClusterRoleBinding
A role binding grants the permissions defined in a role to a user or set of users.
-
It holds a list of
subjects
(users, groups, or service accounts), and a reference to the role being granted. -
A
RoleBinding
grants permissions within a specific namespace whereas aClusterRoleBinding
grants that access cluster-wide. -
A RoleBinding may reference any Role in the same namespace.
-
A RoleBinding can also reference a ClusterRole to grant the permissions defined in that ClusterRole to resources inside the RoleBinding’s namespace.
-
To bind a ClusterRole to all the namespaces in a cluster, use a ClusterRoleBinding.
Here is an example of a RoleBinding that grants the "pod-reader" Role to the user "jane" within the "default" namespace.
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
name: jane # "name" is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" specifies the binding to a Role / ClusterRole
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
For instance, even though the following RoleBinding refers to a ClusterRole, "dave" (the subject, case sensitive) will only be able to read Secrets in the "dev" namespace, because the RoleBinding’s namespace (in its metadata) is "dev".
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "dev" namespace.
# You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
name: read-secrets
#
# The namespace of the RoleBinding determines where the permissions are granted.
# This only grants permissions within the "dev" namespace.
namespace: dev
subjects:
- kind: User
name: dave # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
The following ClusterRoleBinding allows any user in the group "manager" to read secrets in any namespace.
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
3.4.3. Referring to Resources
In the Kubernetes API, most resources (including subresources) are represented and accessed using a string representation of their object name, such as pods
for a Pod. RBAC refers to resources using exactly the same name that appears in the URL for the relevant API endpoint.
A request for a Pod’s logs looks like: GET /api/v1/namespaces/{namespace}/pods/{name}/log
.
-
In this case,
pods
is the namespaced resource for Pod resources, andlog
is a subresource of pods. -
To represent this in an RBAC role, use a slash (
/
) to delimit the resource and subresource. -
To allow a subject to read
pods
and also access thelog
subresource for each of those Pods, write:apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-and-pod-logs-reader rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list"]
To restrict to individual instances of a resource, refer to resources by name for certain requests through the resourceNames
list. Here is an example that restricts its subject to only get
or update
a ConfigMap named my-configmap
:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
#
# at the HTTP level, the name of the resource for accessing ConfigMap
# objects is "configmaps"
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
Rather than referring to individual resources
, apiGroups
, and verbs
, use the wildcard *
symbol to refer to all such objects.
-
For
nonResourceURLs
, use the wildcard*
as a suffix glob match. -
For
resourceNames
, an empty set means that everything is allowed.
Here is the definition of the built-in cluster-admin
ClusterRole.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# ...
name: cluster-admin
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
- nonResourceURLs:
- '*'
verbs:
- '*'
3.4.4. Aggregated ClusterRoles
A controller, running as part of the cluster control plane, watches for ClusterRole objects with an aggregationRule
set that defines a label selector to match other ClusterRole objects that should be combined into the rules
field of this one.
Here is an example aggregated ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # The control plane automatically fills in the rules
3.4.5. Referring to Subjects
A RoleBinding or ClusterRoleBinding binds a role to subjects which can be groups, users or ServiceAccounts.
The prefix |
ServiceAccounts have names prefixed with
|
For a user named alice@example.com
:
subjects:
- kind: User
name: "alice@example.com"
apiGroup: rbac.authorization.k8s.io
For a group named frontend-admins
:
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
For the default
service account in the "kube-system" namespace:
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
For all service accounts in the "qa" namespace:
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
For all service accounts in any namespace:
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
For all authenticated users:
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
For all unauthenticated users:
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
For all users:
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
3.4.6. Default Roles and Role Bindings
API servers create a set of default ClusterRole and ClusterRoleBinding objects.
-
Many of these are
system:
prefixed, which indicates that the resource is directly managed by the cluster control plane. -
All of the default ClusterRoles and ClusterRoleBindings are labeled with
kubernetes.io/bootstrapping=rbac-defaults
.
Take care when modifying ClusterRoles and ClusterRoleBindings with names that have a |
At each start-up, the API server updates default cluster roles with any missing permissions, and updates default cluster role bindings with any missing subjects.
Some of the default ClusterRoles are not system:
prefixed which are intended to be user-facing roles that include super-user roles (cluster-admin
), roles intended to be granted cluster-wide using ClusterRoleBindings, and roles intended to be granted within particular namespaces using RoleBindings (admin
, edit
, view
).
3.4.7. Command-line utilities
-
Create a Role named "pod-reader" that allows users to perform
get
,watch
andlist
on pods:kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
-
Create a Role named "pod-reader" with resourceNames specified:
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
-
Create a Role named "foo" with apiGroups specified:
kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
-
Create a Role named "foo" with subresource permissions:
kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
-
Create a Role named "my-component-lease-holder" with permissions to get/update a resource with a specific name:
kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
-
Create a ClusterRole named "pod-reader" that allows user to perform
get
,watch
andlist
on pods:kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
-
Create a ClusterRole named "pod-reader" with resourceNames specified:
kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
-
Create a ClusterRole named "foo" with apiGroups specified:
kubectl create clusterrole foo --verb=get,list,watch --resource=replicasets.apps
-
Create a ClusterRole named "foo" with subresource permissions:
kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
-
Create a ClusterRole named "foo" with nonResourceURL specified:
kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
-
Create a ClusterRole named "monitoring" with an aggregationRule specified:
kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"
-
Within the namespace "acme", grant the permissions in the "admin" ClusterRole to a user named "bob":
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
-
Within the namespace "acme", grant the permissions in the "view" ClusterRole to the service account in the namespace "acme" named "myapp":
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
-
Within the namespace "acme", grant the permissions in the "view" ClusterRole to a service account in the namespace "myappnamespace" named "myapp":
kubectl create rolebinding myappnamespace-myapp-view-binding --clusterrole=view --serviceaccount=myappnamespace:myapp --namespace=acme
-
Across the entire cluster, grant the permissions in the "cluster-admin" ClusterRole to a user named "root":
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
-
Across the entire cluster, grant the permissions in the "system:node-proxier" ClusterRole to a user named "system:kube-proxy":
kubectl create clusterrolebinding kube-proxy-binding --clusterrole=system:node-proxier --user=system:kube-proxy
-
Across the entire cluster, grant the permissions in the "view" ClusterRole to a service account named "myapp" in the namespace "acme":
kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
-
Test applying a manifest file of RBAC objects, displaying changes that would be made:
kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client
-
Apply a manifest file of RBAC objects, preserving any extra permissions (in roles) and any extra subjects (in bindings):
kubectl auth reconcile -f my-rbac-rules.yaml
-
Apply a manifest file of RBAC objects, removing any extra permissions (in roles) and any extra subjects (in bindings):
kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions
4. Certificates and Certificate Signing Requests
A CertificateSigningRequest
(CSR) resource is used to request that a certificate be signed by a denoted signer, after which the request may be approved or denied before finally being signed. [4]
4.1. Signers
Signers abstractly represent the entity or entities that might sign, or have signed, a security certificate.
Any signer that is made available for outside a particular cluster should provide information about how the signer works, so that consumers can understand what that means for CertifcateSigningRequests and (if enabled) ClusterTrustBundles which are cluster-scoped objects for distributing X.509 trust anchors (root certificates) to workloads within the cluster. .
-
Trust distribution: how trust anchors (CA certificates or certificate bundles) are distributed.
-
Permitted subjects: any restrictions on and behavior when a disallowed subject is requested.
-
Permitted x509 extensions: including IP subjectAltNames, DNS subjectAltNames, Email subjectAltNames, URI subjectAltNames etc, and behavior when a disallowed extension is requested.
-
Permitted key usages / extended key usages: any restrictions on and behavior when usages different than the signer-determined usages are specified in the CSR.
-
Expiration/certificate lifetime: whether it is fixed by the signer, configurable by the admin, determined by the CSR
spec.expirationSeconds
field, etc and the behavior when the signer-determined expiration is different from the CSRspec.expirationSeconds
field. -
CA bit allowed/disallowed: and behavior if a CSR contains a request a for a CA certificate when the signer does not permit it.
Commonly, the status.certificate
field of a CertificateSigningRequest contains a single PEM-encoded X.509 certificate once the CSR is approved and the certificate is issued.
4.2. Kubernetes signers
Kubernetes provides built-in signers that each have a well-known signerName
:
-
kubernetes.io/kube-apiserver-client
: signs certificates that will be honored as client certificates by the API server. Never auto-approved by kube-controller-manager.-
Trust distribution: signed certificates must be honored as client certificates by the API server. The CA bundle is not distributed by any other means.
-
Permitted subjects: no subject restrictions, but approvers and signers may choose not to approve or sign.
-
Permitted x509 extensions - honors subjectAltName and key usage extensions and discards other extensions.
-
Permitted key usages: Must include
["client auth"]
. Must not include key usages beyond["digital signature", "key encipherment", "client auth"]
. -
Expiration/certificate lifetime: for the kube-controller-manager implementation of this signer, set to the minimum of the
--cluster-signing-duration
option or, if specified, thespec.expirationSeconds
field of the CSR object. -
CA bit allowed/disallowed: not allowed.
-
-
kubernetes.io/kube-apiserver-client-kubelet
: signs client certificates that will be honored as client certificates by the API server. May be auto-approved by kube-controller-manager.-
Trust distribution: signed certificates must be honored as client certificates by the API server. The CA bundle is not distributed by any other means.
-
Permitted subjects: organizations are exactly
["system:nodes"]
, common name starts withsystem:node:
. -
Permitted x509 extensions: honors key usage extensions, forbids subjectAltName extensions and drops other extensions.
-
Permitted key usages:
["key encipherment", "digital signature", "client auth"]
or["digital signature", "client auth"]
. -
Expiration/certificate lifetime: for the kube-controller-manager implementation of this signer, set to the minimum of the
--cluster-signing-duration
option or, if specified, thespec.expirationSeconds
field of the CSR object. -
CA bit allowed/disallowed - not allowed.
-
-
kubernetes.io/kubelet-serving
: signs serving certificates that are honored as a valid kubelet serving certificate by the API server, but has no other guarantees. Never auto-approved by kube-controller-manager.-
Trust distribution: signed certificates must be honored by the API server as valid to terminate connections to a kubelet. The CA bundle is not distributed by any other means.
-
Permitted subjects: organizations are exactly
["system:nodes"]
, common name starts withsystem:node:
. -
Permitted x509 extensions: honors key usage and DNSName/IPAddress subjectAltName extensions, forbids EmailAddress and URI subjectAltName extensions, drops other extensions. At least one DNS or IP subjectAltName must be present.
-
Permitted key usages:
["key encipherment", "digital signature", "server auth"]
or["digital signature", "server auth"]
. -
Expiration/certificate lifetime: for the kube-controller-manager implementation of this signer, set to the minimum of the
--cluster-signing-duration
option or, if specified, thespec.expirationSeconds
field of the CSR object. -
CA bit allowed/disallowed - not allowed.
-
The kube-controller-manager implements control plane signing for each of the built in signers. Failures for all of these are only reported in kube-controller-manager logs.
A Kubernetes administrator (with appropriate permissions) can manually approve (or deny) CertificateSigningRequests by using the kubectl certificate approve
and kubectl certificate deny
commands.
4.3. How to issue a certificate for a user
-
Generate a certificate signing request:
openssl req \ -nodes \ -newkey rsa \ -subj "/CN=developer/O=developers" \ -keyout developer.key \ -out developer-csr.pem
-
Create a CertificateSigningRequest and submit it to Kubernetes Cluster:
kubectl apply -f - <<EOF apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: developers spec: username: developer groups: ["developers"] request: $(base64 <(cat developer-csr.pem) | tr -d '\n') usages: ["digital signature", "key encipherment", "client auth"] #expirationSeconds: 7200 signerName: kubernetes.io/kube-apiserver-client EOF
certificatesigningrequest.certificates.k8s.io/developers created
-
Approve the CertificateSigningRequest via
kubectl
:kubectl get csr developers
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION developers 17s kubernetes.io/kube-apiserver-client kubernetes-admin <none> Pending
kubectl certificate approve developers
certificatesigningrequest.certificates.k8s.io/developers approved
-
Retrieve the certificate from the CSR object:
kubectl get csr developers \ -ojsonpath='{.status.certificate}' \ | base64 -d > developer.crt
-
Create a kubeconfig file:
Below is a script to generate the kubeconfig named
developer.config
in the current directory.# replace the CA file with your cluster certificate_authority=/etc/kubernetes/pki/ca.crt kubectl config set-cluster \ kubernetes \ --kubeconfig developer.config \ --server $(kubectl config view --minify | grep server | awk '{print $NF}') \ --certificate-authority $certificate_authority \ --embed-certs kubectl config set-credentials \ developer \ --kubeconfig developer.config \ --user developer \ --client-key developer.key \ --client-certificate developer.crt \ --embed-certs kubectl config set-context \ developer@kubernetes \ --kubeconfig developer.config \ --cluster kubernetes \ --user developer \ --namespace default
-
Create Role and RoleBinding:
# create a cluster role named developer:namespace:view # and assign the `get` and `list` permissions on `namespace` resources. kubectl create clusterrole developer:namespace:view \ --resource namespace \ --verb get \ --verb list kubectl create clusterrolebinding developer:namespace:view \ --clusterrole=developer:namespace:view \ --user developer
$ kubectl get ns --kubeconfig developer.config NAME STATUS AGE default Active 152d kube-node-lease Active 152d kube-public Active 152d kube-system Active 152d
-
References
-
[1] https://kubernetes.io/docs/concepts/security/controlling-access/
-
[2] https://kubernetes.io/docs/reference/access-authn-authz/authentication/
-
[3] https://kubernetes.io/docs/reference/access-authn-authz/authorization/
-
[4] https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/
-
[5] https://www.cncf.io/blog/2018/08/01/demystifying-rbac-in-kubernetes/