Skip to content

KEP-4633: Only allow anonymous auth for configured endpoints #4634

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

Merged
merged 1 commit into from
Jun 7, 2024

Conversation

vinayakankugoyal
Copy link
Contributor

@vinayakankugoyal vinayakankugoyal commented May 13, 2024

  • One-line PR description: Adding new KEP.

@k8s-ci-robot k8s-ci-robot requested review from enj and mikedanese May 13, 2024 23:29
@k8s-ci-robot k8s-ci-robot added kind/kep Categorizes KEP tracking issues and PRs modifying the KEP directory cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. sig/auth Categorizes an issue or PR as relevant to SIG Auth. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels May 13, 2024
@vinayakankugoyal vinayakankugoyal force-pushed the kep branch 8 times, most recently from deeb407 to d42cd81 Compare May 13, 2024 23:43
@vinayakankugoyal
Copy link
Contributor Author

/assign @liggitt

@vinayakankugoyal
Copy link
Contributor Author

/un-assign @liggitt

@vinayakankugoyal
Copy link
Contributor Author

vinayakankugoyal commented May 13, 2024

/unassign @liggitt

@vinayakankugoyal
Copy link
Contributor Author

/unassign @liggitt

@vinayakankugoyal
Copy link
Contributor Author

/cc @liggitt

@vinayakankugoyal vinayakankugoyal force-pushed the kep branch 2 times, most recently from ee42d91 to ade7a71 Compare May 28, 2024 21:11
@liggitt
Copy link
Member

liggitt commented May 29, 2024

This lgtm. Will give @enj time to look over it as well, and @jpbetz for PRR (alpha) review.

I'd like to see this merged by the end of the week if possible.

@enj
Copy link
Member

enj commented May 31, 2024

I'd like to see this merged by the end of the week if possible.

I plan on looking at this today. If that doesn't happen, I'll take care of getting it merged/marked implementable next week.

@vinayakankugoyal
Copy link
Contributor Author

I'd like to see this merged by the end of the week if possible.

I plan on looking at this today. If that doesn't happen, I'll take care of getting it merged/marked implementable next week.

Hi @enj! gentle ping on this. We are getting close to the KEP freeze timelines. Thanks!

@enj
Copy link
Member

enj commented Jun 5, 2024

At a high level, I am in favor of this KEP. I believe it will let certain environments harden themselves.

Assuming Jordan is back from PTO tomorrow, I think my comments below would serve as good topics for the API review meeting.

  1. As far as path based logic goes, both RBAC and the path authz support globs. Why does this feature not support globs as well?

  2. Does the path matching require an exact match or does it perform any kind of trimming on leading or trailing slashes?

  3. By the time the authentication layer runs, we have already paid the cost to of parsing the request info data. Thus why are we using paths to represent resources, when we have the proper GVR available to us?

  4. I disagree with the structure of this API. It seems to assume that the existing flag based config is 'good' when we clearly believe that it is not. I doubt we would design it today in the same way. So instead of having two fields will nuanced interactions with each other, I would expect an API that has two mutually exclusive positive fields. For example:

anonymous:
  enabledForAllRequests: bool
  enabledForSelectedPaths: [ ... ]

This makes it obvious from the single field exactly what the config is doing.

  1. I would also prefer an API that leaves enough space for future extension instead of assuming we will only have path based restrictions:
anonymous:
  enabledForAllRequests: bool
  enabledWithConditions:
    - path: ...
    - resource: ...
  1. Should we allow for IP based allow lists for anonymous auth?

  2. This entire feature and much more could be accomplished with an L7 proxy in front of the API server (over localhost). Many OSS proxies exist that can do this while allowing the cluster operator to disable anonymous authentication on the cluster. Why is that approach not recommended since it requires no changes to core Kube?

  3. No other existing authenticator makes decisions based on the request metadata today. Why is okay for the anonymous authenticator to do that? Are we okay in the future allowing other authenticators to do that? Both request signing and IP based conditional authentication come to mind as use cases.

  4. @stlaz made an interesting comment that this design felt like it belonged in authorization instead of authentication. The path based restriction does feel like a deny authorizer. If an existing authenticator (like JWT) asserts the anonymous user (or the anonymous user is impersonated), are we okay with that anonymous user not having any of these restrictions? If the restriction was implemented in authorization, it would be uniform regardless of how the anonymous user was asserted.

@liggitt
Copy link
Member

liggitt commented Jun 6, 2024

responding to #4634 (comment)

  1. As far as path based logic goes, both RBAC and the path authz support globs. Why does this feature not support globs as well?

I want to keep the surface area here as small as possible, globbing wasn't required for the use cases presented so far, and the intent of this feature is to constrain anonymous auth to a well-known set of endpoints. That points to constraining this to exact paths in my opinion.

AI: call out that this is more constrained than RBAC, etc, on purpose, and why.

  1. Does the path matching require an exact match or does it perform any kind of trimming on leading or trailing slashes?

AI: clarify this is an exact case-sensitive match, if you want to allow with/without slash, add both to the list (just like RBAC).

  1. By the time the authentication layer runs, we have already paid the cost of parsing the request info data. Thus why are we using paths to represent resources, when we have the proper GVR available to us?

A flat list of paths is way simpler to reason about than parallel lists of non-resource paths and structured resource tuples, in terms of what it is allowing. I expect anyone using this feature to have ~1-3 entries and being very explicit about the paths the anonymous authenticator can be used for.

AI: explain why this surface area is so constrained, and indicate that people who want anonymous access to a wider or more complicated set of endpoints should probably just leave it globally enabled and lean on authorization policy.

  1. I disagree with the structure of this API. It seems to assume that the existing flag based config is 'good' when we clearly believe that it is not. I doubt we would design it today in the same way. So instead of having two fields will nuanced interactions with each other, I would expect an API that has two mutually exclusive positive fields. For example:
anonymous:
  enabledForAllRequests: bool
  enabledForSelectedPaths: [ ... ]

This makes it obvious from the single field exactly what the config is doing.

I want to be able to use the config file to disable anonymous auth as well, so I think the single coarse-grained explicit on / off boolean field is useful.

Because we load the config file strictly, a typoed restrictToPaths will error. I don't think making the admin repeat themselves to enable for all paths is useful.

AI: explicitly describe how to disable anonymous auth via the config file

  1. I would also prefer an API that leaves enough space for future extension instead of assuming we will only have path based restrictions:
anonymous:
  enabledForAllRequests: bool
  enabledWithConditions:
    - path: ...
    - resource: ...

AI: switch to a list of struct conditions with only path as a condition today, which makes it possible to extend in the future if needed.

conditions []AnonymousAuthCondition

type AnonymousAuthCondition struct {
  Path string
}
  1. Should we allow for IP based allow lists for anonymous auth?

I don't think we should include this now, but if we structured as mentioned for 5, this could be added in the future:

conditions:
- path: /healthz
  ip: 127.0.0.1
- path: /readyz
  ip: 127.0.0.1
- path: /livez
  ip: 127.0.0.1
- path: /api/v1/namespaces/kube-public/configmaps/public-info
- path: /.well-known/openid-configuration
  1. This entire feature and much more could be accomplished with an L7 proxy in front of the API server (over localhost). Many OSS proxies exist that can do this while allowing the cluster operator to disable anonymous authentication on the cluster. Why is that approach not recommended since it requires no changes to core Kube?

If someone is going to set up a sidecar load balancer container for kube-apiserver anyway, then sure, that could handle this scenario. However, many deployments do not run sidecar load balancer containers (see every kubeadm deployment) and the complexity to recommend they start doing so is way higher than allowing scoping down anonymous auth this way.

AI: add an alternative considered sentence that a sidecar proxy could have handled this but would push complexity into all consumers who are not running side car proxies today, and the complexity of allowing the restriction in-tree is minimal.

  1. No other existing authenticator makes decisions based on the request metadata today. Why is okay for the anonymous authenticator to do that? Are we okay in the future allowing other authenticators to do that? Both request signing and IP based conditional authentication come to mind as use cases.

AuthenticateRequest already takes the full request, TokenReview is a subset of that which only looks at the bearer token. I'd actually be ok with resurrecting #2843 to forward some info about the request to the token authenticators if we can constrain it sufficiently

Determining if a given authenticator is active or not is a much smaller surface area than modifying the resulting user info based on request attributes. It's worth noting that this doesn't change the authenticator go interface at all, AuthenticateRequest already has the go request. Starting with a very constrained in-tree use of this information which we know doesn't modify resulting user info, before considering surfacing it to our external APIs, seems ok.

  1. @stlaz made an interesting comment that this design felt like it belonged in authorization instead of authentication. The path based restriction does feel like a deny authorizer.

I'm not in favor of splitting this between authn and authz for a couple reasons:

  1. a deny authorizer is a lot more complex to implement than restricting the anonymous authenticator
  2. having two decoupled subsystems where a later phase is responsible for locking down over-granted stuff from the first phase is not ideal... we already have this with authz/admission, and I don't want to repeat that pattern if we don't have to

AI: add an alternative considered about split authn / deny authorizer and why we don't want to do that.

If an existing authenticator (like JWT) asserts the anonymous user (or the anonymous user is impersonated), are we okay with that anonymous user not having any of these restrictions? If the restriction was implemented in authorization, it would be uniform regardless of how the anonymous user was asserted.

Having other actual authenticators identify the incoming request as anonymous is ... sort of insane. I think we should start by just configuring / restricting the actual anonymous authenticator.

AI: add an open question to resolve before beta about also applying any restrictions here to anonymous userInfo that comes back after all authenticators and impersonation have run.

@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jun 6, 2024
@jpbetz
Copy link
Contributor

jpbetz commented Jun 6, 2024

/approve
For PRR

@vinayakankugoyal
Copy link
Contributor Author

@liggitt and @enj - I've updated the KEP based on the discussion and AI in #4634 (comment). Please take another look! Thanks!

@liggitt
Copy link
Member

liggitt commented Jun 7, 2024

thanks

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 7, 2024
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jpbetz, liggitt, vinayakankugoyal

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 7, 2024
@k8s-ci-robot k8s-ci-robot merged commit f54a6dd into kubernetes:master Jun 7, 2024
@k8s-ci-robot k8s-ci-robot added this to the v1.31 milestone Jun 7, 2024
@cfryanr
Copy link

cfryanr commented Jun 10, 2024

How would this new feature impact aggregated APIs added later to the cluster by installing apps which include a new APIService? I didn't see mention of that in the KEP. If some of those new aggregated APIs require anonymous auth, would anonymous auth be rejected if those paths were not included in this new configuration (assuming this new feature is configured with paths)?

@liggitt
Copy link
Member

liggitt commented Jun 10, 2024

would anonymous auth be rejected if those paths were not included in this new configuration (assuming this new feature is configured with paths)?

Yes. This is putting control about which endpoints allow anonymous auth in the hands of the kube-apiserver administrator. If they constrain anonymous auth to a specific set of paths, that precludes anonymous access through the kube-apiserver to aggregated API server endpoints not included in that set of paths.

@neolit123
Copy link
Member

neolit123 commented Jun 10, 2024

i think i agree with some of the points @enj brough up earlier especially around extensibility of the feature.
on a UX tangent, it seems like the configuration becomes "well-guarded" by the administrator as it's a file on disk, however it also becomes not well extensible.

example:

  • kubeadm defaults some anonymous auth endpoint config so that it can bootstrap clusters with BS tokens.
  • a tool is deployed on the kubeadm cluster that needs to change the kubeadm defaults so that it can support additional annonymous paths. i believe such a tool today is Pinniped that @enj also worked on.

and as another crude example, if anonymous paths were guarded by authz with something like RBAC then that means they could be additive as resources are. however a single centralized config is a different story and also it means the admin has to keep it in sync on HA setups. so maybe a controller is needed.

this makes deployment well guarded but more challenging.

@enj
Copy link
Member

enj commented Jun 10, 2024

if anonymous paths were guarded by authz with something like RBAC

One of the goals of the feature is to disallow misconfiguration of clusters via RBAC, especially in cloud envs where the control plane config is owned by the cloud provider. Any tool has to the deal with anonymous auth being disabled. For example, AKS always has it disabled and there is no way to enable it. I don't see that ever changing.

If kubeadm adopts this functionality (therefore changing the default of those environments), they should make it easy to configure since there is no distinction between the Kube API admin and the cluster operator in self hosted clusters. The anonymous config needs to be coordinated with the runtime config of the cluster such as aggregated APIs.

@neolit123
Copy link
Member

neolit123 commented Jun 10, 2024

if anonymous paths were guarded by authz with something like RBAC

One of the goals of the feature is to disallow misconfiguration of clusters via RBAC, especially in cloud envs where the control plane config is owned by the cloud provider.

here i mean the way RBAC is implemented as more of an example. it's an additive permission mechanism, via API resources, vs the static config which this feature utilizes. if the cluster-admin role could add permissions for new paths additively we shift the responsibility from the kube-apiserver administrator to the cluster administrator, which may not be the same people...it makes this feature N times more complex and less secure supposedly, but more flexible.

If kubeadm adopts this functionality (therefore changing the default of those environments), they should make it easy to configure since there is no distinction between the Kube API admin and the cluster operator in self-hosted clusters. The anonymous config needs to be coordinated with the runtime config of the cluster such as aggregated APIs.

also i would like to be clear that i don't disagree with the static config approach, and yes kubeadm can enable its internal patches mechanism to support extensibility on the cluster creation phase, but that would be a blocker for any tool deployed on top of kubeadm only via kubectl and YAML that wishes to enable additional anonymous auth endpoints. it has no way to modify the static config. (unless it also deploys a high-proviliged controller that manipulates files on control plane disk)

for managed solutions up the stack like GKE, AKS, TKG, we could reason about this feature enablement, but i don't think i would give a +1 to enable it by default in OSS kubeadm. we could write a hardening guide. but i'm just one of the votes, so maybe the rest of the kubeadm maintainers will disagree with me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/kep Categorizes KEP tracking issues and PRs modifying the KEP directory lgtm "Looks good to me", indicates that a PR is ready to be merged. sig/auth Categorizes an issue or PR as relevant to SIG Auth. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

9 participants