-
Couldn't load subscription status.
- Fork 285
feat: Add support for passing additional parameters to OIDC providers #4195
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
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for docs-kargo-io canceled.
|
|
I see this must be related to #4197. I want to tread lightly here, but I think this approach has a lot of potential. Some things I'd be interested in seeing:
I just want to set expectations that the mapping of OIDC users to ServiceAccounts won't go away. This would be an alternative. The reason we need to keep this feature is that in many (possibly even a majority of) orgs, many (or even most) Kargo users actually don't have any access to the cluster and the whole system of mapping users to SAs is really the only way to accommodate such users. I'm excited to see where this could go and will close #4197 because this seems like a much better direction. |
|
@thomaspurchas I'm confused by one thing... this PR was opened prior to #4197. What was #4197 meant to achieve that couldn't be done better through this approach? I feel like I must be missing something. |
|
@krancour this PR makes it possible to get multi audience tokens. #4197 makes it possible to use multi audience tokens. So they’re “matched pair” of PRs. But I figured it would be better to introduce them as two separate PRs because they’re kinda doing slightly different things, and touch very different (but related) parts of the codebase.
Yeah I wasn’t expecting the existing SA approach to ever go away. Taking advantage of OIDC and RBAC like this requires a very specific cluster and IDP setup that probably isn’t viable for everyone.
I can add that to this PR.
I can certainly take a look, but I’m not sure what value it would bring. I wasn’t aware the CLI was capable of doing its own OIDC handshake, but if it is, it should be easy to extend this change to the CLI.
I’m not sure how best to do this. I can tell you that I have this working internally, and it’s been working well for little while now (indeed the only reason #4197 exists, is because I discovered the JWT limitation while trying to get all of this working). But I’m not sure how to create a public demo, as we use our own in-house IDP rather than any of big IDP services. Our IDP isn’t doing anything non-standard to support this, it’s all bog standard OIDC/oAuth, I’m just not familiar enough with any external IDP to set up something I could publicly demo. |
|
I think we mutually agree #4197 just doesn't make sense without this PR, so especially with #4197 being a one-liner, let's just deal with everything here. 🙏
What I meant originally about not excluding the CLI from this feature was not excluding it from the generic ability to pass additional parameters during the authorization code flow. Since then, I've realized a reason that the CLI can benefit specifically from multi-audience tokens... Its current ability to use a k8s token to authenticate with the Kargo API server is predicated on the existence of kubeconfig, that kubeconfig's current context being the correct one, etc. On top of that, the token often doesn't appear directly in the kubeconfig because there is very often an auth plugin at play. The trickery involved in actually obtaining and using that token in such cases is complex. I wouldn't have any of that go away really, because that "client config" option will remain useful in cases where OIDC just isn't set up at all, but outside of that case, the multi-audience tokens would simply be a much more straightforward way of doing the same thing without relying on kubeconfig or any kind of tomfoolery.
When the PR looks fully ready, I can stand up a throwaway cluster and IDP to help us validate it all. |
ea4ee9c to
ac5a883
Compare
Additional parameters are added to the authorization request, and allow the OIDC client to request things like additional audiences to be included in the resulting JWTs. Signed-off-by: Thomas Purchas <purchas@apple.com>
Kubernetes supports the use of OIDC tokens for user authentication by sending the OIDC ID Tokens as the bearer token in requests. So returning access forbidden errors because someone has a OIDC token that doesn't map to Kargo's internal role system doesn't mean they're not authorised to interact with the underlying Kargo CRDs. By allowing people who have authenticated with an OIDC token to fall through to k8s bearerToken auth, it makes it possible for people to use the same OIDC issuer for both their k8s authentication, and Kargo authentication, then rely solely on k8s RBAC to manage authorisation for both the k8s cluster and Kargo, regardless of the interface the user chooses (Kargo UI/CLI, Kubectl). Signed-off-by: Thomas Purchas <purchas@apple.com>
The API server now support passing additional OIDC parameters to the difference Kargo clients, this change updates the Helm chart to make it easy to set the relevant env vars. Signed-off-by: Thomas Purchas <purchas@apple.com>
The API server and browser UI both support additional OIDC params, this change brings that support to the Kargo CLI. Signed-off-by: Thomas Purchas <purchas@apple.com>
ac5a883 to
c7cd24b
Compare
|
Thanks @thomaspurchas. This is looking pretty good. I will review more thoroughly in the coming week, but I think we're nicely aligned on the approach now. |
|
@krancour do you know when you might have time to look at this? |
|
@krancour is there anything I can to help you review this PR? If you can give me some pointers on OIDC providers that support multi-audience setups, I might be able to put together a test setup for you. |
Signed-off-by: Kent Rancourt <kent.rancourt@gmail.com>
|
@thomaspurchas sorry for the delay. I've finally gotten around to reviewing this carefully and the code looks just fine in theory, but after spending hours experimenting and scouring docs, I couldn't make this work end-to-end with any publicly available IDP. This unfortunately leaves me with doubts about the practicality of what you're trying to enable with this change.
The spec for sure allows the The unfortunate thing here, I think, is that probably no one but you benefits from this change, and having no access to an IDP with this unique capability, it's not possible to thoroughly vet that change. I'm sorry to say, but I'm reluctant to move forward with this unless you can show this working end-to-end with some publicly available IDP. |
|
Tentatively closing this. |
|
@krancour could you give me a list of public IDPs that you've tried? I'm not super familiar with the IDP landscape, so a list providers you know about would give me a good starting point to see if I can make this working using a public IDP. Also if we're closing this, can we reopen #4197? You don't need multi-audience support for the JWT issued to Kargo to be accepted by the k8s RBAC layer. k8s can be configured to accept JWTs from multiple issuers at the same time. So there is nothing preventing someone from configuring their k8s cluster to accept the JWTs already being issued to Kargo. I think it's also worth noting that there may be other reasons for wanting to pass additional parameters in the auth request to an OIDC provider, beyond just multi-audience tokens. For example, it's often used to provide hints to the IDP's login flow. Auth0 have some docs on how a number of IDP systems accept additional parameters. My use-case specific uses multi-audience tokens, so that's what I've tested. But these two bits of functionality individually add important functionality that is broadly usable by anyone. It just that in my specific case, I'm using these two components together in a manner that is less common than expected. |
|
I experimented extensively with AKS + Entra ID and KinD with a standalone Dex. After no success with those, I resorted to reading docs and consulting Copilot for other IDPs. There was little point struggling with any IDP unless their docs explicitly noted support for this. I'll concede that Ory claims to support this and with enough fiddling, I possibly could have gotten k8s to work with Ory, but it's neither easy nor common to use k8s distros from the public cloud providers with any IDP other than their own. I'm not at all saying this is impossible to do. I'm saying it's very hard to validate these changes and the hours that I've already sunk into this exceed the perceived benefit. |
Can we find another way to validate the parameter passing that doesn't rely on multi-audience support? And separately find a way to validate the change in the RBAC code, that also doesn't require multi-audience support? It'll be two seperate, completely unrelated, test scenarios. Each validating one specific part of this change, and also proving the independent value of the two changes? For example, Dex allows clients to pass an additional Microsoft Entra supports Support for additional parameters makes it possible for people to configure Kargo to pass parameters like For the RBAC fallthrough, that can be achieve with a Kind cluster and Kargo using Dex, with the Kind cluster configured to accept JWTs issued to either audience. I can try and put together a Kind cluster config that sets this up, it might take me a little while. |
I don't think it will come to that...
I actually started working on that lastnight, but I'm using Ory since it purports to support the exact scenario you care about. I'll re-open this, but wrapping this up is low priority.
Isn't that actually a tad different than the scenario you were initially concerned with? Making the k8s API server accept tokens for two different audiences (which I'm not positive is possible, but let's find out) and making the IDP issue multi-audience tokens seem like distinctly different approaches to the same problem. If the former is even possible with KinD, I'm highly skeptical that most other k8s distros would permit that. |
|
Big block of text below, so want to prefix this with an offer to have call to talk through this stuff, might be easier than going back and forth via Github. If that's of interest, just say so, and I can reach out via Discord.
It is, but the changes needed to support it are very similar. #4197 is all that's needed to support this case.
It's explicitly supported in k8s 1.3 and above via the auth configuration file. The k8s team added the auth config file to support this exact use case, the example config in the k8s docs show how to accept multiple audencies from the same issuer. The functionality is currently not exposed via hosted services like EKS or GKE, but I from talking to EKS support staff (and bugs that broken our clusters) that EKS now uses the authentication config files under-the-hood, so EKS has the technical capability to support multiple OIDC issuers (and the UI even hints at the support), it's just disabled in the UI at the moment.
It is different. What I'm trying to highlight is that the two changes here:
both have very important uses outside of just the multi-audience ID token scenario. Multi-audience tokens aren't the only scenario where you need these two features. For Support for passing additional parameter to OIDC providers you also need this functionality for using IdP specific features, exposed via additional query parameters, like:
For #4197 - Allowing auth to fallthrough to k8s RBAC if the OIDC token isn't recognised by Kargo you need this functionality to allow people to use the K8s RBAC system directly, if they have an auth setup that allows them to issue OIDC tokens that are recognised by both k8s and Kargo. There's three different ways to make that happen:
It's only the multi-audience token scenario that requires both of these changes to happen at the same time. I could go a create two new PRs for these changes, and provide you with two brand new, perfectly valid and useful, reasons for making each change. I think there's sufficient justification for these changes, even if you can't get the multi-audience config working, and I think it's worth evaluating these changes based on those other uses, because they're much easier to test and validate. Multi-audience support then becomes a happy accident, as a consequence of adding support for features that are independently valuable. |
|
I understand everything you said and appreciate you cluing me in on a few more obscure config options that I wasn't yet aware of. But I'm asking you to please understand this is not a priority for our team. Jumping on a call is the last thing on my radar right now. It doesn't matter whether you view this as one change or two individually useful changes that happen to also work great together. For something we don't see as a priority, I've sunk a lot of time already into validating this, and I think it should be clear from me re-opening the PR that I am graciously willing to put more time into it still, but I'm asking for you to understand that it's happening on a best effort basis as time permits. |
I appreciate the time your putting into this, and I'm not trying to pressure you into going faster and apologise if it's coming across like that. I just trying to highlight some options for validating this change that might be quicker and easier to do, rather than trying to get the multi-audience tokens working end-to-end. Ultimately it would be a shame if these changes were rejected simply because use-case I presented with them is too obscure, when there are plenty of non-obscure use-cases that could be used instead. I have very little visibility into what your team considers a priority, so I can only guess at what might provide reasonable justification for prioritising, or not prioritising a specific feature. But regardless of that, we'll continue to run a fork of Kargo internally anyway, even once this is merged, because our internal processes make contributing to OSS projects difficult (it took me a month to get approval to contribute these changes). I just want to make sure I've given you everything you need to review this change, on whatever timeline works best for you. |
Helm template produced incorrect env vars for additional oidc parameters Signed-off-by: Thomas Purchas <purchas@apple.com>
c12c4df to
a016196
Compare
Some OIDC providers support passing additional parameters in authorization requests to support features like multi-audience tokens, or tokens where the audience and client ID are different. An example of how providers implement this can be found here.
This change adds support for passing additional static parameters in the OIDC authorization request, so that Kargo can request tokens with different audiences, or multiple audiences. Being able to customise the audience in the returned authentication token, makes it possible for Kargo to request a token that's both recognised by Kargo and recognised as an authentication token for the underlying Kubernetes cluster. Which in turn opens up the possibility of using K8s authentication tokens with Kargo, and having Kargo operations directly authenticate with the user token, rather than having to manage it own RBAC and service account layer to provide access control.