Skip to content

Commit c30ffd2

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): creates a ConfigMap with a GLAuth config defining two users (builder/readonly) and one group (cts-builders), then deploys GLAuth on port 3893. - New deploy-dex task (parallel with deploy-glauth): creates a ConfigMap with a Dex config using the password connector and a static OAuth2 client (cts-integration), then deploys Dex on port 5556. - Updated deploy-cts: runAfter now 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 including OIDCOAuthIntrospectionEndpoint pointing at Dex's token introspection endpoint (which accepts http:// URLs, unlike OIDCOAuthVerifyJwksUri) together with OIDCOAuthClientID/Secret so that mod_auth_openidc can validate Bearer tokens. OIDCSSLValidateServer Off and OIDCOAuthSSLValidateServer Off allow the HTTP-only Dex endpoint in the test namespace. The <RequireAny> block allows unauthenticated GET requests while requiring a valid Bearer token for writes. - Updated run-tests: installs requests alongside pytest and passes AUTH_BACKEND=openidc so the auth tests are not skipped. 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) under OIDC or a plain HTTPClient in noauth mode; used by the five pre-existing workflow tests so they continue to pass in both modes. - 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 c30ffd2

2 files changed

Lines changed: 540 additions & 32 deletions

File tree

.tekton/integration-test-eaas.yaml

Lines changed: 324 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,36 @@ 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+
OIDCOAuthIntrospectionEndpoint http://dex:5556/token/introspect
578+
OIDCOAuthClientID cts-integration
579+
OIDCOAuthClientSecret cts-integration-secret
580+
271581
WSGISocketPrefix /tmp/wsgi
272582
WSGIDaemonProcess cts threads=5 home=/usr/share/cts
273583
WSGIScriptAlias / /usr/share/cts/cts.wsgi
274584
275585
<Directory /usr/share/cts>
276586
WSGIProcessGroup cts
277587
WSGIApplicationGroup %{GLOBAL}
588+
AuthType openid-connect
589+
<RequireAny>
590+
<RequireAll>
591+
Require expr %{REQUEST_URI} !~ /userinfo/
592+
Require method GET
593+
</RequireAll>
594+
Require valid-user
595+
</RequireAny>
278596
</Directory>
279-
EOF
597+
EOFYAML
280598
281599
# Deploy CTS
282600
kubectl apply -f - <<EOF
@@ -478,9 +796,9 @@ spec:
478796
set -ex
479797
export HOME=/tmp
480798
481-
echo 'Installing pytest...'
799+
echo 'Installing pytest and requests...'
482800
python3 -m ensurepip
483-
python3 -m pip install --user pytest
801+
python3 -m pip install --user pytest requests
484802
485803
echo ''
486804
echo 'Cloning repository...'
@@ -492,7 +810,7 @@ spec:
492810
493811
echo ''
494812
echo 'Running pytest...'
495-
CTS_URL=http://cts:8080 python3 -m pytest tests/test_integration_api.py -v -s -o addopts=
813+
CTS_URL=http://cts:8080 AUTH_BACKEND=openidc python3 -m pytest tests/test_integration_api.py -v -s -o addopts=
496814
"
497815
TEST_RESULT=$?
498816
set -e

0 commit comments

Comments
 (0)