Skip to main content

Users

We use service accounts to grant permissions to apps, like bots.

  • We can have users, but there is no user resource in Kubernetes.
  • We can have service accounts.

If there is no user in Kubernetes, what is a user?

A user is someone who has a certificate and a key that was signed by the Kubernetes certificate authority.

We define the user by the CN (common name) of the certificate.

alt text

After authorization, permissions are checked on each request executed by the Kubernetes API by comparing the CN with the permissions they can have.

To create a certificate we need to create a certificate request (CSR) and send it to be signed by the Kubernetes CA. To create a CSR several tools can be used, but the most common is OpenSSL.

A CSR is the certificate without a CA signature.

The second step is to send the CSR to the Kubernetes API through a CertificateSigningRequest to be signed by the Kubernetes cluster CA. The API is the only Kubernetes component that has access to the cluster certificate authority certificate, but it needs to be approved by someone who has the power to release this approval (cluster admin for example).

Once this CertificateSigningRequest is approved, the API will sign the CSR and in the same CertificateSigningRequest the CRT will be made available, which is the certificate signed by the CA.

The CRT is the CSR + CA Signature.

This must be sent to the requester somehow, but it is not automatic. We can copy and send by email for example.

alt text

Just to be clear, as an administrator of a self-hosted cluster and having access to master nodes, we can have access to the cluster CA. If we want to copy the certificate and sign it ourselves without the kubernetes api it is possible.

The Kubernetes API makes the process easier for us, keeps the certificate inside the cluster ensuring security. It's not because we can do it that we should do it.

Once a certificate is issued there is no way to revoke it. It remains valid as long as the expiration date has not been reached.

If a certificate is compromised what we should do:

  • Remove all access via RBAC.
  • The username cannot be used until the certificate expires.
  • Recreate the cluster CA and reissue all certificates.

Knowing this:

  • Do not share certificates or access.
  • Do not issue long-lived certificates.
  • Do not use simple names like jane, use email which is something unique.
  • Manage certificate access with a password manager.

Creating a User Certificate

# Generating the private key
root@cks-master:/etc/kubernetes/manifests# openssl genrsa -out david.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...........................+++++
............................................................................................................................+++++
e is 65537 (0x010001)

# Generating the CSR
root@cks-master:~# openssl req -new -key david.key -out david.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:david
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

root@cks-master:~# ls david.*
david.csr david.key

# We will need the csr in base64 to fill out the request
root@cks-master:~# cat david.csr | base64 | tr -d "\n"
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=root@cks-master:~#

We create a CertificateSigningRequest with the yaml below.

apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: david
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kube-apiserver-client
# expirationSeconds: 86400 # one day
expirationSeconds: 15552000 # 180 days
usages:
- client auth

Now we can apply this yaml.

root@cks-master:~# kubectl apply -f csr.yaml
certificatesigningrequest.certificates.k8s.io/david created

# We can see the csr in pending state waiting for approval
root@cks-master:~# k get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
david 35s kubernetes.io/kube-apiserver-client kubernetes-admin 180d Pending

# Let's approve
root@cks-master:~# k certificate approve david
certificatesigningrequest.certificates.k8s.io/david approved

# Checking
root@cks-master:~# k get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
david 4m20s kubernetes.io/kube-apiserver-client kubernetes-admin 180d Approved,Issued

root@cks-master:~# k get csr david -o yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"certificates.k8s.io/v1","kind":"CertificateSigningRequest","metadata":{"annotations":{},"name":"david"},"spec":{"expirationSeconds":15552000,"request":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=","signerName":"kubernetes.io/kube-apiserver-client","usages":["client auth"]}}
creationTimestamp: "2024-08-21T03:47:18Z"
name: david
resourceVersion: "397047"
uid: ef44740a-a188-4fd2-9fac-e6ab8481560c
spec:
expirationSeconds: 15552000
groups:
- kubeadm:cluster-admins
- system:authenticated
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
username: kubernetes-admin
status:
# The Certificate is here but is in base64
certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPakNDQWlLZ0F3SUJBZ0lRU3BRcDJUaEZjOE54NWtSOW45UGQ1VEFOQmdrcWhraUc5dzBCQVFzRkFEQVYKTVJNd0VRWURWUVFERXdwcmRXSmxjbTVsZEdWek1CNFhEVEkwTURneU1UQXpORFl6TVZvWERUSTFNREl4TnpBegpORFl6TVZvd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdUQ2xOdmJXVXRVM1JoZEdVeElUQWZCZ05WCkJBb1RHRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF4TUZaR0YyYVdRd2dnRWkKTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMrSFkyN0RsOAp4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZjZGUzhaZlpCCnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oT2NwL09jTk0Ka3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQ0NTh4VTFDdgpVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVnBZUXh0TExrClBmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYQURmM0FnTUIKQUFHalJqQkVNQk1HQTFVZEpRUU1NQW9HQ0NzR0FRVUZCd01DTUF3R0ExVWRFd0VCL3dRQ01BQXdId1lEVlIwagpCQmd3Rm9BVXVxUE1RNGcvaGVCb2tsaDZheUpWQm5UNkFZNHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBTXY1Cmpsakh1NWhiUzVzVkdZNjR5V3JvVVpjcmhVZm9oM3JGTXlqTDBpa09mbU9XKy9qRmM2ckF0UzRLbUg0ZzRWNEUKRUFVZVVFak9MNDc4WlVqK3QvWDFmNGczd25KQThmRnhxNm5pcmxWMlNPdkJTSlBRSjllaWJ0Q04wa1VlQlNudwpvK29nM2FkUFVDNWk3ZUFHS1hNQkIzZjFTelhZRlNxbG83Zkx3MUs5OG44N0o4bkNVUUgrNzN6d2lQNDJWTGNwCkxQNnI0a2NvS0hacEhiSlZtRTZEcGExTzBCazR1Qm1PaDNvbE1ZaGd6Ymx0czZrMURnNUFjdWhhRjIyOFhuYnUKRFJqZDh5NFk4UkJBZnpZbDRvaHluSkxESWdoZ3hISzZEZlNKYzlBWjZtREtoWm5tbkI5d0o1T3MycmNxekRtNwpxNDdYbDFpd3l2OVkxRm8raFNjPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
conditions:
- lastTransitionTime: "2024-08-21T03:51:31Z"
lastUpdateTime: "2024-08-21T03:51:31Z"
message: This CSR was approved by kubectl certificate approve.
reason: KubectlApprove
status: "True"
type: Approved

# To make it easier we can use jsonpath and decode it
root@cks-master:~# kubectl get csr david -o jsonpath='{.status.certificate}' | base64 --decode
-----BEGIN CERTIFICATE-----
MIIDOjCCAiKgAwIBAgIQSpQp2ThFc8Nx5kR9n9Pd5TANBgkqhkiG9w0BAQsFADAV
MRMwEQYDVQQDEwprdWJlcm5ldGVzMB4XDTI0MDgyMTAzNDYzMVoXDTI1MDIxNzAz
NDYzMVowVTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEOMAwGA1UEAxMFZGF2aWQwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0FAkAO+svUwEMXbMC+HY27Dl8
xA6RXo7blHnyyBA7cbu0ojkqHWVDANKZw32wzX1aMv+pvE6eEz7QTOpf6FS8ZfZB
y3zrqz6EAdvYQV521eBeMDAyXkcTuFHhfaMcTlKcSi/Qm7Ehbr9wamnhOcp/OcNM
krw9mK+4eq41PAKLpUNpumDKGDPAeUQm0BrCc7oO9iTmoyTTh9Rz3JLt458xU1Cv
UYPlNvmbWHXAkBKW9YK8aVG/iN8mh64Uj3lCUdw2CoGTQa65edlVa6BVpYQxtLLk
PfKdf8joALic564h2vpxDdd3rXAsvYKnam0dumRbAdZOaijGtb7oGTVXADf3AgMB
AAGjRjBEMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHwYDVR0j
BBgwFoAUuqPMQ4g/heBoklh6ayJVBnT6AY4wDQYJKoZIhvcNAQELBQADggEBAMv5
jljHu5hbS5sVGY64yWroUZcrhUfoh3rFMyjL0ikOfmOW+/jFc6rAtS4KmH4g4V4E
EAUeUEjOL478ZUj+t/X1f4g3wnJA8fFxq6nirlV2SOvBSJPQJ9eibtCN0kUeBSnw
o+og3adPUC5i7eAGKXMBB3f1SzXYFSqlo7fLw1K98n87J8nCUQH+73zwiP42VLcp
LP6r4kcoKHZpHbJVmE6Dpa1O0Bk4uBmOh3olMYhgzblts6k1Dg5AcuhaF228Xnbu
DRjd8y4Y8RBAfzYl4ohynJLDIghgxHK6DfSJc9AZ6mDKhZnmnB9wJ5Os2rcqzDm7
q47Xl1iwyv9Y1Fo+hSc=
-----END CERTIFICATE-----

kubectl get csr david -o jsonpath='{.status.certificate}' | base64 --decode > david.crt

Now we can use this certificate and key. Note that at no time did we send the private key. The private key should only be with the client.

# We are adding a user to our kubeconfig
root@cks-master:~# k config set-credentials david --client-key=david.key --client-certificate=david.crt
User "david" set.

root@cks-master:~# k config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.128.0.5:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: david
user:
client-certificate: /root/david.crt
client-key: /root/david.key
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED

# If we want to omit all certificates as shown by kubernetes-admin
root@cks-master:~# k config set-credentials david --client-key=david.key --client-certificate=david.crt --embed-certs
User "david" set.

root@cks-master:~# k config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.128.0.5:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: david
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED

# To see the filled values
root@cks-master:~# k config view --raw

# Now let's link the user to the cluster through context
root@cks-master:~# k config set-context david --user=david --cluster=kubernetes
Context "david" created.

root@cks-master:~# k config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
david kubernetes david
* kubernetes-admin@kubernetes kubernetes kubernetes-admin

# Let's use this context
root@cks-master:~# k config use-context david
Switched to context "david".

# But user david has no permission for anything
root@cks-master:~# k get ns
Error from server (Forbidden): namespaces is forbidden: User "david" cannot list resource "namespaces" in API group "" at the cluster scope
root@cks-master:~#

If it were user jane, they would have permission for what we configured above.

Do the same process for jane.