Skip to content

Commit 65ce1a0

Browse files
author
Agent
committed
Add OIDC authentication to integration tests
Deploys Dex (OIDC provider) and GLAuth (LDAP) alongside CTS in the EaaS pipeline and exercises the full mod_auth_openidc -> load_openidc_user -> get_user_info -> query_ldap_groups -> has_role auth stack end-to-end. Pipeline changes (.tekton/integration-test-eaas.yaml): - New deploy-glauth task (parallel with deploy-dex after provision-environment): ConfigMap with GLAuth config defining builder/readonly users and cts-builders group, then deploys GLAuth on port 3893. - New deploy-dex task (parallel with deploy-glauth): ConfigMap with Dex config using the password connector and a static OAuth2 client (cts-integration), then deploys Dex on port 5556. OIDCProviderMetadataURL points mod_auth_openidc to the Dex discovery document; OIDCSSLValidateServer Off and OIDCOAuthSSLValidateServer Off allow the HTTP-only endpoints in the test namespace. OIDCOAuthVerifyJwksUri is intentionally omitted because mod_auth_openidc rejects http:// URLs for that directive at parse time and the JWKS URI is fetched automatically from the discovery document. - Updated deploy-cts: runAfter includes deploy-glauth and deploy-dex. The cts-config ConfigMap sets AUTH_BACKEND=openidc, AUTH_OPENIDC_USERINFO_URI, AUTH_LDAP_SERVER, AUTH_LDAP_GROUPS, ADMINS, and ALLOWED_BUILDERS. The httpd.conf gains mod_auth_openidc directives and a RequireAny block that allows unauthenticated GET requests while requiring a valid Bearer token for writes. - Updated run-tests: installs requests alongside pytest and passes AUTH_BACKEND=openidc to the test runner. Test changes (tests/test_integration_api.py): - AuthHTTPClient: HTTPClient subclass that injects Authorization: Bearer on every request. - _get_oidc_token(): obtains a real access token from Dex via the ROPC grant. - write_http_client fixture: returns an AuthHTTPClient (builder token) when AUTH_BACKEND=openidc, or a plain HTTPClient in noauth mode. Workflow tests that POST/PATCH use this fixture so they run correctly in both configurations. - auth_http_client_builder / auth_http_client_readonly fixtures: OIDC-only fixtures skipped when AUTH_BACKEND != openidc. - Four new OIDC test functions: unauthenticated write returns 401, builder can POST, readonly user gets 403, GET endpoints remain accessible without token. Generated-By: OpenCode (google-vertex-anthropic/claude-sonnet-4-6@default)
1 parent 6552ee2 commit 65ce1a0

2 files changed

Lines changed: 533 additions & 32 deletions

File tree

.tekton/integration-test-eaas.yaml

Lines changed: 321 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,293 @@ spec:
7777
- name: ownerUid
7878
value: $(context.pipelineRun.uid)
7979

80+
- name: deploy-glauth
81+
runAfter:
82+
- provision-environment
83+
taskSpec:
84+
params:
85+
- name: kubeconfig-secret
86+
type: string
87+
steps:
88+
- name: create-glauth
89+
image: quay.io/konflux-ci/appstudio-utils:latest
90+
script: |
91+
#!/usr/bin/env bash
92+
set -euo pipefail
93+
94+
KUBECONFIG=/tmp/kubeconfig
95+
kubectl get secret $(params.kubeconfig-secret) -o jsonpath='{.data.kubeconfig}' | base64 -d > $KUBECONFIG
96+
export KUBECONFIG
97+
98+
echo "=========================================="
99+
echo "Deploying GLAuth LDAP Server"
100+
echo "=========================================="
101+
102+
kubectl apply -f - <<'EOFYAML'
103+
apiVersion: v1
104+
kind: ConfigMap
105+
metadata:
106+
name: glauth-config
107+
data:
108+
glauth.cfg: |
109+
[ldap]
110+
enabled = true
111+
listen = "0.0.0.0:3893"
112+
113+
[ldaps]
114+
enabled = false
115+
116+
[backend]
117+
datastore = "config"
118+
baseDN = "dc=example,dc=com"
119+
120+
[[users]]
121+
name = "builder"
122+
unixid = 5001
123+
primarygroup = 5501
124+
passsha256 = "6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a"
125+
[[users.capabilities]]
126+
action = "search"
127+
object = "*"
128+
129+
[[users]]
130+
name = "readonly"
131+
unixid = 5002
132+
primarygroup = 5502
133+
passsha256 = "6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a"
134+
[[users.capabilities]]
135+
action = "search"
136+
object = "*"
137+
138+
[[groups]]
139+
name = "cts-builders"
140+
unixid = 5501
141+
includegroups = []
142+
143+
[[groups]]
144+
name = "readonly-users"
145+
unixid = 5502
146+
includegroups = []
147+
EOFYAML
148+
149+
kubectl apply -f - <<'EOFYAML'
150+
apiVersion: apps/v1
151+
kind: Deployment
152+
metadata:
153+
name: glauth
154+
labels:
155+
app: glauth
156+
spec:
157+
replicas: 1
158+
selector:
159+
matchLabels:
160+
app: glauth
161+
template:
162+
metadata:
163+
labels:
164+
app: glauth
165+
spec:
166+
containers:
167+
- name: glauth
168+
image: docker.io/glauth/glauth:v2.3.2
169+
command: ["/app/glauth"]
170+
args: ["-c", "/etc/glauth/glauth.cfg"]
171+
ports:
172+
- containerPort: 3893
173+
name: ldap
174+
readinessProbe:
175+
tcpSocket:
176+
port: 3893
177+
initialDelaySeconds: 3
178+
periodSeconds: 5
179+
failureThreshold: 12
180+
resources:
181+
requests:
182+
memory: "64Mi"
183+
cpu: "50m"
184+
limits:
185+
memory: "128Mi"
186+
cpu: "200m"
187+
volumeMounts:
188+
- name: glauth-config
189+
mountPath: /etc/glauth
190+
readOnly: true
191+
volumes:
192+
- name: glauth-config
193+
configMap:
194+
name: glauth-config
195+
---
196+
apiVersion: v1
197+
kind: Service
198+
metadata:
199+
name: glauth
200+
labels:
201+
app: glauth
202+
spec:
203+
ports:
204+
- port: 3893
205+
targetPort: 3893
206+
name: ldap
207+
selector:
208+
app: glauth
209+
EOFYAML
210+
211+
echo "Waiting for GLAuth to be ready..."
212+
if ! kubectl wait --for=condition=available --timeout=120s deployment/glauth; then
213+
echo "GLAuth deployment failed! Debug info:"
214+
kubectl describe deployment glauth
215+
kubectl describe pod -l app=glauth
216+
kubectl logs -l app=glauth --tail=50 || echo "No logs available"
217+
exit 1
218+
fi
219+
echo "✓ GLAuth is ready"
220+
params:
221+
- name: kubeconfig-secret
222+
value: $(tasks.provision-environment.results.secretRef)
223+
224+
- name: deploy-dex
225+
runAfter:
226+
- provision-environment
227+
taskSpec:
228+
params:
229+
- name: kubeconfig-secret
230+
type: string
231+
steps:
232+
- name: create-dex
233+
image: quay.io/konflux-ci/appstudio-utils:latest
234+
script: |
235+
#!/usr/bin/env bash
236+
set -euo pipefail
237+
238+
KUBECONFIG=/tmp/kubeconfig
239+
kubectl get secret $(params.kubeconfig-secret) -o jsonpath='{.data.kubeconfig}' | base64 -d > $KUBECONFIG
240+
export KUBECONFIG
241+
242+
echo "=========================================="
243+
echo "Deploying Dex OIDC Provider"
244+
echo "=========================================="
245+
246+
kubectl apply -f - <<'EOFYAML'
247+
apiVersion: v1
248+
kind: ConfigMap
249+
metadata:
250+
name: dex-config
251+
data:
252+
config.yaml: |
253+
issuer: http://dex:5556
254+
255+
storage:
256+
type: memory
257+
258+
web:
259+
http: 0.0.0.0:5556
260+
261+
logger:
262+
level: debug
263+
264+
enablePasswordDB: true
265+
266+
staticPasswords:
267+
- email: builder@example.com
268+
hash: "$2y$10$6cZyh42YBb2Q5.fE9nj3mu3UHs21NUmVP2fpU63EM3/ecJuHVscEC"
269+
username: builder
270+
userID: "builder-id"
271+
- email: readonly@example.com
272+
hash: "$2y$10$6cZyh42YBb2Q5.fE9nj3mu3UHs21NUmVP2fpU63EM3/ecJuHVscEC"
273+
username: readonly
274+
userID: "readonly-id"
275+
276+
staticClients:
277+
- id: cts-integration
278+
secret: cts-integration-secret
279+
name: CTS Integration
280+
redirectURIs:
281+
- http://cts:8080/redirect_uri
282+
grantTypes:
283+
- password
284+
- authorization_code
285+
286+
oauth2:
287+
skipApprovalScreen: true
288+
passwordConnector: local
289+
EOFYAML
290+
291+
kubectl apply -f - <<'EOFYAML'
292+
apiVersion: apps/v1
293+
kind: Deployment
294+
metadata:
295+
name: dex
296+
labels:
297+
app: dex
298+
spec:
299+
replicas: 1
300+
selector:
301+
matchLabels:
302+
app: dex
303+
template:
304+
metadata:
305+
labels:
306+
app: dex
307+
spec:
308+
containers:
309+
- name: dex
310+
image: ghcr.io/dexidp/dex:v2.41.1
311+
args: ["dex", "serve", "/etc/dex/config.yaml"]
312+
ports:
313+
- containerPort: 5556
314+
name: http
315+
resources:
316+
requests:
317+
memory: "64Mi"
318+
cpu: "50m"
319+
limits:
320+
memory: "256Mi"
321+
cpu: "500m"
322+
readinessProbe:
323+
httpGet:
324+
path: /.well-known/openid-configuration
325+
port: 5556
326+
initialDelaySeconds: 5
327+
periodSeconds: 5
328+
timeoutSeconds: 5
329+
failureThreshold: 12
330+
volumeMounts:
331+
- name: dex-config
332+
mountPath: /etc/dex
333+
readOnly: true
334+
volumes:
335+
- name: dex-config
336+
configMap:
337+
name: dex-config
338+
---
339+
apiVersion: v1
340+
kind: Service
341+
metadata:
342+
name: dex
343+
labels:
344+
app: dex
345+
spec:
346+
ports:
347+
- port: 5556
348+
targetPort: 5556
349+
name: http
350+
selector:
351+
app: dex
352+
EOFYAML
353+
354+
echo "Waiting for Dex to be ready..."
355+
if ! kubectl wait --for=condition=available --timeout=180s deployment/dex; then
356+
echo "Dex deployment failed! Debug info:"
357+
kubectl describe deployment dex
358+
kubectl describe pod -l app=dex
359+
kubectl logs -l app=dex --tail=50 || echo "No logs available"
360+
exit 1
361+
fi
362+
echo "✓ Dex is ready"
363+
params:
364+
- name: kubeconfig-secret
365+
value: $(tasks.provision-environment.results.secretRef)
366+
80367
- name: deploy-database
81368
runAfter:
82369
- provision-environment
@@ -215,6 +502,8 @@ spec:
215502
- name: deploy-cts
216503
runAfter:
217504
- deploy-database
505+
- deploy-glauth
506+
- deploy-dex
218507
taskSpec:
219508
params:
220509
- name: kubeconfig-secret
@@ -241,7 +530,7 @@ spec:
241530
echo "Image: $IMAGE"
242531
243532
# Create ConfigMap with production configuration and httpd config for CTS
244-
kubectl apply -f - <<EOF
533+
kubectl apply -f - <<'EOFYAML'
245534
apiVersion: v1
246535
kind: ConfigMap
247536
metadata:
@@ -251,8 +540,16 @@ spec:
251540
from conf.config import BaseConfiguration
252541
253542
class ProdConfiguration(BaseConfiguration):
254-
AUTH_BACKEND = "noauth"
543+
AUTH_BACKEND = "openidc"
255544
SQLALCHEMY_DATABASE_URI = "postgresql://cts:cts-test@cts-db:5432/cts"
545+
AUTH_OPENIDC_USERINFO_URI = "http://dex:5556/userinfo"
546+
AUTH_OPENIDC_REQUIRED_SCOPES = ["openid"]
547+
AUTH_LDAP_SERVER = "ldap://glauth:3893"
548+
AUTH_LDAP_GROUPS = [
549+
("ou=groups,dc=example,dc=com", "(&(objectClass=posixGroup)(memberUid={0}))"),
550+
]
551+
ADMINS = {"groups": [], "users": ["builder"]}
552+
ALLOWED_BUILDERS = {"groups": [], "users": ["builder"]}
256553
httpd.conf: |
257554
ServerRoot "/etc/httpd"
258555
PidFile /tmp/httpd.pid
@@ -268,15 +565,33 @@ spec:
268565
269566
Include conf.modules.d/*.conf
270567
568+
OIDCProviderMetadataURL http://dex:5556/.well-known/openid-configuration
569+
OIDCSSLValidateServer Off
570+
OIDCOAuthSSLValidateServer Off
571+
OIDCClientID cts-integration
572+
OIDCClientSecret cts-integration-secret
573+
OIDCRedirectURI http://cts:8080/redirect_uri
574+
OIDCCryptoPassphrase changeme
575+
OIDCRemoteUserClaim preferred_username
576+
OIDCOAuthRemoteUserClaim preferred_username
577+
271578
WSGISocketPrefix /tmp/wsgi
272579
WSGIDaemonProcess cts threads=5 home=/usr/share/cts
273580
WSGIScriptAlias / /usr/share/cts/cts.wsgi
274581
275582
<Directory /usr/share/cts>
276583
WSGIProcessGroup cts
277584
WSGIApplicationGroup %{GLOBAL}
585+
AuthType openid-connect
586+
<RequireAny>
587+
<RequireAll>
588+
Require expr %{REQUEST_URI} !~ /userinfo/
589+
Require method GET
590+
</RequireAll>
591+
Require valid-user
592+
</RequireAny>
278593
</Directory>
279-
EOF
594+
EOFYAML
280595
281596
# Deploy CTS
282597
kubectl apply -f - <<EOF
@@ -478,9 +793,9 @@ spec:
478793
set -ex
479794
export HOME=/tmp
480795
481-
echo 'Installing pytest...'
796+
echo 'Installing pytest and requests...'
482797
python3 -m ensurepip
483-
python3 -m pip install --user pytest
798+
python3 -m pip install --user pytest requests
484799
485800
echo ''
486801
echo 'Cloning repository...'
@@ -492,7 +807,7 @@ spec:
492807
493808
echo ''
494809
echo 'Running pytest...'
495-
CTS_URL=http://cts:8080 python3 -m pytest tests/test_integration_api.py -v -s -o addopts=
810+
CTS_URL=http://cts:8080 AUTH_BACKEND=openidc python3 -m pytest tests/test_integration_api.py -v -s -o addopts=
496811
"
497812
TEST_RESULT=$?
498813
set -e

0 commit comments

Comments
 (0)