RBAC Implementation on k8s

Kubernetes RBAC: Full Access to One Namespace, Read-Only on Others

RBAC Implementation on k8s

Introduction

Kubernetes RBAC (Role-Based Access Control) is a fundamental security feature that allows cluster administrators to control access to resources and actions within a Kubernetes cluster.

In this document, I will demonstrate how to configure RBAC to grant one service account full access to a specific namespace while restricting it to read-only access in other namespaces within a Kubernetes cluster. If you need the source code you can always head over to my github profile

Service Account

The service account name will be the user name in Kubeconfig. Here i am creating the service account in the kube-system namespace, as i am creating a ClusterRole. If you want to create a config to give namespace-level limited access, create the service account in the required namespace.

kubectl -n kube-system create serviceaccount developer

Secret Object for the Service Account

Starting from Kubernetes Version 1.24, the secret for the service account has to be created separately with annotations kubernetes.io/service-account.name and type kubernetes.io/service-account-token. Let's create a secret named devops-cluster-admin-secret with the required annotation and type.

cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: developer
  namespace: kube-system
  annotations:
    kubernetes.io/service-account.name: developer
type: kubernetes.io/service-account-token
EOF

ClusterRole

ClusterRole Definition

A ClusterRole is a Kubernetes resource that defines a set of rules for cluster-wide access control. It specifies what actions are allowed on which resources by whom (subjects). Below is an example of a ClusterRole named developer.

# This yaml file creates only ready access to all namespaces
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: developer
rules:
  # Rule 1: Allow read access to Pods and related resources in all namespaces.
  - apiGroups:
      - ""
    resources:
      - pods
      - pods/log
      - pods/status
      - pods/portforward
      - namespaces
      - services
      - cronjobs
    verbs:
      - get
      - list
      - watch
      - create
      - update

ClusterRole Rules

  • Rule 1: This rule allows the developer to perform actions like get, list, watch, create, and update on various resources such as Pods, Namespaces, Services, and CronJobs in all namespaces.

ClusterRoleBinding

ClusterRoleBinding Definition

A ClusterRoleBinding binds a ClusterRole to a set of subjects (users, groups, or service accounts) and specifies what role they have within the cluster. Here's an example of a ClusterRoleBinding named developer-binding that binds the developer ClusterRole to a ServiceAccount named developer in the kube-system namespace.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: developer-binding
subjects:
  - kind: ServiceAccount
    name: developer
    namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: developer

Subjects

  • The subjects section specifies who is being granted permissions. In this example, it binds the developer ClusterRole to a ServiceAccount named developer in the kube-system namespace.

RoleRef

  • The roleRef section defines which ClusterRole is being bound to the subjects. In this case, it references the developer ClusterRole.

Role and RoleBinding

A Role defines permissions within a specific namespace, and a RoleBinding associates a Role with a user or a service account within that namespace.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev-namespace
  name: developer-admin
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-admin-bind
  namespace: dev-namespace
subjects:
- kind: ServiceAccount
  name: developer
  namespace: kube-system
roleRef:
  kind: Role
  name: developer-admin
  apiGroup: rbac.authorization.k8s.io

In these examples, we have a Role named developer-admin defined in the dev-namespace, allowing full access to all resources in that namespace. The RoleBinding developer-admin-bind associates the developer ServiceAccount in the kube-system namespace with the developer-admin Role, granting it full control over resources in the dev-namespace.


Get all Cluster Details & Secrets

I will retrieve all the required kubeconfig details and save them in variables. Then, finally, I will substitute it directly with the Kubeconfig YAML.

If you have used a different secret name, replace devops-cluster-admin-secret with your secret name,

export SA_SECRET_TOKEN=$(kubectl -n kube-system get secret/developer -o=go-template='{{.data.token}}' | base64 --decode)

export CLUSTER_NAME=$(kubectl config current-context)

export CURRENT_CLUSTER=$(kubectl config view --raw -o=go-template='{{range .contexts}}{{if eq .name "'''${CLUSTER_NAME}'''"}}{{ index .context "cluster" }}{{end}}{{end}}')

export CLUSTER_CA_CERT=$(kubectl config view --raw -o=go-template='{{range .clusters}}{{if eq .name "'''${CURRENT_CLUSTER}'''"}}"{{with index .cluster "certificate-authority-data" }}{{.}}{{end}}"{{ end }}{{ end }}')

export CLUSTER_ENDPOINT=$(kubectl config view --raw -o=go-template='{{range .clusters}}{{if eq .name "'''${CURRENT_CLUSTER}'''"}}{{ .cluster.server }}{{end}}{{ end }}')

Generate the Kubeconfig With the Variables

If you execute the following YAML, all the variables get substituted, and a config named devops-cluster-admin-config gets generated.

cat << EOF > developer-config
apiVersion: v1
kind: Config
current-context: ${CLUSTER_NAME}
contexts:
- name: ${CLUSTER_NAME}
  context:
    cluster: ${CLUSTER_NAME}
    user: devops-cluster-admin
clusters:
- name: ${CLUSTER_NAME}
  cluster:
    certificate-authority-data: ${CLUSTER_CA_CERT}
    server: ${CLUSTER_ENDPOINT}
users:
- name: devops-cluster-admin
  user:
    token: ${SA_SECRET_TOKEN}
EOF

Validate the Generated Kubeconfig

To validate the Kubeconfig, execute it with the kubectl command to see if the cluster is getting authenticated.

kubectl get nodes --kubeconfig=ddeveloper-config

Conclusion

Kubernetes RBAC is a powerful tool for controlling access to resources within a cluster. By defining ClusterRoles and ClusterRoleBindings, you can finely tune the permissions of users, groups, or service accounts, ensuring that they only have access to the resources and actions they need.

Remember that RBAC configurations should be tailored to your specific use case and security requirements. Carefully review and test RBAC policies in a non-production environment before applying them in production to avoid unintended consequences.