Rolebinding with ClusterRole is not restricted to namespace when using a ServiceAccount - kubernetes

I want to set a serviceaccount authorizations by associating it to a clusterRole but restricted to a namespace using a rolebinding.
I declared one clusterrole and I configured a rolebinding in a namespace pointing to that clusterrole.
However when I access the cluster with the serviceaccount token defined in the rolebinding I'm not restricted to the namespace.
On the other hand, when I'm accessing the cluster with a "User" certificate, this is working. I have only access to the namespace.
Kubernetes v1.13.5
The Rolebinding I defined:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: exploitant
namespace: myNamespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- kind: ServiceAccount
name: default
namespace: myNamespace
- apiGroup: rbac.authorization.k8s.io
kind: User
name: myUser
This is what I get:
kubectl auth can-i --token=XXXXXXXX get po -n myNamespace
yes
--> as expected
kubectl auth can-i --token=XXXXXXXX get po -n kube-system
yes
--> not expected !!!

The solution is to create a specific ServiceAccount. The "default" serviceAccount should not be used. By default all pods run with the default service account (if you dont specify one). So, the default service account exist in all namespace, so default service account can read pods in all namespace.

Related

Is there a way for K8s service account to create another service account in a different namespace?

I have an app which interacts with an existing service account ("the agent") on a designated namespace. I want the agent to be able to create additional service accounts and roles on other namespaces. Is there a way to do so?
I've already answered to this question in a comment section, but I've also decided to provide more comprehensive information with examples.
Background
Kubernetes includes RBAC (role-based access control) mechanism that enables you to specify which actions are permitted for specific user or group of users. From Kubernetes v1.6 RBAC is enabled by default.
There are four Kubernetes objects: Role, ClusterRole, RoleBinding and ClusterRoleBinding, that we can use to configure needed RBAC rules. Role and RoleBinding are namespaced and ClusterRole and ClusterRoleBinding are cluster scoped resources.
We use Role and RoleBinding to authorize user to namespaced resources and we use ClusterRole and ClusterRoleBinding for cluster wide resources.
However, we can also mix this resurces.
Below I will briefly describe common combinations.
NOTE: It is impossible to link ClusterRoleBindings with Role.
For every test case I created new test namespace and test-agent service account.
Role and RoleBinding
I created simple Role and RoleBinding in specific namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: test
rules:
- apiGroups:
- ""
resources:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: test-role
subjects:
- kind: ServiceAccount
name: test-agent
We can see that test-agent has access only to resources in test namespace:
$ kubectl auth can-i get pod -n test --as=system:serviceaccount:test:test-agent
yes
$ kubectl auth can-i get pod -n default --as=system:serviceaccount:test:test-agent
no
ClusterRole and RoleBinding
I created ClusterRole and RoleBinding:
NOTE: I didn't specify any namespace for ClusterRole.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-clusterrole
rules:
- apiGroups:
- ""
resources:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: test-clusterrole
subjects:
- kind: ServiceAccount
name: test-agent
Now we can see, that if a ClusterRole is linked to a ServiceAccount using a RoleBinding, the ClusterRole permissions apply ONLY to the namespace in which this RoleBinding has been created:
$ kubectl auth can-i get pod -n test --as=system:serviceaccount:test:test-agent
yes
$ kubectl auth can-i get pod -n default --as=system:serviceaccount:test:test-agent
no
ClusterRole and ClusterRoleBinding
Finally I created ClusterRole and ClusterRoleBinding:
NOTE: I didn't specify any namespace for ClusterRole and ClusterRoleBinding.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-clusterrole
rules:
- apiGroups:
- ""
resources:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-clusterrolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: test-clusterrole
subjects:
- kind: ServiceAccount
name: test-agent
namespace: test
Now we can see, that if a ClusterRole is linked to a ServiceAccount using a ClusterRoleBinding, the ClusterRole permissions apply to all namespaces:
$ kubectl auth can-i get pod -n test --as=system:serviceaccount:test:test-agent
yes
$ kubectl auth can-i get pod -n default --as=system:serviceaccount:test:test-agent
yes
$ kubectl auth can-i get pod -n kube-system --as=system:serviceaccount:test:test-agent
yes
Useful note: You can display all possible verbs for specific resource using
kubectl api-resources -o wide, e.g. to display all possible verbs for Deployment we can use:
$ kubectl api-resources -o wide | grep deployment
deployments deploy apps/v1 true Deployment [create delete deletecollection get list patch update watch]

How to give all service accounts in namespace the same cluster role?

I have a group of service accounts in namespace prometheus and I have a cluster role for reading all pods in my cluster. How can I build ClusterRoleBinding to do it?
If you go to K8s docs about Using RBAC Authorization
And scroll down to examples, you can see this one:
For all service accounts in the "qa" namespace:
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
You can now take it and apply to your usecase:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: <some-fancy-name>
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: <clusterrolename>
subjects:
- kind: Group
name: system:serviceaccounts:prometheus
apiGroup: rbac.authorization.k8s.io
There is also one different example worth to notice:
Grant a role to all service accounts in a namespace
If you want all applications in a namespace to have a role, no matter
what service account they use, you can grant a role to the service
account group for that namespace.
For example, grant read-only permission within "my-namespace" to all
service accounts in that namespace:
kubectl create rolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts:my-namespace \
--namespace=my-namespace

how to unbind a role/cluster role from a service account in k8s

For default service account I have creating clusterrolebinding for cluster role=cluster-admin using below kubectl command
kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=rbac-test:default
cluster-admin role is bind to default service account.
How to unbind it again from service account?
When you run your kubectl command it creates the following object:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: add-on-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: default
namespace: rbac-test
You should be able to just delete that object:
kubectl delete clusterrolebinding add-on-cluster-admin

ClusterRoleBinding requires namespace

I have the following:
apiVersion: v1
kind: ServiceAccount
metadata:
name: SomeServiceAccount
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: SomeClusterRole
rules:
- apiGroups:
- "myapi.com"
resources:
- 'myapi-resources'
verbs:
- '*'
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: SomeClusterRoleBinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: SomeClusterRole
subjects:
- kind: ServiceAccount
name: SomeServiceAccount
But it throws:
The ClusterRoleBinding "SomeClusterRoleBinding" is invalid: subjects[0].namespace: Required value
I thought the whole point of "Cluster"RoleBinding is that it's not limited to a single namespace. Anyone can explain this?
Kubernetes version 1.13.12
Kubectl version v1.16.2
Thanks.
You are not required set a namespace while creating a ServiceAccount, the case here is that you are required to specify the namespace of your Service account when you refer to it while creating a ClusterRoleBinding to select it.
ServiceAccounts are namespace scoped subjects, so when you refer to
them, you have to specify the namespace of the service account you
want to bind. Source
In your case you can just use default namespace while creating your ClusterRoleBinding for example.
By doing this you are not tieing your ClusterRoleBinding to any namespace, as you can see in this example.
$ kubectl get clusterrolebinding.rbac.authorization.k8s.io/tiller -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"tiller"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cluster-admin"},"subjects":[{"kind":"ServiceAccount","name":"tiller","namespace":"kube-system"}]}
creationTimestamp: "2019-11-18T13:47:59Z"
name: tiller
resourceVersion: "66715"
selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/tiller
uid: 085ed826-0a0a-11ea-a665-42010a8000f7
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
A kubernetes service account is scoped to a namespace. If you don't specify the namespace while creating the service account, your service account gets created in the 'default' namespace.
This allows you to create service accounts with the same name in different namespaces. i.e. All the namespaces have a service account named "default" when the namespace gets created.
To create service account in a namespace:
kubectl create serviceaccount my-sa -n my-namespace
The namespaces you have to put in the subject here refers to "where the service account is" and not "which namespaces this cluster role binding binds the resource access to".
The cluster-wide aspect of a ClusterRole is that the resources in the rules are cluster-wide. For example, you could use a ClusterRole to give a subject get access to all Pods in all namespaces. With a Role, you could only give a subject get access to Pods in specific namespaces.
The cluster-wide aspect of a ClusterRoleBinding does not apply in any way to the subjects of the binding. In your example, you cannot create a binding for all service accounts with a particular name in all namespaces.
Indeed, you're right, the ClusterRoleBinding should not be tied to a namespace, but
I think the Subject may be tied or not (that's what the error says). You can debug this by checking the Kubernetes API spec for your specific version.
For example here, on the subject's namespace, it says: If the object kind is non-namespace, such as "User" or "Group", and this value is not empty the Authorizer should report an error.

How to provide access to a service account to read pods in multiple namespaces?

I'm going over RBAC in Kubernetes. It appears to me that
a ServiceAccount can be bound to a Role within a namespace
(or)
a ServiceAccount can be bound to a ClusterRole and have cluster-wide access (all namespaces?)
Is it possible for a single Service Account (or User) to not have cluster-wide access but only have read-only access in only a subset of namespaces? If so, can someone elaborate on how this can be achieved. Thanks!
You need to create a RoleBinding for every namespace in each namespace the ServiceAccount should have access to.
There is an example to give the default ServiceAccount permissions to read pods in the development namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets
namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io