diff --git a/.github/workflows/oidc-integration-test.yml b/.github/workflows/oidc-integration-test.yml new file mode 100644 index 0000000000..82fa5a13ac --- /dev/null +++ b/.github/workflows/oidc-integration-test.yml @@ -0,0 +1,124 @@ +name: OIDC integration tests +on: + pull_request: + push: + branches: + - qa/** + - stable/** +jobs: + integration-tests: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + browser: [Chrome, Electron, Firefox] + name: ${{ matrix.browser }} + env: + COMPOSE_FILE: ${{ github.workspace }}/docker/docker-compose.dev.yml + steps: + - name: Check out code + uses: actions/checkout@v3 + - name: Start containerized services + run: | + sudo sysctl -w vm.max_map_count=262144 + docker compose -p ci up -d percona elasticsearch gearmand + - name: Launch Keycloak service + run: | + docker compose -p ci -f ${{ github.workspace }}/docker/docker-compose.keycloak.yml up -d + - name: Wait for Keycloak to be Ready + run: | + echo "Waiting for Keycloak to be ready..." + for i in {1..30}; do + if nc -z localhost 8080; then + echo "Keycloak is up!" + break + fi + echo "Waiting for Keycloak..." + sleep 5 + done + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + coverage: none + extensions: apcu, opcache + - name: Setup PHP-FPM + run: | + sudo apt install php7.4-fpm + sudo service php7.4-fpm start + - name: Cache Composer dependencies + uses: actions/cache@v3 + with: + path: ~/.composer/cache/files + key: 20.04-7.4-composer-${{ hashFiles('composer.lock') }} + - name: Install Composer dependencies + run: composer install + - name: Cache NPM dependencies + uses: actions/cache@v3 + with: + path: | + ~/.npm + ~/.cache/Cypress + key: npm-${{ hashFiles('package-lock.json') }} + - name: Install NPM dependencies + run: sudo npm install -g npm && npm ci + - name: Modify Gearman config + run: | + echo -e "all:\n servers:\n default: 127.0.0.1:63005" \ + > apps/qubit/config/gearman.yml + - name: Build themes + run: | + sudo npm install -g "less@<4.0.0" + make -C plugins/arDominionPlugin + make -C plugins/arArchivesCanadaPlugin + npm run build + - name: Run the installer + run: | + php symfony tools:install \ + --database-host=127.0.0.1 \ + --database-port=63003 \ + --database-name=atom \ + --database-user=atom \ + --database-password=atom_12345 \ + --search-host=127.0.0.1 \ + --search-port=63002 \ + --search-index=atom \ + --demo \ + --no-confirmation + - name: Update OIDC plugin app.yml file + run: sudo cp docker/etc/oidc/arOidcPlugin/config/app.yml plugins/arOidcPlugin/config + - name: Update factories.yml to use oidcUser + run: | + sudo sed -i 's/class: myUser/class: oidcUser/' config/factories.yml + - name: Change filesystem permissions + run: sudo chown -R www-data:www-data ${{ github.workspace }} + - name: Start application services + run: | + sudo cp test/etc/fpm_conf /etc/php/7.4/fpm/pool.d/atom.conf + sudo rm /etc/php/7.4/fpm/pool.d/www.conf + sudo systemctl restart php7.4-fpm + sudo php-fpm7.4 --test + sudo cp test/etc/worker_conf /usr/lib/systemd/system/atom-worker.service + sudo systemctl daemon-reload + sudo systemctl start atom-worker + - name: Install OIDC Plugin + run: | + php symfony tools:atom-plugins add arOidcPlugin + - name: Install and configure Nginx + run: | + sudo apt install nginx + sudo cp test/etc/nginx_conf /etc/nginx/sites-available/atom + sudo ln -s /etc/nginx/sites-available/atom /etc/nginx/sites-enabled + sudo rm -f /etc/nginx/sites-enabled/default + sudo nginx -t + sudo systemctl restart nginx + - name: Create writable Cypress videos and screenshots dirs + run: | + sudo mkdir -p ${{ github.workspace }}/cypress/screenshots ${{ github.workspace }}/cypress/videos + sudo chmod a=rwx ${{ github.workspace }}/cypress/screenshots ${{ github.workspace }}/cypress/videos + - name: Run tests + env: + BROWSER: ${{ matrix.browser }} + CYPRESS_VIDEO: false + CYPRESS_BASE_URL: http://localhost + run: npx cypress run -b ${BROWSER,} diff --git a/docker/docker-compose.keycloak.yml b/docker/docker-compose.keycloak.yml new file mode 100644 index 0000000000..399d5d4701 --- /dev/null +++ b/docker/docker-compose.keycloak.yml @@ -0,0 +1,15 @@ +--- +services: + 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 diff --git a/docker/etc/keycloak/realm.json b/docker/etc/keycloak/realm.json new file mode 100644 index 0000000000..0f22dc4ff2 --- /dev/null +++ b/docker/etc/keycloak/realm.json @@ -0,0 +1,129 @@ +[ + { + "id": "demo", + "realm": "demo", + "sslRequired": "none", + "enabled": true, + "eventsEnabled": true, + "eventsExpiration": 900, + "adminEventsEnabled": true, + "adminEventsDetailsEnabled": true, + "attributes": { + "adminEventsExpiration": "900" + }, + "clients": [ + { + "id": "atom", + "clientId": "atom", + "name": "atom", + "enabled": true, + "rootUrl": "http://docker-atom:63001", + "adminUrl": "http://docker-atom:63001", + "baseUrl": "http://docker-atom:63001", + "clientAuthenticatorType": "client-secret", + "secret": "example-secret", + "redirectUris": ["http://docker-atom:63001/*"], + "webOrigins": ["http://docker-atom:63001"], + "standardFlowEnabled": true, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false + } + ], + "users": [ + { + "id": "demo", + "email": "demo@example.com", + "username": "demo", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "temporary": false, + "type": "password", + "value": "demo" + } + ], + "realmRoles": [ + "atom-admin", + "atom-editor" + ] + } + ], + "roles": { + "realm": [ + { + "name": "atom-admin", + "description": "Admin role for AtoM" + }, + { + "name": "atom-editor", + "description": "Editor role for AtoM" + } + ] + } + }, + { + "id": "secondary", + "realm": "secondary", + "sslRequired": "none", + "enabled": true, + "eventsEnabled": true, + "eventsExpiration": 900, + "adminEventsEnabled": true, + "adminEventsDetailsEnabled": true, + "attributes": { + "adminEventsExpiration": "900" + }, + "clients": [ + { + "id": "atom-secondary", + "clientId": "atom-secondary", + "name": "atom-secondary", + "enabled": true, + "rootUrl": "http://docker-atom:63001", + "adminUrl": "http://docker-atom:63001", + "baseUrl": "http://docker-atom:63001", + "clientAuthenticatorType": "client-secret", + "secret": "example-secret", + "redirectUris": ["http://docker-atom:63001/*"], + "webOrigins": ["http://docker-atom:63001"], + "standardFlowEnabled": true, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false + } + ], + "users": [ + { + "id": "support", + "email": "support@example.com", + "username": "support", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "temporary": false, + "type": "password", + "value": "support" + } + ], + "realmRoles": [ + "atom-admin" + ] + } + ], + "roles": { + "realm": [ + { + "name": "atom-admin", + "description": "Admin role for AtoM" + }, + { + "name": "atom-editor", + "description": "Editor role for AtoM" + } + ] + } + } +] diff --git a/docker/etc/oidc/arOidcPlugin/config/app.yml b/docker/etc/oidc/arOidcPlugin/config/app.yml new file mode 100644 index 0000000000..5b028925e1 --- /dev/null +++ b/docker/etc/oidc/arOidcPlugin/config/app.yml @@ -0,0 +1,70 @@ +## OIDC Plugin configuration. +all: + oidc: + providers: + demo: + url: 'http://keycloak:8080/realms/demo' + client_id: 'atom' + client_secret: 'example-secret' + send_oidc_logout: true + enable_refresh_token_use: true + server_cert: false + set_groups_from_attributes: true + user_groups: + administrator: + attribute_value: 'atom-admin' + group_id: 100 + editor: + attribute_value: 'atom-editor' + group_id: 101 + contributor: + attribute_value: 'atom-contributor' + group_id: 102 + translator: + attribute_value: 'atom-translator' + group_id: 103 + scopes: + - 'openid' + - 'profile' + - 'email' + roles_source: 'access-token' + roles_path: + - 'realm_access' + - 'roles' + user_matching_source: 'oidc-email' + auto_create_atom_user: true + secondary: + url: 'http://keycloak:8080/realms/secondary' + client_id: 'atom-secondary' + client_secret: 'example-secret' + send_oidc_logout: true + enable_refresh_token_use: true + server_cert: false + set_groups_from_attributes: true + user_groups: + administrator: + attribute_value: 'atom-admin' + group_id: 100 + editor: + attribute_value: 'atom-editor' + group_id: 101 + contributor: + attribute_value: 'atom-contributor' + group_id: 102 + translator: + attribute_value: 'atom-translator' + group_id: 103 + scopes: + - 'openid' + - 'profile' + - 'email' + roles_source: 'access-token' + roles_path: + - 'realm_access' + - 'roles' + user_matching_source: 'oidc-email' + auto_create_atom_user: true + primary_provider_name: primary + provider_query_param_name: secondary + redirect_url: 'http://127.0.0.1:63001/index.php/oidc/login' + logout_redirect_url: 'http://127.0.0.1:63001'