Skip to content

Commit 3a3b804

Browse files
committed
Knox as OIDC Provider (#1215)
* KnoxIDF - Initial commit * KnoxIDF - multi OP support * KnoxIDF - make token endpoint configurable during discovery * KnoxIDF - Code cleanup and bug fixes * KnoxIDF - Multi OP enablement improvements and code adoption to Larry's recent changes * KnoxIDF - Add REFRESH_TOKEN support * KnoxIDF - Automatically enable JdbcFederatedIdentityService when KnoxIDF is present in any topology * KnoxIDF - Added Docker-based integration tests * KnoxIDF: configurable user params provider (only LDAP for now) * KnoxIDF: add support for auth code flow with PKCE * KnoxIDF: fix an issue with the empty user params provider implementation * KnoxIDF: Refactor Docker build to use local Maven artifacts and unify CI/Dev workflows
1 parent 9c000de commit 3a3b804

80 files changed

Lines changed: 4262 additions & 196 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build/Dockerfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ FROM eclipse-temurin:17-jre
1717

1818
MAINTAINER moresandeep
1919

20-
RUN useradd -ms /bin/bash gateway
20+
# Install dependencies
21+
RUN apt-get update && apt-get install -y git && useradd -ms /bin/bash gateway
2122

2223
# Create temporary directories for extraction
2324
RUN mkdir -p /tmp/knox-artifacts /tmp/knoxshell-artifacts /knox-runtime /knoxshell /knox-runtime/knoxshell
@@ -43,6 +44,8 @@ ADD .github/workflows/build/conf/topologies/health.xml /knox-runtime/conf/topolo
4344
ADD .github/workflows/build/conf/topologies/knoxldap.xml /knox-runtime/conf/topologies/knoxldap.xml
4445
ADD .github/workflows/build/conf/topologies/remoteauth.xml /knox-runtime/conf/topologies/remoteauth.xml
4546
ADD .github/workflows/build/conf/topologies/k8sauth.xml /knox-runtime/conf/topologies/k8sauth.xml
47+
ADD .github/workflows/build/conf/topologies/knoxidf-ldap.xml /knox-runtime/conf/topologies/knoxidf-ldap.xml
48+
ADD .github/workflows/build/conf/topologies/knoxidf-token.xml /knox-runtime/conf/topologies/knoxidf-token.xml
4649

4750
RUN chown -R gateway /knox-runtime/
4851

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<topology>
3+
<gateway>
4+
<provider>
5+
<role>authentication</role>
6+
<name>ShiroProvider</name>
7+
<enabled>true</enabled>
8+
<param>
9+
<name>main.ldapRealm</name>
10+
<value>org.apache.knox.gateway.shirorealm.KnoxLdapRealm</value>
11+
</param>
12+
<param>
13+
<name>main.ldapRealm.userDnTemplate</name>
14+
<value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>
15+
</param>
16+
<param>
17+
<name>main.ldapRealm.contextFactory.url</name>
18+
<value>ldap://ldap:33389</value>
19+
</param>
20+
<param>
21+
<name>main.ldapRealm.contextFactory.authenticationMechanism</name>
22+
<value>simple</value>
23+
</param>
24+
<param>
25+
<name>urls./knoxidf/api/v1/.well-known/openid-configuration</name>
26+
<value>anon</value>
27+
</param>
28+
<param>
29+
<name>urls./knoxidf/api/v1/client/register</name>
30+
<value>anon</value>
31+
</param>
32+
<param>
33+
<name>urls./knoxidf/api/v1/authorize/callback</name>
34+
<value>anon</value>
35+
</param>
36+
<param>
37+
<name>urls./knoxidf/api/v1/jwks</name>
38+
<value>anon</value>
39+
</param>
40+
<param>
41+
<name>urls./**</name>
42+
<value>authcBasic</value>
43+
</param>
44+
</provider>
45+
<provider>
46+
<role>identity-assertion</role>
47+
<name>Default</name>
48+
<enabled>true</enabled>
49+
</provider>
50+
</gateway>
51+
52+
<service>
53+
<role>KNOXIDF</role>
54+
<param>
55+
<name>knoxidf.knox.token.ttl</name>
56+
<value>60000</value>
57+
</param>
58+
<param>
59+
<name>knoxidf.knox.token.limit.per.user</name>
60+
<value>-1</value>
61+
</param>
62+
<param>
63+
<name>token.exchange.topology.name</name>
64+
<value>knoxidf-token</value>
65+
</param>
66+
</service>
67+
</topology>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<topology>
3+
<gateway>
4+
<provider>
5+
<role>federation</role>
6+
<name>JWTProvider</name>
7+
<enabled>true</enabled>
8+
<param>
9+
<name>knox.token.exp.server-managed</name>
10+
<value>true</value>
11+
</param>
12+
</provider>
13+
<provider>
14+
<role>identity-assertion</role>
15+
<name>Default</name>
16+
<enabled>true</enabled>
17+
</provider>
18+
</gateway>
19+
20+
<service>
21+
<role>KNOXIDF</role>
22+
<param>
23+
<name>knoxidf.knox.token.ttl</name>
24+
<value>86400000</value>
25+
</param>
26+
<param>
27+
<name>knoxidf.knox.token.limit.per.user</name>
28+
<value>-1</value>
29+
</param>
30+
</service>
31+
<service>
32+
<role>KNOXTOKEN</role>
33+
<param>
34+
<name>knox.token.ttl</name>
35+
<value>60000</value>
36+
</param>
37+
<param>
38+
<name>knox.token.limit.per.user</name>
39+
<value>-1</value>
40+
</param>
41+
</service>
42+
</topology>

.github/workflows/publish-test-results.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,5 @@ jobs:
4646
commit: ${{ github.event.workflow_run.head_sha }}
4747
event_file: artifacts/Event File/event.json
4848
event_name: ${{ github.event.workflow_run.event }}
49-
files: "artifacts/**/*.xml"
49+
files: "artifacts/test-results/**/*.xml"
5050

.github/workflows/tests.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,43 @@ jobs:
6969
# Run the tests service defined in docker-compose.yml
7070
docker compose -f ./.github/workflows/compose/docker-compose.yml up --exit-code-from tests tests
7171
72+
- name: Collect Knox Logs and Conf
73+
if: always()
74+
run: |
75+
mkdir -p .github/workflows/artifacts/knox-logs
76+
mkdir -p .github/workflows/artifacts/knox-conf
77+
docker compose -f ./.github/workflows/compose/docker-compose.yml cp knox:/knox-runtime/logs .github/workflows/artifacts/knox-logs
78+
docker compose -f ./.github/workflows/compose/docker-compose.yml cp knox:/knox-runtime/conf .github/workflows/artifacts/knox-conf
79+
7280
- name: Upload Test Results
7381
if: (!cancelled())
7482
uses: actions/upload-artifact@v4
7583
with:
7684
name: test-results
7785
path: .github/workflows/tests/test-results.xml
7886

87+
- name: Archive Knox Logs
88+
if: always()
89+
run: tar -cvzf knox-logs.tar.gz -C .github/workflows/artifacts/knox-logs .
90+
91+
- name: Upload Knox Logs
92+
if: always()
93+
uses: actions/upload-artifact@v4
94+
with:
95+
name: knox-logs
96+
path: knox-logs.tar.gz
97+
98+
- name: Archive Knox Conf
99+
if: always()
100+
run: tar -cvzf knox-conf.tar.gz -C .github/workflows/artifacts/knox-conf .
101+
102+
- name: Upload Knox Conf
103+
if: always()
104+
uses: actions/upload-artifact@v4
105+
with:
106+
name: knox-conf
107+
path: knox-conf.tar.gz
108+
79109
- name: Upload Event File
80110
uses: actions/upload-artifact@v4
81111
with:

.github/workflows/tests/common_utils.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
from __future__ import annotations
1919

20+
import base64
21+
import json
2022
import os
2123
import unittest
2224
from typing import Any
@@ -72,3 +74,32 @@ def assert_hsts_header(testcase: unittest.TestCase, response: requests.Response)
7274
"""Assert the response includes the expected Strict-Transport-Security header."""
7375
testcase.assertIn(HSTS_HEADER_NAME, response.headers)
7476
testcase.assertEqual(response.headers[HSTS_HEADER_NAME], HSTS_EXPECTED_VALUE)
77+
78+
def get_token_id_display_text(uuid):
79+
"""
80+
Format the token ID for display, matching Knox's getTokenIDDisplayText logic.
81+
"""
82+
if uuid and len(uuid) == 36 and "-" in uuid:
83+
first_dash = uuid.find('-')
84+
last_dash = uuid.rfind('-')
85+
return f"{uuid[:first_dash]}...{uuid[last_dash+1:]}"
86+
return uuid
87+
88+
89+
def get_token_claim(token, claim):
90+
"""
91+
Decodes a JWT token and returns the value of the specified claim.
92+
"""
93+
try:
94+
payload_b64 = token.split('.')[1]
95+
# URL-safe base64 decoding usually needs padding adjustment
96+
missing_padding = len(payload_b64) % 4
97+
if missing_padding:
98+
payload_b64 += '=' * (4 - missing_padding)
99+
# Use urlsafe_b64decode just in case, though standard b64decode often works with padding
100+
payload_json = base64.urlsafe_b64decode(payload_b64).decode('utf-8')
101+
payload = json.loads(payload_json)
102+
return payload.get(claim)
103+
except Exception as e:
104+
print(f"Failed to decode token for claim '{claim}': {e}")
105+
return None

0 commit comments

Comments
 (0)