Repository navigation
Conversation
…ject audiences - New delegation policy field subjectAudiences (schema, admin API, policy evaluation, deny reason subject_audience_not_allowed) - token.exchange.subject.token.policy.audiences.issuers: on a delegated exchange, accept a subject_token from a listed issuer that lacks knox.token.audiences only if its aud intersects the actor policy's subjectAudiences - delegation.headless.reject.subject.with.act: reject a delegated token as a headless subject - Unit, integration and E2E tests (knoxidf-token-multi-hop topology); docs Co-Authored-By: Claude <noreply@anthropic.com>
Test Results 4 files 4 suites 1m 40s ⏱️ Results for commit 6f71e00. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
KNOX-3520 - Support multi-hop RFC 8693 delegation via policy-bound subject audiences
What changes were proposed in this pull request?
A token-exchange topology validates the
subject_tokenand theactor_tokenagainst the sameknox.token.audienceslist. A token minted by a delegated exchange carries only the requested target audience, so it can never be presented again as asubject_token, and on-behalf-of chains stop after the first hop, even thoughdelegation.max.actor.chain.depthallows deeper chains. The workarounds either break recipient binding (adding the token-service audience to every downstream token) or open the gate (droppingknox.token.audiences, which lets any stolen SA token, minted for any audience, act as a delegation actor).This PR adds one narrow relaxation that is bound to the actor: a re-exchanged
subject_tokenis accepted only by the service it was addressed to.New delegation policy field:
subjectAudiencesresourcePolicy, which lists the services the actor may mint tokens for.DELEGATION_POLICY_SUBJECT_AUDIENCESchild table, added to both the default and the Oracle DDL scripts, withON DELETE CASCADE.createTablesIfNotExistcreates missing tables at startup, so existing databases pick up the new table.400 invalid_request.JdbcDelegationPolicyService#evaluatedenies with the new audit reasonsubject_audience_not_allowedwhen the check is required and the subject token'sauddoes not intersectsubjectAudiences. The client still gets the generic400 invalid_request"rejected by policy".New JWTProvider parameters (both off by default)
token.exchange.subject.token.policy.audiences.issuersactor_tokenpresent), asubject_tokenfrom one of these issuers that fails theknox.token.audiencescheck is accepted only if itsaudintersects the actor policy'ssubjectAudiences. Never applies to actor tokens, headless or same-subject exchanges. Unset: today's behavior.delegation.headless.reject.subject.with.acttrue, a headlesssubject_token(the acting party) that carries anactclaim is rejected with400 invalid_request(audit reasonheadless_subject_has_act).Resulting audience rules
actor_token, and the headlesssubject_tokenaudmust contain aknox.token.audiencesvaluesubject_tokenaudmust contain aknox.token.audiencesvaluesubject_tokenknox.token.audiencesvalue, accepted only if anactor_tokenis present,issis listed, andaud∩subjectAudiences≠ ∅subject_tokenaudmust contain aknox.token.audiencesvaluesubject_tokenact(when enabled)Implementation
PolicyBoundSubjectAudienceValidator(new) wraps the topology'sRequestAudienceValidator. When theknox.token.audiencescheck fails for a token from a listed issuer, it defers the decision to the policy instead of rejecting. Signature, issuer, expiry and not-before checks are unchanged and still enforced.TokenExchangeHandleruses it only for delegated exchanges (createSubjectAudienceValidator), and passes the subject token's audiences, plus whether the policy match is required, to the policy check throughPolicyCheckRequest.JWTFederationFilterreads the two new parameters.Docs
knox-site/docs/knoxidf/:token_exchange.md: the newsubjectAudiencesfield, evaluation order, a new "Multi-hop delegation" section, and the configuration table.configuration.md: the 2 new parameters.endpoints.md: the admin API field and validation.security.md: 2 new bullets.operations.md: the new deny reason.How was this patch tested?
mvn -pl gateway-spi,gateway-server,gateway-provider-security-jwt,gateway-service-knoxidf verify. All modules pass, including checkstyle, PMD, SpotBugs and forbiddenapis.PolicyBoundSubjectAudienceValidatorTest(new): a delegate pass returns no policy match; a delegate failure is accepted provisionally only for a listed issuer (not for unlisted or null issuers); the configured audiences are passed to the delegate; the flag is reset on each validation.TokenExchangeHandlerTest:invalid_requestand audited;act, and not applied to delegated exchanges.JWTFederationFilterDelegationConfigTest: parsing of the new parameters.JWTFederationFilterTokenExchangeTest, full filter path:401) even when the issuer is listed;JdbcDelegationPolicyServiceTest:subject_audience_not_allowedcases: match, mismatch, empty policy set, token withoutaud, ignored when not required;subjectAudiences.DelegationPolicySchemaTestandKnoxDatabaseTest: the new table is queryable, enforces its FK and cascades on delete; a pre-KNOX-3520 schema gets the table on upgrade.DelegationPolicyResourceTest: field omitted, persisted, null elements filtered; empty or whitespace values rejected on register, update and registerOrUpdate.DelegationPolicyDtoImmutabilityTest: defensive copies in the request and response DTOs.DelegationPolicyTestandPolicyCheckRequestTest: new fields, defaults, immutability.Integration Tests
.github/workflows/build/conf/topologies/knoxidf-token-multi-hop.xml, added to the Dockerfile. It setsknox.token.audiences=https://recipient1, its own issuer (listed in bothjwt.expected.issuerandtoken.exchange.subject.token.policy.audiences.issuers),delegation.headless.reject.subject.with.act=true,delegation.max.actor.chain.depth=3, nestedactclaims, and thepassthroughaudience validator..github/workflows/tests/test_multi_hop_delegation.py(11 tests). Policies are seeded through the KNOXIDF_ADMIN API. tom is the subject; recursiveUser and sam alternate as actors.sub=tom, the multi-hop issuer, only the requestedaud, and the full nestedactchain.delegation.max.actor.chain.depth.subjectAudiencesdo not match, or are empty.delegation_helpers.py:DelegationPolicyAdmin.register()/update()acceptsubject_audiences.assert_issued_jwt()helper.