Skip to content

Commit

Permalink
Add integration test for OIDC authentication
Browse files Browse the repository at this point in the history
Co-authored-by: Steve Breker <[email protected]>
  • Loading branch information
replaceafill and sbreker authored Sep 30, 2024
1 parent 46a1eb8 commit 937f41b
Show file tree
Hide file tree
Showing 11 changed files with 398 additions and 13 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/oidc-integration-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: "OIDC Integration Test"
on:
workflow_dispatch:
jobs:
test:
name: "Test"
runs-on: "ubuntu-24.04"
steps:
- name: "Check out repository"
uses: "actions/checkout@v4"
- name: "Save user id"
id: user_id
run: |
echo "user_id=$(id -u)" >> $GITHUB_OUTPUT
- name: "Save group id"
id: group_id
run: |
echo "group_id=$(id -g)" >> $GITHUB_OUTPUT
- name: "Set up buildx"
uses: "docker/setup-buildx-action@v3"
- name: "Run tests"
run: |
./run.sh
shell: "bash"
working-directory: "tests/integration"
env:
USER_ID: ${{ steps.user_id.outputs.user_id }}
GROUP_ID: ${{ steps.group_id.outputs.group_id }}
UBUNTU_VERSION: "22.04"
PYTHON_VERSION: "3.9"
COMPOSE_DOCKER_CLI_BUILD: 1
DOCKER_BUILDKIT: 1
PYTEST_ADDOPTS: -vv
17 changes: 17 additions & 0 deletions hack/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,21 @@ FROM base AS archivematica-tests

# -----------------------------------------------------------------------------

FROM base AS archivematica-dashboard-integration-tests

USER root

RUN set -ex \
&& python3 -m playwright install-deps firefox

USER archivematica

RUN set -ex \
&& mkdir -p /var/archivematica/.cache/ms-playwright \
&& python3 -m playwright install firefox

ENV PYTHONPATH=/src/src/dashboard/src/:/src/src/archivematicaCommon/lib/

# -----------------------------------------------------------------------------

FROM ${TARGET}
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ module = [
"tests.archivematicaCommon.test_execute_functions",
"tests.dashboard.fpr.test_views",
"tests.dashboard.test_oidc",
"tests.integration.test_oidc_auth",
"tests.MCPClient.conftest",
"tests.MCPClient.test_characterize_file",
"tests.MCPClient.test_has_packages",
Expand Down
6 changes: 6 additions & 0 deletions requirements-dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@ pytest
pytest-cov
pytest-django
pytest-mock
pytest-playwright
pytest-randomly
tox

# playwright requires specific versions of greenlet which may clash with our
# gevent dependency in requirements.txt.
# See https://github.com/microsoft/playwright-python/issues/2190
git+https://github.com/microsoft/playwright-python.git@d9cdfbb1e178b6770625e9f857139aff77516af0#egg=playwright
23 changes: 21 additions & 2 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,11 @@ gearman3 @ git+https://github.com/artefactual-labs/python-gearman.git@b68efc868c
# via -r requirements.txt
gevent==24.2.1
# via -r requirements.txt
greenlet==3.1.0
greenlet==3.1.1
# via
# -r requirements.txt
# gevent
# playwright
gunicorn==23.0.0
# via -r requirements.txt
idna==3.10
Expand Down Expand Up @@ -169,11 +170,15 @@ platformdirs==4.3.6
# via
# tox
# virtualenv
playwright @ git+https://github.com/microsoft/playwright-python.git@d9cdfbb1e178b6770625e9f857139aff77516af0
# via
# -r requirements-dev.in
# pytest-playwright
pluggy==1.5.0
# via
# pytest
# tox
prometheus-client==0.20.0
prometheus-client==0.21.0
# via
# -r requirements.txt
# django-prometheus
Expand All @@ -190,6 +195,8 @@ pycparser==2.22
# via
# -r requirements.txt
# cffi
pyee==12.0.0
# via playwright
pyopenssl==24.2.1
# via
# -r requirements.txt
Expand All @@ -203,16 +210,22 @@ pyproject-hooks==1.1.0
pytest==8.3.3
# via
# -r requirements-dev.in
# pytest-base-url
# pytest-cov
# pytest-django
# pytest-mock
# pytest-playwright
# pytest-randomly
pytest-base-url==2.1.0
# via pytest-playwright
pytest-cov==5.0.0
# via -r requirements-dev.in
pytest-django==4.9.0
# via -r requirements-dev.in
pytest-mock==3.14.0
# via -r requirements-dev.in
pytest-playwright==0.5.2
# via -r requirements-dev.in
pytest-randomly==3.15.0
# via -r requirements-dev.in
python-cas==1.6.0
Expand All @@ -232,6 +245,8 @@ python-mimeparse==2.0.0
# via
# -r requirements.txt
# django-tastypie
python-slugify==8.0.4
# via pytest-playwright
referencing==0.35.1
# via
# -r requirements.txt
Expand All @@ -244,6 +259,7 @@ requests==2.32.3
# amclient
# mozilla-django-oidc
# opf-fido
# pytest-base-url
# python-cas
rpds-py==0.20.0
# via
Expand All @@ -260,6 +276,8 @@ sqlparse==0.5.1
# via
# -r requirements.txt
# django
text-unidecode==1.3
# via python-slugify
tomli==2.0.1
# via
# build
Expand All @@ -274,6 +292,7 @@ typing-extensions==4.12.2
# via
# -r requirements.txt
# asgiref
# pyee
unidecode==1.3.8
# via -r requirements.txt
urllib3==2.2.3
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ gearman3 @ git+https://github.com/artefactual-labs/python-gearman.git@b68efc868c
# via -r requirements.in
gevent==24.2.1
# via -r requirements.in
greenlet==3.1.0
greenlet==3.1.1
# via gevent
gunicorn==23.0.0
# via -r requirements.in
Expand Down Expand Up @@ -102,7 +102,7 @@ orjson==3.10.7
# via -r requirements.in
packaging==24.1
# via gunicorn
prometheus-client==0.20.0
prometheus-client==0.21.0
# via
# -r requirements.in
# django-prometheus
Expand Down
16 changes: 7 additions & 9 deletions tests/dashboard/test_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


@pytest.mark.parametrize(
"host_and_port, base_url",
"host_and_port, expected_result",
[
((None, None), ""),
(("", ""), ""),
Expand All @@ -19,15 +19,15 @@
(("http://foobar.tld:789/asdf", "8089"), "http://foobar.tld:789/asdf"),
],
)
def test_0066_get_base_url(host_and_port, base_url):
def test_0066_get_base_url(host_and_port, expected_result):
"""Test _get_baseurl."""
assert base_url == mod._get_base_url(*host_and_port), "Failed with args %s" % (
host_and_port
assert expected_result == mod._get_base_url(*host_and_port), (
"Failed with args %s" % (host_and_port)
)


@pytest.mark.parametrize(
"base_url, host_and_port",
"url, expected_result",
[
(None, ("", "")),
("", ("", "")),
Expand All @@ -38,8 +38,6 @@ def test_0066_get_base_url(host_and_port, base_url):
("http://foobar.tld:8089/subpath", ("foobar.tld", "8089")),
],
)
def test_0066_get_host_and_port(base_url, host_and_port):
def test_0066_get_host_and_port(url, expected_result):
"""Test _get_host_and_port."""
assert host_and_port == mod._get_host_and_port(
base_url
), f"Failed with arg {base_url}"
assert expected_result == mod._get_host_and_port(url), f"Failed with arg {url}"
84 changes: 84 additions & 0 deletions tests/integration/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: am-integration

services:

mysql:
image: "percona:8.0"
command: "--character-set-server=utf8mb4 --collation-server=utf8mb4_0900_ai_ci"
environment:
MYSQL_ROOT_PASSWORD: "root"
# These are used in the settings.testmysql modules
MYSQL_USER: "archivematica"
MYSQL_PASSWORD: "demo"
MYSQL_DATABASE: "test_DASHBOARDTEST"
cap_add:
- "SYS_NICE"
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "127.0.0.1"]
interval: 5s
timeout: 5s
retries: 5
start_period: 15s

archivematica-dashboard:
build:
context: "../../"
dockerfile: "hack/Dockerfile"
args:
TARGET: "archivematica-dashboard-integration-tests"
USER_ID: ${USER_ID:-1000}
GROUP_ID: ${GROUP_ID:-1000}
UBUNTU_VERSION: ${UBUNTU_VERSION:-22.04}
PYTHON_VERSION: ${PYTHON_VERSION:-3.9}
command: ["pytest", "--browser", "firefox", "/src/tests/integration/"]
hostname: "archivematica-dashboard"
environment:
PYTEST_ADDOPTS: ${PYTEST_ADDOPTS:-}
RUN_INTEGRATION_TESTS: "true"
DJANGO_LIVE_TEST_SERVER_ADDRESS: "archivematica-dashboard:8000"
DJANGO_ALLOW_ASYNC_UNSAFE: true
FORWARDED_ALLOW_IPS: "*"
AM_GUNICORN_ACCESSLOG: "/dev/null"
AM_GUNICORN_RELOAD: "true"
AM_GUNICORN_RELOAD_ENGINE: "auto"
DJANGO_SETTINGS_MODULE: "settings.testmysql"
ARCHIVEMATICA_DASHBOARD_DASHBOARD_GEARMAN_SERVER: "gearmand:4730"
ARCHIVEMATICA_DASHBOARD_DASHBOARD_ELASTICSEARCH_SERVER: "elasticsearch:9200"
ARCHIVEMATICA_DASHBOARD_DASHBOARD_PROMETHEUS_ENABLED: "1"
ARCHIVEMATICA_DASHBOARD_CLIENT_USER: "archivematica"
ARCHIVEMATICA_DASHBOARD_CLIENT_PASSWORD: "demo"
ARCHIVEMATICA_DASHBOARD_CLIENT_HOST: "mysql"
ARCHIVEMATICA_DASHBOARD_CLIENT_DATABASE: "MCP"
ARCHIVEMATICA_DASHBOARD_SEARCH_ENABLED: "${AM_SEARCH_ENABLED:-true}"
ARCHIVEMATICA_DASHBOARD_OIDC_AUTHENTICATION: "true"
OIDC_RP_CLIENT_ID: "am-dashboard"
OIDC_RP_CLIENT_SECRET: "example-secret"
OIDC_OP_AUTHORIZATION_ENDPOINT: "http://keycloak:8080/realms/demo/protocol/openid-connect/auth"
OIDC_OP_TOKEN_ENDPOINT: "http://keycloak:8080/realms/demo/protocol/openid-connect/token"
OIDC_OP_USER_ENDPOINT: "http://keycloak:8080/realms/demo/protocol/openid-connect/userinfo"
OIDC_OP_JWKS_ENDPOINT: "http://keycloak:8080/realms/demo/protocol/openid-connect/certs"
OIDC_OP_LOGOUT_ENDPOINT: "http://keycloak:8080/realms/demo/protocol/openid-connect/logout"
OIDC_RP_SIGN_ALGO: "RS256"
volumes:
- "../../:/src"
depends_on:
mysql:
condition: service_healthy
links:
- "mysql"
- "keycloak"

keycloak:
image: "quay.io/keycloak/keycloak:latest"
command: ["start-dev", "--import-realm"]
restart: "unless-stopped"
environment:
KEYCLOAK_ADMIN: "admin"
KEYCLOAK_ADMIN_PASSWORD: "admin"
KC_METRICS_ENABLED: true
KC_LOG_LEVEL: "INFO"
ports:
- 8080:8080
volumes:
- "./etc/keycloak/realm.json:/opt/keycloak/data/import/realm.json:ro"
52 changes: 52 additions & 0 deletions tests/integration/etc/keycloak/realm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"id": "demo",
"realm": "demo",
"sslRequired": "none",
"enabled": true,
"eventsEnabled": true,
"eventsExpiration": 900,
"adminEventsEnabled": true,
"adminEventsDetailsEnabled": true,
"attributes": {
"adminEventsExpiration": "900"
},
"clients": [
{
"id": "am-dashboard",
"clientId": "am-dashboard",
"name": "am-dashboard",
"enabled": true,
"rootUrl": "http://archivematica-dashboard:8000",
"adminUrl": "http://archivematica-dashboard:8000",
"baseUrl": "http://archivematica-dashboard:8000",
"clientAuthenticatorType": "client-secret",
"secret": "example-secret",
"redirectUris": ["http://archivematica-dashboard:8000/*"],
"webOrigins": ["http://archivematica-dashboard:8000"],
"standardFlowEnabled": true,
"serviceAccountsEnabled": true,
"authorizationServicesEnabled": true,
"publicClient": false
}
],
"users": [
{
"id": "demo",
"email": "[email protected]",
"username": "demo",
"firstName": "Demo",
"lastName": "User",
"enabled": true,
"emailVerified": true,
"credentials": [
{
"temporary": false,
"type": "password",
"value": "demo"
}
]
}
]
}
]
23 changes: 23 additions & 0 deletions tests/integration/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash

__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

cd ${__dir}

docker compose build archivematica-dashboard

status=$?

if [ $status -ne 0 ]; then
exit $status
fi

docker compose run --rm archivematica-dashboard

status=$?

if [ -z "${REUSE_TEST_ENV}" ]; then
docker compose down --volumes
fi

exit $status
Loading

0 comments on commit 937f41b

Please sign in to comment.