-
Notifications
You must be signed in to change notification settings - Fork 149
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
Expand JWT claim matching capabilities #493
Comments
Hi @cipherboy, I'm pondering this story and hoping to make a stab at it! I'm a little confused how the An additional question: would the policies granted by the role be a static list? Ie, any claim match gets a specific list of policies. |
@suprjinx This is true in some deployments, but I didn't think this was a universal assumption (that everyone would be using entities to back the JWT engine -- you can use it without provisioning entities). However, even with entities backing JWTs, this is definitely still applicable to One of the other ideas I had for this was using something like #753, but for matching JWTs like GCP uses. Then you could template your entity if desired. That would be an alternative to the role system entirely. Thoughts? |
I'm totally unfamiliar with GCP -- do you have a reference to their docs on how this works? I'm thinking that regex pattern in the |
@suprjinx Hmm, I think the k8s docs are a little better (which also uses CEL): https://kubernetes.io/docs/reference/using-api/cel/, https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/, and https://github.com/google/cel-spec are good pointers to start with. Essentially, it is a non-Turing-complete language with more expressive properties for validation and supporting custom environment-provided functions. While a regex is OK, it becomes hard to describe complex templating semantics with it that you could with CEL. This would require two languages (one for validation, using regex) and one for templating (which, would also partially re-do validation and could err separately from request validation erring). I guess, lacking another concrete example, in the above subject, we'd have CEL would also help with repetition: you could do conditional matches (e.g., if the project is XYZ, also allow ABC branch, but only DEF branches for all other projects) and other more complex things with fewer, more succinct policies. My 2c! |
I came across this PR in vault hashicorp/vault-plugin-auth-jwt#89, where globs were preferred to regex |
@suprjinx Right, we should have that as well (https://openbao.org/api-docs/auth/jwt/ -- search for The latter, even if it were for a single "entity" (if we defined it as above as |
@suprjinx Hmmm, I think that would be fine for an incremental improvement, but I think adding CELs would be a good time to rethink the binding logic entirely. How about a new interface instead? What would that look like? |
We could add a new map attribute to the role, eg
|
I do think expanding the |
I don't think this is quite sufficient. Unless we wish to issue valid-but-useless OpenBao tokens (which are reject-all, and I'd rather not issue a token in the first place), we still need a moderately-complex token issuance rejection logic. In particular, if your matching on sub is not sufficient, even if your CEL policy is sufficiently advanced to reject it based on associated metadata, you would still have the potential to accept validly-signed-but-unauthorized JWTs and issue a OpenBao token for them, which your underlying CEL policy would reject all access for, because your role isn't sufficiently expressive. So I'd argue you need some amount of CEL-in-JWT-engine anyways. And if you have it, the choice of backend policy engine doesn't matter, it is just a language for constraining OpenBao token issuance. I guess, articulating a bit more what I'd expect out of just the JWT engine... I think I'd do something like:
(you'd enforce exclusivity with Authentication is then simplified to run OIDC or JWT authentication up until you do the role-match evaluation, where you'd then switch over to executing the CEL program The resulting Thoughts? |
that sounds like a great approach -- do we need an RFC step before starting to work on it? |
@suprjinx Given we're introducing a whole new language as a dependency to this plugin, I'd say it's prudent. If you don't want to write it though, I'm happy to do the paperwork. |
I'll try to work up an RFC draft and post here -- it seems like there's a good bit of overlap with RFC #753, so I'll follow its lead :-) |
I'm on board with using CEL as a means of evaluating jwt claims, but I don't yet understand the justification for adding a new |
Sure, happy to @DrDaveD. The short answer is it is an either-or thing. Either you use a role (with a given role name) or you use CEL (with a given CEL role name). The purpose of the new path is that many of the options on We could leave it on the Let me know if you (well, both of you @suprjinx!) want to chat ahead of our Jan 9th community call or if we are happy leaving it until then. |
So the concept of role is still applicable, it's just implemented way differently. Maybe it would be easier to understand if it still included the word "role" then, like I don't see any applicability of this new type of role to the Come to think of it, overall there's a lot of different options between the |
in #753, the |
@DrDaveD said:
While true that the authentication is done by the token issuer, isn't the JWT Auth method still controlling authorization, i.e., whether or not it accepts the issued OIDC ID token? If you set From that standpoint, the CEL policy would also be applicable to OIDC: you'd use that (instead of the native role capabilities) to control whether you issue a Vault token and with what properties. I see both sides of the "roles" naming -- I personally find value in not calling it a role, so there's no confusion that it doesn't augment or supplement the role -- but also see value in calling it a role for consistency / discoverability. Hmmm... :-) |
@suprjinx said:
Hmm, the reason why they were posted to I don't quite like calling them hooks. How about Personally I believe bikesheds should always be a nice shade of blue ;-) |
There's a lot of non-intuitive naming in the Vault API, so I think it's worth some bikeshedding to get a good solution :-) I'll put |
RFC: CEL Expression Support for JWT AuthenticationSummaryThis feature proposes the use of Common Expression Language (CEL) in Vault's jwt-based auth engines (oidc, jwt) to create a flexible framework for validating claims and dynamically assigning token policies. CEL will allow administrators to define fine-grained rules for claim validation and dynamic policy assignment, extending the more static assignment of role- and identity-based policies. Problem StatementVault's jwt-based auth engines (OIDC and JWT) currently assemble token policies from User-facing descriptionAdministrators can define CEL extensions under a new endpoint, Users authenticating with JWT or OIDC tokens will have their claims validated through the CEL roles where present. If successful, they receive a token with dynamically-assigned policies. For example:
Technical DescriptionCEL in Vault Auth Engines (OIDC, JWT)CEL roles integrate with Vault's Auth engine (OIDC and JWT) to dynamically evaluate claims. Instead of using static role-to-policy assignment with Workflow:
API Endpoints
CEL Request Format (Auth Engine to CEL)The following parameters are sent to the CEL policy engine:
CEL Reply Format (CEL role to Auth Engine)The CEL role engine evaluates the claims and returns a
Rationale and alternativesDynamic policy assignment can be implemented using templating for ACLs, but the expressiveness of CEL is much greater. Some form CEL or regex evaluation could be added to existing role instead of creating a new type, as with glob matching for Alternatively, a web hook approach like Vault's CIEPS could be used to achieve similar flexibility. However, the performance implications and system brittleness make this an unattractive alternative. DownsidesAdditional complexity of a new type; not backwards compatible with Vault. |
Oh I suppose it would be possible. My assumption was that the token issuer is trustworthy and there's no good reason to second guess it by blocking some of the things it generates. |
i think the next step here might be a POC branch which I'll work on (following @fatima2003's approach in #753), but perhaps the RFC should become it's own ticket? |
POC draft PR here #869 -- feedback most appreciated! |
Is your feature request related to a problem? Please describe.
GitLab provisions complex JWT claims on ID tokens used with its Vault integration. However, the JWT role isn't expressive enough to fully authenticate these fields.
Describe the solution you'd like
In particular, the
sub
claim contains the following structure, which is unique to pipeline jobs:Matching on a prefix of this (
bound_subject=project_path:my-group/my-project:ref_type:*:ref:*
) isn't possible, to allow a pipeline running in any branch to have access to protected secrets. Similarly, forbound_claims
, it isn't possible to match a glob or an either-or choice (say,bound_claims[environment]=prod-*
orbound_claims[ref]=v*
(withref_type=tag
)).I'm not sure what tools we have currently, or what make the best sense to solve it:
allowed_domains
in PKI secrets enging).Describe alternatives you've considered
Manually specifying every possible value could potentially require a large increase in the number of roles, or tight coupling to their current values which could be inflexible (e.g., binding strictly to version number from a tag, while not binding at all could result in say, requests from another branch).
Explain any additional use-cases
n/a
Additional context
n/a
The text was updated successfully, but these errors were encountered: