Limit listed Kubernetes namespaces by access

11/27/2019

I have a set of users(dev-team) who need access only to dev and qa namespaces. I created a service account, cluster role and cluster role binding as shown below.

Service Account

apiVersion: v1
kind: ServiceAccount
metadata:
  name: dev-team

Cluster role

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: dev-team-users
rules:
  - apiGroups: ["rbac.authorization.k8s.io",""]
    resources: ["namespaces"]
    resourceNames: ["dev","qa"]
    verbs: ["get","list","create"]

Cluster role binding

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: dev-team-user-bindings
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: dev-team-users
subjects:
- kind: User
  name: dev-team
  namespace: kube-system
  apiGroup: rbac.authorization.k8s.io

When I try to verify the access kubectl get namespaces --as=dev-team

I get the below error message

Error from server (Forbidden): namespaces is forbidden: User "dev-team" cannot list resource "namespaces" in API group "" at the cluster scope

I am expecting to see only dev and qa namespaces to show up. Am I missing something here?

-- Niranjan
kubernetes
rbac

1 Answer

11/27/2019

The list operation fails because you are using the resourceNames field in the ClusterRole to restrict the namespace objects to grant access too but list would return all namespace objects.

But I guess what you really want is to restrict access to the resources in a namespace, and not the namespace objects themselves (which contain not much more information than the name of the namespace).

To achieve this, you have to create Roles (or a ClusterRole) and RoleBindings in those namespaces that you want to grant access to the users.

Here is how you can grant access to all resources for the dev-team user in the dev and qa namespace but deny access to any resources in any other namespace.

Create a ClusterRole (you could also create a Role in the dev and qa namespaces, but using a ClusterRole allows you to define the permissions only once and then reference it from multiple RoleBindings):

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: dev-team-users
rules:
- apiGroups:
    - '*'
  resources:
  - '*'
  verbs:
  - '*'

Create a RoleBinding in both the dev and qa namespaces:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: dev-team-user-bindings
  namespace: dev
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: dev-team-users
subjects:
- kind: User
  name: dev-team
  apiGroup: rbac.authorization.k8s.io
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: dev-team-user-bindings
  namespace: qa
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: dev-team-users
subjects:
- kind: User
  name: dev-team
  apiGroup: rbac.authorization.k8s.io

Test access:

kubectl get pods -n qa --as=dev-team           # Succeeds
kubectl get pods -n dev --as=dev-team          # Succeeds
kubectl get pods -n default --as=dev-team      # Fails
kubectl get pods -n kube-system --as=dev-team  # Fails

See Kubernetes RBAC documentation.

EDIT

1. Identify namespaces a user has created

Can't do this with RBAC. You would need some form of auditing.

2. Identify namespaces a user has access to

Also can't do this easily with RBAC. But you could just iterate through all namespaces and test whether a given user has access:

for n in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
  echo -n "$n: "
  kubectl auth can-i get pods -n "$n" --as=dev-team
done

You can vary the verb/resource part (e.g. get pods) as needed.

-- weibeld
Source: StackOverflow