Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance "resourceNames" field's capability in RBAC Roles to give permissions to all instances of a resource matching some pattern #56582

Closed
mssachan opened this issue Nov 29, 2017 · 38 comments
Assignees
Labels
kind/feature Categorizes issue or PR as related to a new feature. sig/auth Categorizes an issue or PR as relevant to SIG Auth.

Comments

@mssachan
Copy link

mssachan commented Nov 29, 2017

Is this a BUG REPORT or FEATURE REQUEST?:

Uncomment only one, leave it on its own line:

/kind bug

/kind feature

What happened:
Currently, we are using resourceNames field in RBAC roles to allow permissions for a particular instance of any resource(like pods, secrets. etc) like below

rules:
- apiGroups: [""]
  resources: ["pods"]
  resourceNames: ["my-pod"]
  verbs: ["get"]

But consider a situation where we create a deploymentwith name say "my-deployment" and now we want to give permissions to check logs of pod(created by this deployment). Pods created by deployment will have name like my-deployment-xxxxx-xxxx.
So, We can add resourceNames: ["my-deployment-xxxxx-xxxx"] in role which will give permissions only for pod with name my-deployment-xxxxx-xxxx.
But if this pod get deleted, then deployment will create new pod with name say my-deployment-yyyyy-yyyy. So, now we have to update existing role with resourceNames: ["my-deployment-yyyyy-yyyy"] to give permissions for new pod my-deployment-yyyyy-yyyy.

What you expected to happen:
resourceNames field in RBAC role should be enhanced to give permissions to all instances of a resource matching some pattern.
For example, if we define resourceNames: ["my-deployment"] in role, then user should be given access to all instances of a resource which contains string "my-deployment" in instance name.

How to reproduce it (as minimally and precisely as possible):

Environment:

  • Kubernetes version (use kubectl version): GitVersion:"v1.8.2-2+d68ca389c3219c"
  • Cloud provider or hardware configuration:
  • OS (e.g. from /etc/os-release):
  • Kernel (e.g. uname -a):
  • Install tools:
  • Others:
@k8s-ci-robot k8s-ci-robot added the kind/feature Categorizes issue or PR as related to a new feature. label Nov 29, 2017
@k8s-github-robot k8s-github-robot added the needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. label Nov 29, 2017
@mssachan
Copy link
Author

/sig rbac

@liggitt
Copy link
Member

liggitt commented Nov 29, 2017

@kubernetes/sig-auth-feature-requests

@k8s-ci-robot k8s-ci-robot added the sig/auth Categorizes an issue or PR as relevant to SIG Auth. label Nov 29, 2017
@k8s-github-robot k8s-github-robot removed the needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. label Nov 29, 2017
@dixudx
Copy link
Member

dixudx commented Nov 30, 2017

/assign

@mikedanese
Copy link
Member

Subdividing namespaces is not trivial. The current advice is to use different namespaces. Are you primarily concerned with dividing access between users or service accounts?

@mssachan
Copy link
Author

@mikedanese It has nothing to do with subdividing namespaces. Also, this feature request is neither specific to users nor service accounts.

@dixudx @liggitt
Actually my requirement is to have a Role which gives permissions to a user to check logs of pod which are created by some deployment and even if pod gets deleted and new pod gets created by deployment, then admin should not have need to update existing role.

But with the current RBAC features, we can define role like below to check logs of a pod created by some deployment:

rules:
- apiGroups: [""]
  resources: ["pods"]
  resourceNames: ["my-pod-xxxx"]
  verbs: ["get"]

But when that pod gets deleted, then deployment will create new pod and admin has to update existing role to give user permission for checking logs of new pod created by deployment.

Note: I think current way is not feasible as admin has to continuously monitor when pod created by deployment got deleted and new pod got created and then admin need to update existing role accordingly each time.
So, I feel resourceNames field in RBAC role should be enhanced to give permissions to all instances of a resource matching some pattern as mentioned in description section of issue.

@liggitt
Copy link
Member

liggitt commented Dec 28, 2017

Subdividing access on name prefix isn't a strong subdivision. Permissions that allowed access to a pods for a deployment named "my" would also allow access to pods for a deployment named "my-app"

@mssachan
Copy link
Author

@liggitt Agree.
Do you think is there any other good way to satisfy my requirement given in issue description??

@liggitt
Copy link
Member

liggitt commented Dec 30, 2017

Not really. I think attempts to subdivide namespaces ("access to logs of pods from only some deployments", etc) like this are likely to be both complex and fragile. I'd echo what @mikedanese said.

@liggitt liggitt closed this as completed Jan 4, 2018
@phemmer
Copy link

phemmer commented Mar 13, 2018

I'm also in the same boat of needing this feature. Our situation is that we have a "production" namespace, a "staging" namespace, etc, of which all our various applications are deployed to. We want to grant each application owner access to their own resources, but since names of things like pods are auto-generated, we can't without granting access to the whole namespace.

The nonResourceURLs attribute already supports this by way of adding a trailing * to the value.

@dedsm
Copy link

dedsm commented Mar 14, 2018

I have a similar request, it would make rbac really powerful if you can specify a regex in the resourceNames to match, I deploy the whole infrastructure in feature branches in my development cluster into new namespaces with a prefix per user, it would be nice to be able to say something like

- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  resourceNames: ["userA-*"]

to allow that user to manage any namespace as long as they start with "userA-"

@ericchiang
Copy link
Contributor

We want to grant each application owner access to their own resources, but since names of things like pods are auto-generated, we can't without granting access to the whole namespace.

There are more issues than just RBAC here. For example if I have the ability to create a pod, I can mount any secret or service account token from a namespace into that pod, even if RBAC prevents me from getting that secret. That's part of why Mike Danese said earlier that "Subdividing namespaces is not trivial." Even if RBAC was more expressive, the security boundary is still the namespace.

to allow that user to manage any namespace as long as they start with "userA-"

The API server doesn't support returning filtered lists based on authorization. If a user lists or watches all namespaces what would they see? Again, adding features to RBAC doesn't change that limitation.

For those following this thread, treat namespaces as the security boundary. Trying to carve up an individual namespace has a lot of nuanced pitfalls.

@liggitt
Copy link
Member

liggitt commented Mar 14, 2018

I would add that prefix matching without a delimiter that cannot appear in the value is generally a bad idea. Letting user bob manage all namespaces that match bob-* sounds great until user bob-tables shows up

@zegl
Copy link
Contributor

zegl commented Jul 3, 2018

I also have a use case where this feature would be useful. I want to install cert-manager, while granting it as little access as possible to our cluster.

cert-manager needs get/create/list access to secrets in all namespaces (or all namespaces that it creates certificates for). This is not optimal as no application should have that much power. My idea is instead to only allow get/create/list access to secrets following the "tls-*" pattern, but sadly that's not possible at the moment.

Please reconsider this feature.

@whereisaaron
Copy link

whereisaaron commented Aug 7, 2018

The current RBAC is pretty limited in this regard. The resourceNames attribute is IMHO almost without a use case, since it can't name/identify any workload, not Deployments, StatefulSets, nor Jobs, as Pod names and quantities are dynamic at runtime.

I agree that a pattern match on the names is not the best model either, for the reasons others have expressed above.

I suggest RBAC could take a leaf from NetworkPolicy and support a label selector to scope Roles and Cluster roles. I think that gives a clean, intensional match that is consistent with the Kubernetes model for subdividing resources.

It also combines consistently with the resources selector, to allow e.g. access to list/describe both Pods and Deployments (but not Secrets) that have the required labels.

@liggitt
Copy link
Member

liggitt commented Aug 7, 2018

The resourceNames attribute is IMHO almost without a use case, since it can't name/identify any workload, not Deployments, StatefulSets, nor Jobs, as Pod names and quantities are dynamic at runtime.

It is currently used for bounding permissions to specific leader lock resources, and read access to specific secrets/configmaps.

I suggest RBAC could take a leaf from NetworkPolicy and support a label selector to scope Roles and Cluster roles. I think that gives a clean, intensional match that is consistent with the Kubernetes model for subdividing resources.

See #44703 (comment) for a discussion of the issues with label selector support in RBAC.

@whereisaaron
Copy link

Label selectors for RBAC have been proposed before. And while not rejected as a concept, the implementation requires several breaking changes under the hood, so probably punted to RBAC v2 😐

#44703

Looks like that although resourceNames is not very useful, but it was something that could be easily added to the current implementation of admission controllers.

We've coded ourselves into a corner here sadly 😥

@Zatvobor
Copy link

Zatvobor commented Aug 5, 2019

@mssachan
I've moved some Deployments toStatefulSets, so it can be managed/described over resourceNames.

@liggitt
Please reconsider the solution for managing pod names.
For example:

# a unique identity of StatefulSet, DaemonSet... pods
resourceNames: [["foo", "*"]]
# a unique identity of ReplicaSet based pods
resourceNames: [["foo", "*", "*"]]

@2rs2ts
Copy link
Contributor

2rs2ts commented Oct 23, 2019

Another use case: the Kubernetes Service Catalog. It makes secrets based on ServiceBinding names (from what I understand) and we don't want to give it the ability to CRUD all secrets in whatever Namespace is using the Service Catalog to create things with the AWS Service Broker. If we could restrict the secrets it could manipulate to specific names we could avoid giving it an escalation path to get ServiceAccount tokens.

@2rs2ts
Copy link
Contributor

2rs2ts commented Oct 23, 2019

By the way, "fragile" is better than "broken" which is what the current system that requires you to give way too broad access is :)

@cameronkerrnz
Copy link

I've been looking at how to configure similar restrictions. In my use-case, I have a pod that is running shinyproxy (has backends for Docker Engine, Docker Swarm or Kubernetes); this pod will talk to the Kubernetes API to create and delete pods that run shiny-server; each with a slightly different configuration (it starts one pod for each user and shuts down the pod on logout or after some period).

I have created a ServiceAccount and a local Role and RoleBinding which effectively has to give it access to do all-things to all pods in its namespace. Obviously not a good security posture (eg. if broken into it could start pods that do crypto-mining)

Looking at the above commentary it is fairly clear that extending resourceNames to support a pattern could be useful for pods, but only to the extent of read-only operations. For anything that involves changing pods it would appear to be a weaker mechanism than would be desired; I would rate it similar to sudo in that regard (which in itself would point to value, but one that could easily lead to unexpected insecurities in configuration).

Presumably OPA (OpenPolicyAgent) is the answer to this. OPA is a CNCF Graduated project and seems to at least be firmly on the radar of K8S distributions such as OpenShift and Rancher at least, and has Google and Microsoft as some of its key contributors (see https://kubernetes.io/blog/2019/08/06/opa-gatekeeper-policy-and-governance-for-kubernetes/). OPA effectively involves a validating (and mutating) admission webhook, but with an implementation where the policy language and machinery are already created for you. In my use-case, it would be very useful for ensuring pod creation/mutation/deletion requests that shinyproxy is making to the K8S API match expectations.

Without OPA (or something like it), I would need to use multiple namespaces (shinyproxy in one namespace, its pods in another), but that is only a partial solution; OPA would provide for a stronger and more flexible set of controls.

@davi5e
Copy link

davi5e commented Jun 16, 2021

IMHO I don't think OPA should be considered the way to go...

There could be a way to cascade RBAC permission where applicable, as for example having readonly permissions to Deployments would yield the same permissions to its ReplicaSets and then further down to Pods. Like so resourceNames would become very useful...

There could be some CRDs where this would also help. Take cert-manager, where issued certificates are represented by Secrets in a namespace. The same logic would apply.

Overall, I don't know if this get into "subdividing namespaces" territory, but if at all feasible we'd all benefit while broadening the current use case for the resourceNames field.

@OmerKahani
Copy link

Many people have come here and added more use cases. Should we re-open the issue to have another look at it?

I also want to add that sometimes dividing things into namespaces is not trivial, so having another solution would help with security.

@tap52384
Copy link

tap52384 commented Nov 2, 2021

Is it possible to create a role that would apply to pods with the same label? If so, that's one way to fix things.

@rcmorano
Copy link

rcmorano commented Nov 13, 2021

JFTR, the use case that brought me to this issue is I have a Job that I would like it would be able to delete/restart some pods, but obviously, I cannot know before hand what the name the pod from the Deployment I want to delete will be and I have some other deployments I wouldn't like it could be able to delete.
It's a low risk scenario to have broader permissions for the Job but I was surprised resourceNames did not support regex and wanted to give my +1 for this FR :)

@thannaske
Copy link

I stumbled across this while attempting to limit a ServiceAccount to manage SSL certificates which are stored as Secrets alongside with application specific-secrets the SA should not be able to read. In my opinion this is a valid use case for this feature request without violating the principle of resource separation by Namespaces.

@leewoobin789
Copy link

setting rules based on certain wildcarded reource names would bring enormous benefits in ecosystems and also other cncf projects, where the RBAC ClusterRoles are having way too high privileges. i kindly ask you to reconsider it again. :)

@thomas7kuo
Copy link

thomas7kuo commented Feb 4, 2022

Please reopen this issue. I have a legit use case and it could enhance the security and access control for many systems

@donistz
Copy link

donistz commented Feb 23, 2022

We also have a problem that can be resolved with a pattern for the resource inside RBAC. We want to grant read access for some dynamically created secrets in the namespace to users who should not be able to read all secrets of that namespace. We don't want to maintain dynamically the role definitions for our service account and users every time when a new secret is created.

@pierluigilenoci
Copy link

Please reopen this issue. I have a legit use case and it could enhance the security and access control for many systems

@thomas7kuo you can try to do a PR for the case in question and I am sure that if all safety and design requirements are met it will be approved.

@sjwl
Copy link

sjwl commented Jun 16, 2022

What if we leverage the labelSelector method?

rules:
- apiGroups: [""]
  resources: ["pods"]
  resourceSelector:
    matchLabels:
      appID: my-app-id
  verbs: ["get"]

not suggesting the implementation would be easier just because we're leveraging a familiar method used for other areas like podSelector or namespaceSelector, only that it's a method well understand already and not introducing something new like a regex expression to define scope.

@ghostsquad
Copy link
Contributor

Any chance this can be reopened?

@mar-pan
Copy link

mar-pan commented Nov 29, 2022

Any chance this can be reopened [x2]?

@pierluigilenoci
Copy link

@mar-pan @ghostsquad this ticket has been closed for 4 years, I assume that the chances of it being reopened are very low.

I share the hope with you but I assume that it is more effective to try to reopen a new one (linking the old one in the description). 😉

@liggitt
Copy link
Member

liggitt commented Nov 30, 2022

What if we leverage the labelSelector method?

That requires access to information (content of the incoming and/or existing object) the Kubernetes authorization layer does not have. Authorization only has access to information in the request headers and URL.

I assume that it is more effective to try to reopen a new one (linking the old one in the description). 😉

Please don't do that, this is unlikely to make progress as a new issue that's a duplicate of this one. A proposal that works through the design along with the implications of such a change can be opened as a KEP, but the feedback from area maintainers has consistently been that subdividing access to objects within a namespace based on fuzzy-matching of names is not recommended.

@tyger
Copy link

tyger commented Dec 20, 2023

Writing to check if anything changed on this front and this request can be reopened?

My understanding so far:

  • As auth system of K8s does only takes into account URL and header of REST API request, there is no technical limitation to implement wildcard functionality for resourceNames property.
  • The fact that it might be misleading is recognised and seems to be generally accepted by requesters, however it will require disclosure in documentation that wildcards shouldn't be taken lightly.
  • Comment above about giving permission to create pod, won't protect from getting access to secrets is not really relevant here as it will work that way without wildcards anyway.

Is there any particular impediments to implement it except for "it is not recommended to subdivide namespaces"?

I believe the essence of the ask here is to make auth filtering rules a bit more flexible, that's it, no expected change of the authentication and authorisation concepts.

@antonmatsiuk
Copy link

another use case for this is to allow port-forward of a specific Pod. Since Deployments/ReplicaSets create Pods with dynamic names, it's not possible to limit without wildcard support on resourceNames

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature Categorizes issue or PR as related to a new feature. sig/auth Categorizes an issue or PR as relevant to SIG Auth.
Projects
None yet
Development

Successfully merging a pull request may close this issue.