smolnar82 opened a new pull request, #1414: URL: https://github.com/apache/knox/pull/1414
[KNOX-3475](https://issues.apache.org/jira/browse/KNOX-3475) - Enforce delegation policy `status` at authorization time ## What changes were proposed in this pull request? A KnoxIDF delegation policy (RFC 8693 token exchange) carries a `status` field (`active` / `revoked`). The status was validated at the REST layer and stored, but **never read at authorization time**: `JdbcDelegationPolicyService.evaluate(...)` looked the policy up by actor and then checked headless/user/group/resource/scope, never the status. So a policy that was *revoked instead of deleted* (its row still present with `status="revoked"`) kept authorizing exchanges. This PR closes that gap: - **`gateway-spi` `DelegationPolicy`** — add canonical `STATUS_ACTIVE`/`STATUS_REVOKED` constants and an `isActive()` helper (true only for exactly `"active"`; revoked, null, or any unknown value is treated as not-active — fail-safe). - **`gateway-server` `JdbcDelegationPolicyService.evaluate()`** — new **Step 1.5** immediately after the actor lookup: `if (!policy.isActive()) return deny("policy_not_active")`. It short-circuits before any user/group/resource/scope check, so a revoked-but-present policy can never authorize. `H2DBDelegationPolicyService` (the embedded-H2 backend that runs in production) inherits `evaluate()` and therefore the check. - **`gateway-service-knoxidf` `DelegationPolicyRequest`** — point its status constants at the SPI ones (single source of truth; no behavior change). Client-facing effect: a revoked actor's delegation exchange is rejected as every other policy denial is — `400 invalid_request` / "The token exchange request is rejected by policy". ## How was this patch tested? Automated unit tests (all green): - `DelegationPolicyTest.isActiveOnlyForExactlyActiveStatus` — `active` → true; `revoked`, `null`, and an unknown value → false. - `JdbcDelegationPolicyServiceTest`: - `testEvaluateDenyRevokedPolicy` — a registered `revoked` policy denies with `policy_not_active` and `effectiveTtlSec== 0`. - `testEvaluateDenyAfterPolicyUpdatedToRevoked` — the exact JIRA scenario: an `active` policy authorizes, then the **same record** is updated to `revoked` → denied. - `H2DBDelegationPolicyServiceTest.shouldDenyEvaluateWhenPolicyRevoked` — proves the inherited check fires on the embedded-H2 subclass used in production. Run with `mvn -pl gateway-spi,gateway-server,gateway-service-knoxidf test` (build/install `gateway-spi` first, or use `-am`). ## Integration Tests Added `test_token_exchange.py::test_delegation_exchange_denied_after_policy_revoked` - the suite's first end-to-end happy-path delegation exchange. Via the `KNOXIDF_ADMIN` REST API (`knoxidf-admin` topology) it seeds an **active** `(USER, guest)` policy, proves the delegation exchange succeeds (200 + `access_token`), PUTs `status=revoked` on the **same record** (full-replace — the "revoked, not deleted" scenario), then replays the identical exchange (same tokens, same resource) and asserts it is now rejected with `400 invalid_request` / "rejected by policy". No topology changes were needed: the policy store is a gateway-wide singleton, so a policy registered via `knoxidf-admin` is seen by the exchange on `knoxidf-token-delegation`. Full docker-compose suite: ``` tests-1 | ------------------------------------------------------------------- tests-1 | Your code has been rated at 10.00/10 (previous run: 9.97/10, +0.03) tests-1 | tests-1 | Waiting for knox... tests-1 | ============================= test session starts ============================== tests-1 | platform linux -- Python 3.10.20, pytest-9.0.3, pluggy-1.6.0 tests-1 | rootdir: /tests tests-1 | collected 92 items tests-1 | tests-1 | test_health.py ..... [ 5%] tests-1 | test_k8s_delegation.py ... [ 8%] tests-1 | test_k8s_serviceaccount_validation.py ...... [ 15%] tests-1 | test_knox_admin_path_traversal.py ... [ 18%] tests-1 | test_knox_auth_service_and_ldap.py ... [ 21%] tests-1 | test_knox_configs.py . [ 22%] tests-1 | test_knox_ldap_cache.py ... [ 26%] tests-1 | test_knox_ldap_injection.py ....... [ 33%] tests-1 | test_knox_ldap_proxy_search.py ......... [ 43%] tests-1 | test_knoxauth_preauth_and_paths.py ...... [ 50%] tests-1 | test_knoxidf.py ...... [ 56%] tests-1 | test_knoxsso_redirect.py . [ 57%] tests-1 | test_knoxtoken_jwt.py .................... [ 79%] tests-1 | test_remote_auth.py ... [ 82%] tests-1 | test_remoteauth_extauthz_additional_path.py .... [ 86%] tests-1 | test_token_exchange.py ............ [100%] tests-1 | tests-1 | =============================== warnings summary =============================== ... tests-1 | tests-1 | -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html tests-1 | ----------------- generated xml file: /tests/test-results.xml ------------------ tests-1 | ======================= 92 passed, 84 warnings in 18.61s ======================= tests-1 exited with code 0 Aborting on container exit... Container compose-tests-1 Stopping Container compose-tests-1 Stopped Config w Enable Watch d Detach ``` ## UI changes N/A. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
