Skip to content

Commit 471a72f

Browse files
author
Agent
committed
Add OIDC authentication to integration tests
Deploy Dex (OIDC provider) and GLAuth (LDAP) alongside CTS in the EaaS pipeline and exercise 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: ConfigMap with two users (builder/readonly) and cts-builders group; GLAuth deployment on port 3893 (non-privileged, required by OpenShift restricted-v2 SCC); command explicitly set to /app/glauth to bypass the dumb-init ENTRYPOINT; TCP readiness probe on port 3893. - New deploy-dex task: ConfigMap with Dex config using the local password connector, two static users, and cts-integration OAuth2 client; readiness probe uses /.well-known/openid-configuration on port 5556 (the main HTTP port) rather than /healthz/ready which is only served on the telemetry port; oauth2.passwordConnector=local enables the ROPC grant; invalid scopeRemaining field removed. - Updated deploy-cts: runAfter includes deploy-glauth and deploy-dex; cts-config ConfigMap sets AUTH_BACKEND=openidc, AUTH_OPENIDC_USERINFO_URI, AUTH_LDAP_SERVER=ldap://glauth:3893, AUTH_LDAP_GROUPS, ADMINS, and ALLOWED_BUILDERS; httpd.conf gains mod_auth_openidc directives and RequireAny block allowing unauthenticated GETs while requiring Bearer token for writes. - Updated run-tests: passes AUTH_BACKEND=openidc so auth tests are not skipped. Test changes (tests/test_integration_api.py): - AuthHTTPClient subclass injects Authorization: Bearer on every request. - _get_oidc_token() obtains a real access token from Dex via ROPC grant. - Four new test functions skipped when AUTH_BACKEND != openidc: test_auth_unauthenticated_write_returns_401 test_auth_builder_can_post_compose test_auth_unauthorized_user_returns_403 test_auth_get_endpoints_accessible_without_token Generated-By: OpenCode (google-vertex-anthropic/claude-sonnet-4-6@default)
1 parent 6552ee2 commit 471a72f

2 files changed

Lines changed: 486 additions & 6 deletions

File tree

.tekton/integration-test-eaas.yaml

Lines changed: 319 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,292 @@ 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+
listen = "0.0.0.0:3893"
111+
112+
[ldaps]
113+
enabled = false
114+
115+
[backend]
116+
datastore = "config"
117+
baseDN = "dc=example,dc=com"
118+
119+
[[users]]
120+
name = "builder"
121+
unixid = 5001
122+
primarygroup = 5501
123+
passsha256 = "6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a"
124+
[[users.capabilities]]
125+
action = "search"
126+
object = "*"
127+
128+
[[users]]
129+
name = "readonly"
130+
unixid = 5002
131+
primarygroup = 5502
132+
passsha256 = "6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a"
133+
[[users.capabilities]]
134+
action = "search"
135+
object = "*"
136+
137+
[[groups]]
138+
name = "cts-builders"
139+
unixid = 5501
140+
includegroups = []
141+
142+
[[groups]]
143+
name = "readonly-users"
144+
unixid = 5502
145+
includegroups = []
146+
EOFYAML
147+
148+
kubectl apply -f - <<'EOFYAML'
149+
apiVersion: apps/v1
150+
kind: Deployment
151+
metadata:
152+
name: glauth
153+
labels:
154+
app: glauth
155+
spec:
156+
replicas: 1
157+
selector:
158+
matchLabels:
159+
app: glauth
160+
template:
161+
metadata:
162+
labels:
163+
app: glauth
164+
spec:
165+
containers:
166+
- name: glauth
167+
image: docker.io/glauth/glauth:v2.3.2
168+
command: ["/app/glauth"]
169+
args: ["-c", "/etc/glauth/glauth.cfg"]
170+
ports:
171+
- containerPort: 3893
172+
name: ldap
173+
readinessProbe:
174+
tcpSocket:
175+
port: 3893
176+
initialDelaySeconds: 3
177+
periodSeconds: 5
178+
failureThreshold: 12
179+
resources:
180+
requests:
181+
memory: "64Mi"
182+
cpu: "50m"
183+
limits:
184+
memory: "128Mi"
185+
cpu: "200m"
186+
volumeMounts:
187+
- name: glauth-config
188+
mountPath: /etc/glauth
189+
readOnly: true
190+
volumes:
191+
- name: glauth-config
192+
configMap:
193+
name: glauth-config
194+
---
195+
apiVersion: v1
196+
kind: Service
197+
metadata:
198+
name: glauth
199+
labels:
200+
app: glauth
201+
spec:
202+
ports:
203+
- port: 3893
204+
targetPort: 3893
205+
name: ldap
206+
selector:
207+
app: glauth
208+
EOFYAML
209+
210+
echo "Waiting for GLAuth to be ready..."
211+
if ! kubectl wait --for=condition=available --timeout=120s deployment/glauth; then
212+
echo "GLAuth deployment failed! Debug info:"
213+
kubectl describe deployment glauth
214+
kubectl describe pod -l app=glauth
215+
kubectl logs -l app=glauth --tail=50 || echo "No logs available"
216+
exit 1
217+
fi
218+
echo "✓ GLAuth is ready"
219+
params:
220+
- name: kubeconfig-secret
221+
value: $(tasks.provision-environment.results.secretRef)
222+
223+
- name: deploy-dex
224+
runAfter:
225+
- provision-environment
226+
taskSpec:
227+
params:
228+
- name: kubeconfig-secret
229+
type: string
230+
steps:
231+
- name: create-dex
232+
image: quay.io/konflux-ci/appstudio-utils:latest
233+
script: |
234+
#!/usr/bin/env bash
235+
set -euo pipefail
236+
237+
KUBECONFIG=/tmp/kubeconfig
238+
kubectl get secret $(params.kubeconfig-secret) -o jsonpath='{.data.kubeconfig}' | base64 -d > $KUBECONFIG
239+
export KUBECONFIG
240+
241+
echo "=========================================="
242+
echo "Deploying Dex OIDC Provider"
243+
echo "=========================================="
244+
245+
kubectl apply -f - <<'EOFYAML'
246+
apiVersion: v1
247+
kind: ConfigMap
248+
metadata:
249+
name: dex-config
250+
data:
251+
config.yaml: |
252+
issuer: http://dex:5556
253+
254+
storage:
255+
type: memory
256+
257+
web:
258+
http: 0.0.0.0:5556
259+
260+
logger:
261+
level: debug
262+
263+
enablePasswordDB: true
264+
265+
staticPasswords:
266+
- email: builder@example.com
267+
hash: "$2y$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYbe.k/104vz0GatBLa"
268+
username: builder
269+
userID: "builder-id"
270+
- email: readonly@example.com
271+
hash: "$2y$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYbe.k/104vz0GatBLa"
272+
username: readonly
273+
userID: "readonly-id"
274+
275+
staticClients:
276+
- id: cts-integration
277+
secret: cts-integration-secret
278+
name: CTS Integration
279+
redirectURIs:
280+
- http://cts:8080/redirect_uri
281+
grantTypes:
282+
- password
283+
- authorization_code
284+
285+
oauth2:
286+
skipApprovalScreen: true
287+
passwordConnector: local
288+
EOFYAML
289+
290+
kubectl apply -f - <<'EOFYAML'
291+
apiVersion: apps/v1
292+
kind: Deployment
293+
metadata:
294+
name: dex
295+
labels:
296+
app: dex
297+
spec:
298+
replicas: 1
299+
selector:
300+
matchLabels:
301+
app: dex
302+
template:
303+
metadata:
304+
labels:
305+
app: dex
306+
spec:
307+
containers:
308+
- name: dex
309+
image: ghcr.io/dexidp/dex:v2.41.1
310+
args: ["dex", "serve", "/etc/dex/config.yaml"]
311+
ports:
312+
- containerPort: 5556
313+
name: http
314+
resources:
315+
requests:
316+
memory: "64Mi"
317+
cpu: "50m"
318+
limits:
319+
memory: "256Mi"
320+
cpu: "500m"
321+
readinessProbe:
322+
httpGet:
323+
path: /.well-known/openid-configuration
324+
port: 5556
325+
initialDelaySeconds: 5
326+
periodSeconds: 5
327+
timeoutSeconds: 5
328+
failureThreshold: 12
329+
volumeMounts:
330+
- name: dex-config
331+
mountPath: /etc/dex
332+
readOnly: true
333+
volumes:
334+
- name: dex-config
335+
configMap:
336+
name: dex-config
337+
---
338+
apiVersion: v1
339+
kind: Service
340+
metadata:
341+
name: dex
342+
labels:
343+
app: dex
344+
spec:
345+
ports:
346+
- port: 5556
347+
targetPort: 5556
348+
name: http
349+
selector:
350+
app: dex
351+
EOFYAML
352+
353+
echo "Waiting for Dex to be ready..."
354+
if ! kubectl wait --for=condition=available --timeout=180s deployment/dex; then
355+
echo "Dex deployment failed! Debug info:"
356+
kubectl describe deployment dex
357+
kubectl describe pod -l app=dex
358+
kubectl logs -l app=dex --tail=50 || echo "No logs available"
359+
exit 1
360+
fi
361+
echo "✓ Dex is ready"
362+
params:
363+
- name: kubeconfig-secret
364+
value: $(tasks.provision-environment.results.secretRef)
365+
80366
- name: deploy-database
81367
runAfter:
82368
- provision-environment
@@ -215,6 +501,8 @@ spec:
215501
- name: deploy-cts
216502
runAfter:
217503
- deploy-database
504+
- deploy-glauth
505+
- deploy-dex
218506
taskSpec:
219507
params:
220508
- name: kubeconfig-secret
@@ -241,7 +529,7 @@ spec:
241529
echo "Image: $IMAGE"
242530
243531
# Create ConfigMap with production configuration and httpd config for CTS
244-
kubectl apply -f - <<EOF
532+
kubectl apply -f - <<'EOFYAML'
245533
apiVersion: v1
246534
kind: ConfigMap
247535
metadata:
@@ -251,8 +539,16 @@ spec:
251539
from conf.config import BaseConfiguration
252540
253541
class ProdConfiguration(BaseConfiguration):
254-
AUTH_BACKEND = "noauth"
542+
AUTH_BACKEND = "openidc"
255543
SQLALCHEMY_DATABASE_URI = "postgresql://cts:cts-test@cts-db:5432/cts"
544+
AUTH_OPENIDC_USERINFO_URI = "http://dex:5556/userinfo"
545+
AUTH_OPENIDC_REQUIRED_SCOPES = ["openid"]
546+
AUTH_LDAP_SERVER = "ldap://glauth:3893"
547+
AUTH_LDAP_GROUPS = [
548+
("ou=groups,dc=example,dc=com", "(&(objectClass=posixGroup)(memberUid={0}))"),
549+
]
550+
ADMINS = {"groups": [], "users": ["builder"]}
551+
ALLOWED_BUILDERS = {"groups": [], "users": ["builder"]}
256552
httpd.conf: |
257553
ServerRoot "/etc/httpd"
258554
PidFile /tmp/httpd.pid
@@ -268,15 +564,32 @@ spec:
268564
269565
Include conf.modules.d/*.conf
270566
567+
OIDCProviderMetadataURL http://dex:5556/.well-known/openid-configuration
568+
OIDCOAuthVerifyJwksUri http://dex:5556/keys
569+
OIDCClientID cts-integration
570+
OIDCClientSecret cts-integration-secret
571+
OIDCRedirectURI http://cts:8080/redirect_uri
572+
OIDCCryptoPassphrase changeme
573+
OIDCRemoteUserClaim preferred_username
574+
OIDCOAuthRemoteUserClaim preferred_username
575+
271576
WSGISocketPrefix /tmp/wsgi
272577
WSGIDaemonProcess cts threads=5 home=/usr/share/cts
273578
WSGIScriptAlias / /usr/share/cts/cts.wsgi
274579
275580
<Directory /usr/share/cts>
276581
WSGIProcessGroup cts
277582
WSGIApplicationGroup %{GLOBAL}
583+
AuthType openid-connect
584+
<RequireAny>
585+
<RequireAll>
586+
Require expr %{REQUEST_URI} !~ /userinfo/
587+
Require method GET
588+
</RequireAll>
589+
Require valid-user
590+
</RequireAny>
278591
</Directory>
279-
EOF
592+
EOFYAML
280593
281594
# Deploy CTS
282595
kubectl apply -f - <<EOF
@@ -478,9 +791,9 @@ spec:
478791
set -ex
479792
export HOME=/tmp
480793
481-
echo 'Installing pytest...'
794+
echo 'Installing pytest and requests...'
482795
python3 -m ensurepip
483-
python3 -m pip install --user pytest
796+
python3 -m pip install --user pytest requests
484797
485798
echo ''
486799
echo 'Cloning repository...'
@@ -492,7 +805,7 @@ spec:
492805
493806
echo ''
494807
echo 'Running pytest...'
495-
CTS_URL=http://cts:8080 python3 -m pytest tests/test_integration_api.py -v -s -o addopts=
808+
CTS_URL=http://cts:8080 AUTH_BACKEND=openidc python3 -m pytest tests/test_integration_api.py -v -s -o addopts=
496809
"
497810
TEST_RESULT=$?
498811
set -e

0 commit comments

Comments
 (0)