Steps to Set Up X509 Certificate Authentication

  mkdir newusercrt
cd newusercrt 
openssl genrsa --out sangam.key 2048
openssl req -new -key sangam.key -out sangam.csr -subj "/CN=sangam/O=group1"
  

This creates a private key (sangam.key) and a CSR (sangam.csr). The CN (Common Name) is set to the user’s name, and O (Organization) is an optional field to specify a group.

Create a CertificateSigningRequest in Kubernetes

Encode the CSR in base64 and create a YAML file for the Kubernetes CSR object:

  cat sangam.csr | base64 | tr -d '\n'
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1p6Q0NBVThDQVFBd0lqRVBNQTBHQTFVRUF3d0djMkZ1WjJGdE1ROHdEUVlEVlFRS0RBWm5jbTkxY0RFdwpnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDelJOOHNFYWNkcmsxdVlPTndNejRaCjVqUUYwUTBNNnBqTk9GTVQxM3JMVXV1NzBzMkNhR1lVUEV4bk52Q01kOTk0cTU3bUc0Y3Z6Ny96VTdpcVFRQ3UKcjc5b0xCVEk5YjlPT0EzZXF2TC9uenZrbGxqUGpCcUFuZitYOGRPdEx4ZTJOYnlja1cyamNHOThKdSsvaVR4YgpiWkVHaXZDeHVXQmNiMktnRHRuczYyZHhxWi8vdU9NVW1nK0J3ZFBBbkx0dUl3enR3ZzYzZlNrMHNSSCt3VGwzCjB3ZFVSblJWU1QzaDE4ZXI4ejBHS3g5RFBZSlBjRzJFT2FUTU5uaklUUUoyRzkrNWdDMFBBa1V1SGJNdjQ4NXQKN3U5alZJT09SUVB6bHd5VHdwQndtV0NjR3ZwNnNKNEtzNmRicWVvc2lHem1KbnZ3QjJxejYzZm5ubmI5aElaMwpBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFSZ1FHVU13TDFZRmhlZHhNOE9HUHY4ODJ6SEpPCjRRd1IzaW8ySXUyZG9Dc3hGL2RhNTV4K0VNQlBwN1Y5UXhHM2tyTitDNDgyOUdrcTh1WHk1MVJENjNMeWNkM20KdGVHQkZVMEZXeTVUYmVzTjJoMVdEQlMySDYrUmtEelI1dHZzclo3dnlZb2crbDQrckxVRFJNM2t4UWZ3WkExdQoyOTdTSWhQUllqSjJXd2xZeU9mMUJhUDRpa1NtT1JkaVZ5OWNKOGFKZDBjQkFBQ3JxVlppTGRtSTNlT3g4bUtnCklwL3lJRzN5K2hhNTFXQUVWdGdtdllPRVphMVRqZFhsWFRMc3VZNzNwdGJyTFBJYldUVVozdytBcHJwWjVCc3QKWXd3Z2F2NTROQmd1TzVKMTlRL3hlK1RBZXRDdTBVdmN6aHhLUVVFT0ZnMHZSREVNNUgzaG1yYll6QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=%  
  

sangam-csr.yaml with following content

cat «EOF | kubectl apply -f - apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: sangam spec: groups:

  • system:authenticated request: $(cat sangam.csr | base64 | tr -d “\n”) signerName: kubernetes.io/kube-apiserver-client usages:
  • client auth EOF

output

  cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: sangam
spec:
  groups:
  - system:authenticated
  request: $(cat sangam.csr | base64 | tr -d "\n")
  signerName: kubernetes.io/kube-apiserver-client
  usages:
  - client auth
EOF
certificatesigningrequest.certificates.k8s.io/sangam created
  

check csr with kubectl

  ➜  newusercrt git:(main) ✗ kubectl get csr
NAME     AGE   SIGNERNAME                            REQUESTOR       REQUESTEDDURATION   CONDITION
sangam   57s   kubernetes.io/kube-apiserver-client   minikube-user   <none>              Pending
  

Approve the CSR in Kubernetes

List CSRs and approve yours:

    newusercrt git:(main) ✗ kubectl certificate approve sangam
certificatesigningrequest.certificates.k8s.io/sangam approved
  

Retrieve the Signed Certificate

Once approved, retrieve the signed certificate from the CSR:

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

Set up kubectl for the User

Configure kubectl to use the certificate:

   kubectl config set-credentials sangam --client-certificate=sangam.crt --client-key=sangam.key
kubectl config set-context sangam --cluster=minikube --user=sangam
User "sangam" set.
Context "sangam" created.
  

Now it is time to create context so that the new user can use the cluster. I will name the context as sangam-context. You can name differently as you wish.

   kubectl config set-context sangam-context --cluster=minikube --user=sangam

Context "sangam-context" created.
  

Test the Configuration

Switch to the new context and test:

  kubectl config use-context sangam-context
 kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "sangam" cannot list resource "nodes" in API group "" at the cluster scope
  

pod-reader-role.yaml

  kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  

readpods-rolebinding.yaml

  kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: "sangam"
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
  
   kubectl config use-context minikube
 kubectl apply -f pod-reader-role.yaml
kubectl apply -f readpods-rolebinding.yaml
role.rbac.authorization.k8s.io/pod-reader created
rolebinding.rbac.authorization.k8s.io/read-pods created
  

run test ngnix pod

   kubectl run test2 --image=nginx
pod/test2 created
kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
test2   1/1     Running   0          49s


kubectl config use-context sangam-context
Switched to context "sangam-context".

 kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
test2   1/1     Running   0          2m1s


kubectl run test3 --image=nginx
Error from server (Forbidden): pods is forbidden: User "sangam" cannot create resource "pods" in API group "" in the namespace "default"


you would have more robust systems for managing certificates.
The kubectl commands assume that Minikube is your current context and you have the necessary permissions to perform these actions.
The certificate signing process in a real-world scenario might involve additional steps or approvals, depending on the organization's policies.
  

Learn more around Role Based Access Control (RBAC)

Role-Based Access Control (RBAC) in Kubernetes is a method of regulating access to computer or network resources based on the roles of individual users within an enterprise. In the context of Kubernetes, RBAC allows you to control who has access to the Kubernetes API and what they can do with those resources

  • Rules: A rule is a set of operations (verbs) that can be carried out on a group of resources which belong to different API Groups.
kubectl explain role.rules
  kubectl explain role.rules     
GROUP:      rbac.authorization.k8s.io
KIND:       Role
VERSION:    v1

FIELD: rules <[]PolicyRule>

DESCRIPTION:
    Rules holds all the PolicyRules for this Role
    PolicyRule holds information that describes a policy rule, but does not
    contain information about who the rule applies to or which namespace the
    rule applies to.
    
FIELDS:
  apiGroups     <[]string>
    APIGroups is the name of the APIGroup that contains the resources.  If
    multiple API groups are specified, any action requested against one of the
    enumerated resources in any API group will be allowed. "" represents the
    core API group and "*" represents all API groups.

  nonResourceURLs       <[]string>
    NonResourceURLs is a set of partial urls that a user should have access to.
    *s are allowed, but only as the full, final step in the path Since
    non-resource URLs are not namespaced, this field is only applicable for
    ClusterRoles referenced from a ClusterRoleBinding. Rules can either apply to
    API resources (such as "pods" or "secrets") or non-resource URL paths (such
    as "/api"),  but not both.

  resourceNames <[]string>
    ResourceNames is an optional white list of names that the rule applies to.
    An empty set means that everything is allowed.

  resources     <[]string>
    Resources is a list of resources this rule applies to. '*' represents all
    resources.

  verbs <[]string> -required-
    Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in
    this rule. '*' represents all verbs.
  
  • Roles and ClusterRoles: Both consist of rules. The difference between a Role and a ClusterRole is the scope: in a Role, the rules are applicable to a single namespace, whereas a ClusterRole is cluster-wide, so the rules are applicable to more than one namespace. ClusterRoles can define rules for cluster-scoped resources (such as nodes) as well. Both Roles and ClusterRoles are mapped as API Resources inside our cluster.
kubectl explain role
  kubernetesdaily.github.io git:(main) ✗ kubectl explain role      
GROUP:      rbac.authorization.k8s.io
KIND:       Role
VERSION:    v1

DESCRIPTION:
    Role is a namespaced, logical grouping of PolicyRules that can be referenced
    as a unit by a RoleBinding.
    
FIELDS:
  apiVersion    <string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind  <string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata      <ObjectMeta>
    Standard object's metadata.

  rules <[]PolicyRule>
    Rules holds all the PolicyRules for this Role
  
kubectl explain clusterroles
  kubernetesdaily.github.io git:(main) ✗ kubectl explain clusterroles
GROUP:      rbac.authorization.k8s.io
KIND:       ClusterRole
VERSION:    v1

DESCRIPTION:
    ClusterRole is a cluster level, logical grouping of PolicyRules that can be
    referenced as a unit by a RoleBinding or ClusterRoleBinding.
    
FIELDS:
  aggregationRule       <AggregationRule>
    AggregationRule is an optional field that describes how to build the Rules
    for this ClusterRole. If AggregationRule is set, then the Rules are
    controller managed and direct changes to Rules will be stomped by the
    controller.

  apiVersion    <string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind  <string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata      <ObjectMeta>
    Standard object's metadata.

  rules <[]PolicyRule>
    Rules holds all the PolicyRules for this ClusterRole
  
  • Subjects: These correspond to the entity that attempts an operation in the cluster. There are three types of subjects:

  • User Accounts: These are global, and meant for humans or processes living outside the cluster. There is no associated resource API Object in the Kubernetes cluster.

  • Service Accounts: This kind of account is namespaced and meant for intra-cluster processes running inside pods, which want to authenticate against the API.

  • Groups: This is used for referring to multiple accounts. There are some groups created by default such as cluster-admin (explained in later sections).

  • RoleBindings and ClusterRoleBindings: Just as the names imply, these bind subjects to roles (i.e. the operations a given user can perform). As for Roles and ClusterRoles, the difference lies in the scope: a RoleBinding will make the rules effective inside a namespace, whereas a ClusterRoleBinding will make the rules effective in all namespaces.

kubectl explain rolebinding

      ✗ kubectl explain rolebindings
GROUP:      rbac.authorization.k8s.io
KIND:       RoleBinding
VERSION:    v1

DESCRIPTION:
    RoleBinding references a role, but does not contain it.  It can reference a
    Role in the same namespace or a ClusterRole in the global namespace. It adds
    who information via Subjects and namespace information by which namespace it
    exists in.  RoleBindings in a given namespace only have effect in that
    namespace.
    
FIELDS:
  apiVersion    <string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind  <string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata      <ObjectMeta>
    Standard object's metadata.

  roleRef       <RoleRef> -required-
    RoleRef can reference a Role in the current namespace or a ClusterRole in
    the global namespace. If the RoleRef cannot be resolved, the Authorizer must
    return an error. This field is immutable.

  subjects      <[]Subject>
    Subjects holds references to the objects the role applies to.
  

kubectl explain clusterrolebindings

  kubectl explain clusterrolebindings
GROUP:      rbac.authorization.k8s.io
KIND:       ClusterRoleBinding
VERSION:    v1

DESCRIPTION:
    ClusterRoleBinding references a ClusterRole, but not contain it.  It can
    reference a ClusterRole in the global namespace, and adds who information
    via Subject.
    
FIELDS:
  apiVersion    <string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind  <string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata      <ObjectMeta>
    Standard object's metadata.

  roleRef       <RoleRef> -required-
    RoleRef can only reference a ClusterRole in the global namespace. If the
    RoleRef cannot be resolved, the Authorizer must return an error. This field
    is immutable.

  subjects      <[]Subject>
    Subjects holds references to the objects the role applies to.
  

Start Minikube with RBAC enabled:

  ➜  kubernetesdaily.github.io git:(main) ✗ minikube start --extra-config=apiserver.authorization-mode=RBAC

😄  minikube v1.32.0 on Darwin 14.2 (arm64)
✨  Using the docker driver based on existing profile
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
🔄  Restarting existing docker container for "minikube" ...
🐳  Preparing Kubernetes v1.28.3 on Docker 24.0.7 ...
    ▪ apiserver.authorization-mode=RBAC
🔗  Configuring bridge CNI (Container Networking Interface) ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
  

create new namespace

  kubernetesdaily.github.io git:(main) ✗ kubectl create namespace rbacminikube
namespace/rbacminikube created
  

Define a Role (nginx-role.yaml) that allows managing NGINX resources (pods and services) within the “rbacminikube” namespace:

create new namespaces with name developement & qa

  ➜  k8s git:(main) ✗ kubectl create namespace development
kubectl create namespace qa
namespace/development created
namespace/qa created
  

Why Create Service Accounts?

  • Process Identity: Service accounts provide an identity for processes that run in pods, enabling Kubernetes to apply RBAC rules to these processes.

  • Scoped Access Control: By associating a service account with certain RBAC roles, you can control what actions the processes running under this account can perform in the Kubernetes cluster.

  • Security Best Practices: Using distinct service accounts for different teams or applications is a security best practice. It prevents privilege escalation and limits the impact if a service account is compromised.

dev-service-account.yaml

  apiVersion: v1
kind: ServiceAccount
metadata:
  name: dev-team-sa
  namespace: development
  

qa-service-account.yaml

  apiVersion: v1
kind: ServiceAccount
metadata:
  name: qa-team-sa
  namespace: qa
  

admin-service-account.yaml

  apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-team-sa
  namespace: default  # or a specific admin namespace
  

apply all service account

  kubectl apply -f dev-service-account.yaml
kubectl apply -f qa-service-account.yaml
kubectl apply -f admin-service-account.yaml
  

define role and Rolebindings

developer role

Permissions to manage pods in the development namespace.

  apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: development-role
  namespace: development
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch", "create", "delete"]
  
  k8s git:(main) ✗ kubectl apply -f development-role.yaml 
role.rbac.authorization.k8s.io/development-role created
  

read-only access to all resources in the qa namespace.

qa-role.yaml

  apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: qa-role
  namespace: qa
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["get", "list", "watch"]
  
  k8s git:(main) ✗ kubectl apply -f qa-role.yaml
role.rbac.authorization.k8s.io/qa-role created
  

Admin Team ClusterRole (admin-clusterrole.yaml): Read access to all resources cluster-wide.

  apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: admin-clusterrole
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["get", "list", "watch"]
  
  kubectl apply -f admin-clusterrole.yaml
clusterrole.rbac.authorization.k8s.io/admin-clusterrole created
  

ngnix deploymemt

  apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: development
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      serviceAccountName: dev-team-sa
      containers:
      - name: nginx
        image: nginx
  
  ➜  k8s git:(main) ✗ kubectl apply -f nginx-deployment.yaml.yaml                                              

deployment.apps/nginx-deployment created
➜  k8s git:(main) ✗ kubectl get deployments -n development
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   1/1     1            1           31s


#### Check out put 


 minikube service nginx-service -n development
|-------------|---------------|-------------|---------------------------|
|  NAMESPACE  |     NAME      | TARGET PORT |            URL            |
|-------------|---------------|-------------|---------------------------|
| development | nginx-service |          80 | http://192.168.49.2:31744 |
|-------------|---------------|-------------|---------------------------|
🏃  Starting tunnel for service nginx-service.
|-------------|---------------|-------------|------------------------|
|  NAMESPACE  |     NAME      | TARGET PORT |          URL           |
|-------------|---------------|-------------|------------------------|
| development | nginx-service |             | http://127.0.0.1:50198 |
|-------------|---------------|-------------|------------------------|
🎉  Opening service development/nginx-service in default browser...
❗  Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
  

can qa role able to access it no

  kubectl auth can-i get deployments --as=system:serviceaccount:qa:qa-role -n development
no
  

Last updated 24 Feb 2024, 10:56 +0530 . history