The documentation says,
If you want to define a role within a namespace, use a Role; if you want to define a role cluster-wide, use a ClusterRole.
So, why am I able to create a ClusterRole in a namespace for a non-namespaced resource StorageClass (or, sc in short)?
kubectl -n apps create clusterrole scrole --verb=create,update,patch,delete --resource=sc
Also, is it correct to say that, a Role is applicable for namespaced resources only and ClusterRole for non-namespaced resources only?
The namespace parameter is redundant and not used even if you provide it while creating a ClusterRole.
A ClusterRole can define permission to namespace scoped resources as well and you can use a RoleBinding to assign the permission to a user or group or service account. When you do that it's basically providing permission to the resources within the namespace where the RoleBinding is created.This is to avoid creating duplicate Roles in every namespace to provide the same permission.
Also when you have cluster scoped resources in a ClusterRole you need to use a ClusterRoleBinding to assign the permission to a a user or group or service account.
Related
I'm going to have an unknown number of users access my K8s (specifically OpenShift if that helps) cluster. Each user will have their own random namespace. So I do not know the namespaces in advance as they will be dynamically created. But I want each user to be able to utilize a ServiceAccount that I create ahead of time.
So, if I create a ServiceAccount fooSA in my namespace foo, I'd like to be able to define a deployment that utilizes fooSA from the bar namespace. For example:
myapp.yaml
...
spec:
serviceAccount: fooSA
...
kubectl apply -f myapp.yaml -n bar
How can I accomplish this?
As ServiceAccounts are namespace scoped I cannot figure out a way to accomplish this.
I want to create a user that has permission to create temporary namespaces (i.e. create and then delete the namespaces) and have full access within these namespaces only, and without being able to delete any other namespaces within the cluster. My problem is that the namespaces in this case are created dynamically by the user with a random name each time...is there any way to meet this requirement for a user to:
Create namespace (with a random name that is only known after execution)
Have full access to this name space only
Able to delete this namespace only
You can first restrict user to create/delete resources only in the namespace using a Role bind that role to the user.
Then you can use ClusterRole with only access to the namespaces resource and allow it to create, delete, etc.
ClusterRole and Role define which resources you can operate on. If your role needs to manage resources in multiple namespaces, you need to use ClusterRole
and RoleBinding defines which namespace your account will be granted
Example:
Create a Role in the namespace that can be used to grant access to resources.
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: namespace1
name: user-namespace-role
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "pods"] # etc...
verbs: ["get", "list", "create",”delete”] # etc
Then execute the below command which creates rolebinding that defines which namespace your account will be granted.
$ kubectl create rolebinding user-namespace-binding --role=user-namespace-role --user=<user-name> --namespace=namespace1
Now Create a ClusterRole that can be used to grant access in any particular namespace, or across all namespaces
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cluster-role-all-namespaces
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # etc
Then Execute the below command to create clusterrolebinding:
$ kubectl create clusterrolebinding all-namespaces-binding --clusterrole=cluster-role-all-namespaces --user=<username>
Refer to Using RBAC authorization for more information.
On my understanding there is no way to accomplish this kind of permissions - I know it's surprising because it would seem like a common use case. Using Roles, the rules only apply to the namespace the role belongs to, using an appropriate RoleBinding. Therefore we can limit actions on specific namespaces, but we cannot define a permission on a namespace with unknown name. Also using regex is not supported to match namespaces names. To solve it with Roles, we would have to apply the role every time a new namespace is created, I think makes no sense for the use case.
As you may know Kubernetes also defines cluster roles and cluster role bindings. Those are similar to normal roles but without a namespace limitation. Of course, using them in this case can break through the isolation we want, that's what they are meant to do.
What I suggest is to predefine a list of namespaces for which those accounts will have permissions. That means you need to create/use the same namespaces and to not generate them dinamically with random names. It also means that it will not be able to create new namespaces.
Lastly, I wanted to mention Hierarchical Namespaces. Under HNS, administrators can organize tenants according to a group hierarchy and allocate capabilities accordingly.
Is it somehow possible to seperately allow patching of resources' metadata through a role in a Kubernetes cluster?
I would like to solely allow patching of namespace's metadata without giving write permissions to the whole namespace object.
The usecase is to allow deployment pipelines to add/change annotations to the namespace without giving them full control.
To add/change namespace's metadata without giving write permissions to the whole namespace object, you can create a RBAC role where you can restrict access to namespace resources. So that deployment pipeline can have access to change only the metadata i.e., annotations to the namespace without giving them full control.
An RBAC Role contains rules that represent a set of permissions. Permissions are purely additive (there are no "deny" rules).
A Role always sets permissions within a particular namespace; when you create a Role, you have to specify the namespace it belongs in.
Let us consider an example Role in the namespace that can be used to grant read access to resources pods and services:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: <namespace-name>
name: read-access
rules:
- apiGroups: [""]
resources: ["pods", “services”]
verbs: ["get", "watch", "list"]
To grant read access to all the resources which are mentioned in the namespace, use this special character “*” in the resources field i.e., resources: ["*”].
Note : If you want to restrict resources to a specific user you can use Rolebinding. A role binding grants the permissions defined in a role to a user or set of users. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted. A RoleBinding grants permissions within a specific namespace
Refer RBAC Role for more information.
There's something I don't quite understand in the way RBAC works in Kubernetes.
I'll state what I understood and what not. Based on the documentation, the RBAC API defines 4 kinds of kubernetes objects:
Role
ClusterRole
RoleBinding
ClusterRoleBinding
Role
A Role defines a set of permissions within a specific namespace. The Role definition contains a namepsace field, and the Role object is created within that namespace. From the docs:
A Role always sets permissions within a particular namespace; when you create a Role, you have to specify the namespace it belongs in.
I suppose that this means that all the rules defined in the Role applies only to the objects that are in that namespace. I'll continue supposing this assumption is true, please correct me otherwise.
ClusterRole
ClusterRole, by contrast, is a non-namespaced resource.
From what I understand (again, correct me if I'm wrong) a ClusterRole is used to define rules that define permissions regarding to resources that are not bound to any namespace, such as nodes.
RoleBinding
A RoleBinding object is a namespaced object. Its function is to bind Roles to subjects, i.e. grant subjects (users, ServiceAccounts, groups) with specific Role. It can also bind subjects with ClusterRoles.
ClusterRoleBinding
Not so much of my interest for the manner of this post.
The Question
My questions is, why is there a namespace metadata bit in the RoleBinding definition? If indeed as I assumed in the Role section, a Role grants permissions to objects only in the specified namespace of that Role, then that restriction is already defined in the Role object itself, why is it again defined in the RoleBinding object?
As I'm writing these lines I suddenly think of an optional answer to that question, please tell me if this is correct:
A RoleBinding can also bind a ClusterRole to a list of subjects, and the permissions defined in that ClusterRole will apply only to resources in the namespace specified in the RoleBinding object. That is why we need a namespace bit in the RoleBinding definition. Indeed it is not necessary when we use a RoleBinding to bind a Role rather than a ClusterRole.
Is that correct?
It is as you said. A RoleBinding needs the namespace specified, because it can also reference a ClusterRole which is not namespaced. So a ClusterRole can be seen (in some cases) as a template for a Role in a specific namespace.
The ClusterRole edit is a good example for this usecase: you would reference this ClusterRole (not namespaced) in your RoleBinding (namespaced):
apiVersion: rbac.authorization.k8s.io/v1namespace.
kind: RoleBinding
metadata:
name: editor
namespace: my-namespace
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
So the user jane would get the permissions defined in the ClusterRole edit but only in the namespace my-namespace.
I am looking for option to have serviceaccount (which is not cluster admins) to be able to create new namespace and automatically get admin permission on it (while all system namespaces are not editable by this serviceaccount).
Currently my serviceaccount binded to clusterrole contains
- apiGroups:
- ""
resources:
- namespaces
verbs:
- create
However it can't do anything on namespace it creates.
Would like to get any suggestions, recommendations.
Unfortunately, it is not possible to do using RBAC objects only.
In the RBAC API, a role contains rules that represent a set of
permissions. Permissions are purely additive (there are no “deny”
rules).
However there is a possible workaround:
you add a pod with Kubernetes python/go/java client inside, using service account with create-Roles+RoleBindings-permissions on a cluster level
then you run a simple code that monitor api-server for new namespaces and create RoleBinding for the namespace-admin in the new namespace
this RoleBinding refers to cluster-admin role, which gives the user all permission in the specific namespace
to differentiate new namespaces from existing ones, the script can also put a label on the namespace: namespace-admin=true or similar.
Also, you could consider using RBAC Manager. Dynamic Namespaces and Labels to be more specific.
RBAC Definitions can now include namespaceSelectors in place of
namespace attributes when specifying Role Binding configuration. This
can be incredibly helpful when working with dynamically provisioned
namespaces.
Please let me know if that helped.