kube-rs / kube

Rust Kubernetes client and controller runtime
https://kube.rs
Apache License 2.0
3.01k stars 307 forks source link

Namespace scoped access for `Controller.owns` #941

Closed wseaton closed 1 year ago

wseaton commented 2 years ago

Would you like to work on this feature?

maybe

What problem are you trying to solve?

When trying to limit the scope of permissions required for a controller, it would be ideal if the client could be configured to only use namespace APIs, as reflection through the ownerreferences should inform the controller enough to do only a namespaced scoped call.

Currently the controller runtime requires passing in a cluster scoped API for both the parent resource and it's child, which is not ideal for potentially sensitive resources like Secrets or ConfigMaps.

Describe the solution you'd like

Another method on Controller like owns_namespaced where we pass in a client generic over namespace but not the resource might work?

Describe alternatives you've considered

Haven't really considered other alternatives.

Documentation, Adoption, Migration Strategy

No response

Target crate for feature

kube-runtime

clux commented 2 years ago

It should not be required to pass in a cluster scoped Api. Where are you getting this assumption from? Controller::owns should inherit the scope of the Api you pass in - because it just takes the events passed from a watch on that Api.

You should be able to either pass a Api::namespaced(..) to watch at a given ns, or a Api::all to watch at the cluster level.

wseaton commented 2 years ago

@clux that makes sense, maybe I didn't specify the question properly, I understand you can pass in a namespaced API, but I'm trying to avoid creating a bunch of namespaced scoped controllers for each namespace that a child resource has to be watched in.

My controller has cluster access to the parent resource, but I'd like it to only make namespaced calls to watch the child resources (controlling the RBAC externally through some automation). Looking at the code though I'm not really sure this is even possible, hence the question :)

nightkr commented 2 years ago

If you the NSes you want to watch are static then you could do something like:

Controller::new(...)
  .owns(Api::<Secret>::namespaced("ns1"))
  .owns(Api::<Secret>::namespaced("ns2"))
  .owns(Api::<Secret>::namespaced("ns..."))
  .run(...)

If you want to control which NSes you watch at runtime then it gets a bit trickier.. it should still technically be possible, but you'd probably need to use the low-level applier API directly rather than Controller.

wseaton commented 2 years ago

If you want to control which NSes you watch at runtime then it gets a bit trickier.. it should still technically be possible, but you'd probably need to use the low-level applier API directly rather than Controller.

This looks promising, for my use-case a project can "opt-in" to management by our controller at any time, so runtime control is ideal (I'd make it externally triggered by another CRD). Would this be a good candidate for eventually exposing in Controller? Or better as a one-off recipe if I can figure it out.

nightkr commented 2 years ago

I don't think the "full journey" will ever have direct first-class support in Controller. I think there might be value in exposing "also listen to this arbitrary Stream<Item = ObjectRef<K>>" as an escape hatch (like the trigger queue that applier takes).

wseaton commented 2 years ago

Noted, I think that makes sense and I have what I need to proceed with this.

Btw, this description of applier is great :grin:

This is the “hard-mode” version of Controller, which allows you some more customization (such as triggering from arbitrary [Stream]s), at the cost of being a bit more verbose.

nightkr commented 2 years ago

Controller (Savage)

clux commented 1 year ago

Going to close this. Resolved question.