# How to Add a New User in Kubernetes with Certificates & RBAC

Kubernetes doesn’t store "users" as API objects. With client certificate authentication, the API server reads the certificate’s Common Name (CN) as the username and each Organization (O) as a group. You grant access using RBAC (Roles/ClusterRoles + Bindings).

There are three steps for **creating a new user in Kubernetes**:

1. Generating a certificate signing request (CSR)
2. Getting the request approved
3. Setting up appropriate RBAC permissions.

Let's walk through this entire process for a new developer added to our team named **"Mary"**.

> **Related:** If you’re creating non-human identities, use **ServiceAccounts** instead of user certs. See my guide: [Kubernetes Service Accounts: Complete Guide for Beginners](/blog/kubernetes-service-accounts-complete-guide-for-beginners/)

## Step 1: Generate a Private Key

First, we need to create a private key for our user in order to create a certificate signing request:

```shell
# Create a private key
openssl genrsa -out mary.key 3072
```

This will generate a new 3072-bit RSA private key and save it (unencrypted, in PEM/PKCS#1 format) to a file named mary.key.

## Step 2: Create an X.509 Certificate Signing Request (CSR)

Next, we'll create a CSR using the private key.

The following command will output a certificate that we will then use in our CertificateSigningRequest Kubernetes resource.

The Common Name (`CN`) represents the username and `O` the group. Adjust as necessary.

```shell
openssl req -new -key mary.key -out mary.csr -subj "/CN=mary/O=developers"
```

## Step 3: Encode the CSR in Base64

Next, let's encode the CSR that we just created in base64 format for use in the CertificateSigningRequest Kubernetes resource we are about to create:

```shell
cat mary.csr | base64 | tr -d "\n"
```

> Here's a [refresher](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#client-certificates) on how the API server authenticates client certificates, if needed.

## Step 4: Create a Kubernetes CSR Resource

Now that we have generated the CSR and encoded it into base64, we are ready to create our CertificateSigningRequest Kubernetes resource.

Create a file named `mary-csr.yaml` with the following content:

```shell
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: mary
spec:
  request: <paste-one-line-base64-here>
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 864000  # 10 days
  usages:
  - client auth
```

Apply this YAML to create the CSR:

```shell
kubectl apply -f mary-csr.yaml
```

## Step 5: Review and Approve the CSR

Check the status of the CSR:

```shell
kubectl get csr
```

Now you can approve the CSR:

```shell
kubectl certificate approve mary
```

## Step 6: Retrieve the Certificate

Get the certificate from the approved CSR:

```shell
kubectl get csr/mary -o yaml
```

Export the issued certificate to a .crt file:

```shell
kubectl get csr mary -o jsonpath='{.status.certificate}'| base64 -d > mary.crt
```

## Step 7: Configure the User in Kubeconfig

Now you or the new user can take all this data and add the new credentials to your/their kubeconfig:

```shell
kubectl config set-credentials mary --client-key=mary.key --client-certificate=mary.crt --embed-certs=true
```

Create a context for Mary:

```shell
kubectl config set-context mary --cluster=kubernetes --user=mary
```

## Step 8: Test the Authentication

Verify that you can authenticate as Mary:

```shell
kubectl --context mary auth whoami
```

You should see output confirming you are "mary".

## Step 9: Create a Role

Now that we've created the user Mary, we want to use RBAC to determine what Mary is authorized to do.

Let's say we don't have a role for her department yet so let's create a role for the developers (which would include her)

Create a role with the necessary permissions:

```shell
kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods
```

> **Note:** Roles are **namespaced**. For cross-namespace access, use a **ClusterRole** and bind it cluster-wide. [Here's an article](/blog/clusterrolebinding-with-service-account-all-namespaces/) I wrote explaining How to Use ClusterRoleBinding With A ServiceAccount in All Namespaces, or see the [Kubernetes documentation]() on the subject.

## Step 10: Create a RoleBinding

And now we can bind this role to Mary via a RoleBinding:

```shell
kubectl create rolebinding developer-binding-mary --role=developer --user=mary
```

## Step 11: Test the Authorization

Now you can test Mary's permissions:

```shell
kubectl --context mary get pods
```

Mary should be able to perform operations on pods as defined in the developer role.

You can also, if you have the right permissions, test her permissions from your own context using:

```shell
kubectl auth can-i list pods --as=mary
```

or

```shell
kubectl auth can-i update pods --as=mary
```

## Additional Tips

1. You can switch contexts to act as Mary:

   ```shell
   kubectl config use-context mary
   ```

2. For more granular permissions, consider using ClusterRoles and namespaced RoleBindings.

3. Remember to secure the private key and certificate files.

4. Consider setting longer expiration times for production environments.

5. Want a hands-on sandbox? Spin up a local cluster on a Raspberry Pi 5 with my guide: [Install Kubernetes on a Raspberry Pi 5](/blog/install-kubernetes-raspberry-pi-5/)

<FAQ
  title="Kubernetes Certificates & RBAC: Frequently Asked Questions"
  faqs={[
    {
      question: 'Does Kubernetes have "User" objects?',
      answer:
        'No. Kubernetes does not store users as API objects. With client certificate auth, the API server reads CN as the username and each O as a group. Authorization is granted via RBAC (Roles/ClusterRoles + Bindings).',
    },
    {
      question: 'How do I map groups from a client certificate?',
      answer:
        'Add one or more O=<group> entries to the certificate subject. Each O value becomes a Kubernetes group (e.g., /CN=mary/O=developers/O=qa).',
    },
    {
      question: 'Should I use Users or ServiceAccounts?',
      answer:
        'Use Users (certs or OIDC) for humans; use ServiceAccounts for workloads running in the cluster. Bind RBAC to the appropriate identity type.',
    },
    {
      question: 'How do I set a default namespace for a user/context?',
      answer:
        'Include a namespace on the context, e.g., `kubectl config set-context mary --namespace=dev --cluster=<cluster> --user=mary`. You can still override with `-n <ns>` per command.',
    },
    {
      question: 'CSR approved but no certificate issued—why?',
      answer:
        'Your cluster may not have a signer for `kubernetes.io/kube-apiserver-client`, or a controller must finalize signing after approval. Check `kubectl get csr mary -o yaml` and ensure `.status.certificate` is populated.',
    },
    {
      question: 'How long should the certificate last?',
      answer:
        'Prefer short-lived certs (e.g., 30–90 days) and rotate regularly. Some signers ignore `spec.expirationSeconds`, so always verify the actual Not After date in the issued cert.',
    },
    {
      question: "How do I revoke a user's access?",
      answer:
        'Remove their RoleBindings/ClusterRoleBindings, rotate or revoke the certificate (and CA if necessary), and remove their kubeconfig credentials. There is no user object to delete.',
    },
    {
      question: 'What is the difference between Role and ClusterRole?',
      answer:
        'Role is namespaced and applies only within a single namespace. ClusterRole is cluster-scoped (or can be referenced by RoleBinding for namespace use) and can grant access across namespaces when bound with a ClusterRoleBinding.',
    },
    {
      question: 'Can I use OIDC instead of client certificates?',
      answer:
        'Yes. Many orgs prefer OIDC (IdP/SSO + MFA) for human users. Configure the API server for OIDC and map IdP claims to groups, then use RBAC as usual.',
    },
    {
      question: 'How can I verify what identity Kubernetes sees?',
      answer:
        'Run `kubectl --context mary auth whoami` to print the username and groups from your current credentials.',
    },
  ]}
/>