ClusterRoleBinding requires namespace - kubernetes

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.

Related

k3s: permissions necessary to access metrics server?

I'd like to grant a service account the ability to access the metrics exposed by the metrics-server service (https://metrics-server.kube-system/metrics). If I create a serviceaccount...
apiVersion: v1
kind: ServiceAccount
metadata:
name: metrics-reader
namespace: prometheus
...and then grant it cluster-admin privileges...
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metrics-reader-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: metrics-reader
namespace: prometheus
...it works! I can use the account token to access the metrics server:
curl -k --header "Authorization: Bearer $token" https://metrics-server.kube-system/metrics
But I don't want to require cluster-admin access just to read
metrics. I tried to use the view cluster role instead of
cluster-admin, but that fails.
Is there an existing role that would grant the appropriate access?
If not, what are the specific permissions necessary to grant read-only
access to the metrics-server /metrics endpoint?
Interesting question. I've found some info for you, however i'm not sure that 100% helpful. It needs more research and reproduce.
check RBAC Deny when requesting metrics. Smth like below?
apiVersion: v1
kind: ServiceAccount
metadata:
name: metrics-reader
namespace: prometheus
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: view-metrics
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: view-metrics
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view-metrics
subjects:
- kind: ServiceAccount
name: metrics-reader
namespace: prometheus
It seems, there is a aggregated-metrics-reader clusterrole (or there was)
Aggregated ClusterRoles are documented in:
https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles.
The purpose of the system:aggregated-metrics-reader ClusterRole, is to
aggregate the rules, that grant permission to get the pod and node
metrics, to the view, edit and admin roles.
however I wasnt able to find any reference to aggregated-metrics-reader clusterrole in current version of that doc.
You can find huge example of using this clusterrole in Metrics server unable to scrape
IN addition check This adds the aggregated-metrics-reader ClusterRole which was missing github PR:
What this PR does / why we need it: This adds the
aggregated-metrics-reader ClusterRole which was missing, and seems to
be required for k8s 1.8+ per the metrics-server documentation and
default deploy manfiests
Unfortunately link in that PR direct to nowhere. I start thinking this obsolete info for 1.8 clusters.. Will update answer in case find anything more relevant

Kubernetes RBAC roles with resourceName and listing objects

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: p-viewer-role
namespace: pepsi
rules:
- apiGroups:
- ""
resourceNames:
- p83
resources:
- pods
verbs:
- list
- get
- watch
When we use resourceNames in the Roles, the following command works
kubectl get pods -n pepsi p83
returns a proper value. However,
kubectl get pods -n pepsi
returns forbidden. Why doesn't it list p83
RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: p-viewer-rolebinding
namespace: pepsi
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: p-viewer-role
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: pepsi-project-viewer
namespace: project
This is expected behavior. You have defined a role which is scoped to the namespace pepsi to pod resources with specific resourceName p83.
For kubectl get pods -n peps command to work you need to remove the resourceNames p83 from the Role
This kind of advanced validation is best handled by OPA where you can define fine grained policies.
Short answer:
list(and watch)actually can be restricted by their resource name, and permits list(and watch) requests using a fieldSelector of metadata.name=... to match a single object (for example, /api/v1/namespaces/$ns/configmaps?fieldSelector=metadata.name=foo)
For more details and some tests you can check this link: https://github.com/kubernetes/website/pull/29468
#sftim and #liggitt do offer a lot of help!

RBAC: roles with multiple namespaces

Trying to write my first set of RBAC roles. So trying to figure out the best way to have 2 roles for multiple namespaced components.
Admin-role (RW for 3 namespaces say default, ns1 & ns2)
user-role (Read-only for 3 namespaces say default, ns1 & ns2)
Was thinking will need a service account with 2 clusterRoles for admin/user
apiVersion: rbac.authorization.k8s.io/v1
kind: ServiceAccount
metadata:
name: sa
namespace: default
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: admin-master
rules:
- apiGroups:
- batch
resources:
- pods
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: user-master
rules:
- apiGroups:
- batch
resources:
- pods
verbs:
- get
- list
- watch
Then make use of roleBindings:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: admin-rw
namespace: ns1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin-master
subjects:
- kind: ServiceAccount
name: sa
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: user-readonly
namespace: ns1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: user-master
subjects:
- kind: ServiceAccount
name: sa
namespace: default
But not sure how the best way to bind roles admin-rw/user-readonly with namespace 2 (ns2)?
Roles are scoped, either bound to an specific namespace or cluster-wide. For namespace-scoped roles, you can just simply deploy the same role in multiple namespaces.
The idea behind this is to have partitioned permissions in the cluster, although it implies more administrative effort but is a safer practice.
Additionally, in your definition, you're trying to bind permissions to specific namespaces, however, you're using ClusterRole which is a cluster-scoped resource. You might want to change that to Role if you want namespace-scoped permissions.
You might find this CNCF article useful on this matter.
This answer https://stackoverflow.com/a/57729174/2660452 is wrong.
ClusterRole and Role defines which resources you can operated. if your role need to manage resources in multiple namespaces, you need to use ClusterRole
and RoleBinding defines which namespace your account will be granted.
here is the example from official document: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-example
A RoleBinding can also reference a ClusterRole to grant the permissions defined in that ClusterRole to resources inside the RoleBinding's namespace. This kind of reference lets you define a set of common roles across your cluster, then reuse them within multiple namespaces.
For instance, even though the following RoleBinding refers to a ClusterRole, "dave" (the subject, case sensitive) will only be able to read Secrets in the "development" namespace, because the RoleBinding's namespace (in its metadata) is "development".
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
# You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
name: read-secrets
#
# The namespace of the RoleBinding determines where the permissions are granted.
# This only grants permissions within the "development" namespace.
namespace: development
subjects:
- kind: User
name: dave # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

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

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.

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