KNOX-3424: Dynamic audience handling in the KNOXTOKEN service #480
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Licensed to the Apache Software Foundation (ASF) under one or more | |
| # contributor license agreements. See the NOTICE file distributed with | |
| # this work for additional information regarding copyright ownership. | |
| # The ASF licenses this file to you under the Apache License, Version 2.0 | |
| # (the "License"); you may not use this file except in compliance with | |
| # the License. You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| name: Apache Knox Docker Compose Tests | |
| on: | |
| pull_request: | |
| branches: | |
| - '**' # triggers for all PRs | |
| workflow_dispatch: | |
| jobs: | |
| build-and-test: | |
| if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'skip-tests') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| checks: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Build with Maven | |
| run: | | |
| mvn clean -Ppackage,release install -T 1C \ | |
| -Dmaven.test.skip=true -Dpmd.skip=true -Dcpd.skip=true -Dcheckstyle.skip=true \ | |
| -Dspotbugs.skip=true -Drat.skip=true -Dforbiddenapis.skip=true -Denforcer.skip=true \ | |
| -Djacoco.skip=true -Dmaven.javadoc.skip=true -Dmaven.source.skip=true \ | |
| -Dshellcheck.skip=true -Dxml.skip=true \ | |
| -s .github/workflows/build/settings.xml | |
| - name: Set up Docker Compose | |
| run: docker compose version | |
| - name: Build Docker Images | |
| run: | | |
| # Build only knox-dev which is the runtime image using artifacts | |
| docker compose -f ./.github/workflows/compose/docker-compose.yml build knox-dev | |
| - name: Start Knox and LDAP Services | |
| run: docker compose -f ./.github/workflows/compose/docker-compose.yml up -d | |
| - name: Wait for services to stabilize | |
| run: sleep 30 # Adjust as needed for services startup time | |
| - name: Run Knox Integration Tests | |
| run: | | |
| # Run the tests service defined in docker-compose.yml | |
| docker compose -f ./.github/workflows/compose/docker-compose.yml up --exit-code-from tests tests | |
| # KnoxIDF federation E2E runs only when the PR carries the 'test-federation' | |
| # label. It stands up a real Keycloak (external OpenID Provider) via the | |
| # override compose file and pulls a multi-hundred-MB image plus minutes of | |
| # realm import, so it is opt-in rather than on every PR. It runs here, before | |
| # the single-EKU steps, so 'knox' is still in its base (non-mTLS) config; the | |
| # override only adds a keycloak dependency to knox, it does not reconfigure it. | |
| - name: Start Keycloak + Knox for federation | |
| if: contains(github.event.pull_request.labels.*.name, 'test-federation') | |
| run: | | |
| # 'up -d knox' blocks until keycloak is service_healthy (override depends_on). | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.knoxidf-federation.yml \ | |
| up -d knox keycloak | |
| - name: Wait for federation stack to stabilize | |
| if: contains(github.event.pull_request.labels.*.name, 'test-federation') | |
| run: sleep 30 # Adjust as needed for services startup time | |
| - name: Run KnoxIDF Federation Tests | |
| id: knoxidf_federation_tests | |
| if: contains(github.event.pull_request.labels.*.name, 'test-federation') | |
| run: | | |
| # Emit a distinct JUnit file so it reports as its own test suite. | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.knoxidf-federation.yml \ | |
| run --rm tests bash -c "pip install -r requirements.txt \ | |
| && pytest test_knoxidf_federation.py --junitxml=test-results-federation.xml" | |
| # Evidence gathering mirrors the single-EKU dumps: on a federation failure, | |
| # capture container status and the knox + keycloak logs so a broker-flow | |
| # failure (bad callback/issuer/JWKS) can be told apart from a Keycloak that | |
| # never came up. | |
| - name: Dump federation diagnostics on failure | |
| if: failure() && steps.knoxidf_federation_tests.outcome == 'failure' | |
| run: | | |
| echo '===== docker compose ps -a =====' | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.knoxidf-federation.yml \ | |
| ps -a || true | |
| echo '===== knox container logs =====' | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.knoxidf-federation.yml \ | |
| logs --no-color knox || true | |
| echo '===== keycloak container logs =====' | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.knoxidf-federation.yml \ | |
| logs --no-color keycloak || true | |
| echo '===== gateway.log =====' | |
| cat ./.github/workflows/compose/logs/gateway.log || true | |
| # Single-EKU mTLS runs as its own pass. Its override turns on | |
| # gateway.client.auth.needed=true, which would break the default | |
| # (no-client-cert) tests above, so the gateway is recreated with the | |
| # single-EKU config and the mTLS suite runs against that instance. The | |
| # already-built apache/knox-dev image is reused -- no second Maven build. | |
| - name: Restart Knox in single-EKU mode | |
| run: | | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku.yml \ | |
| up -d knox | |
| - name: Wait for single-EKU gateway to stabilize | |
| run: sleep 30 # Adjust as needed for services startup time | |
| - name: Run Single-EKU mTLS Tests | |
| id: single_eku_tests | |
| run: | | |
| # KNOX_SINGLE_EKU=true (set by the override) un-skips the suite. | |
| # Emit a distinct JUnit file so it reports as its own test suite. | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku.yml \ | |
| run --rm tests bash -c "pip install -r requirements.txt \ | |
| && pytest test_single_eku_mtls.py --junitxml=test-results-single-eku.xml" | |
| # Evidence gathering: a "Connection refused" from the suite means the | |
| # single-EKU gateway never listened. Dump container status, the knox | |
| # container's stdout/stderr (includes the entrypoint's create-alias output | |
| # and any Java startup stacktrace), and the gateway log so we can tell a | |
| # failed entrypoint apart from single-EKU fail-fast validation. | |
| - name: Dump single-EKU diagnostics on failure | |
| if: failure() && steps.single_eku_tests.outcome == 'failure' | |
| run: | | |
| echo '===== docker compose ps -a =====' | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku.yml \ | |
| ps -a || true | |
| echo '===== knox container logs =====' | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku.yml \ | |
| logs --no-color knox || true | |
| echo '===== gateway.log =====' | |
| cat ./.github/workflows/compose/logs/gateway.log || true | |
| # Second single-EKU scenario: mTLS OFF. Proves single-EKU does not force | |
| # inbound client authentication -- a no-client-cert request must succeed. | |
| - name: Restart Knox in single-EKU (no mTLS) mode | |
| run: | | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku-no-mtls.yml \ | |
| up -d knox | |
| - name: Wait for single-EKU (no mTLS) gateway to stabilize | |
| run: sleep 30 # Adjust as needed for services startup time | |
| - name: Run Single-EKU (no mTLS) Tests | |
| id: single_eku_no_mtls_tests | |
| run: | | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku-no-mtls.yml \ | |
| run --rm tests bash -c "pip install -r requirements.txt \ | |
| && pytest test_single_eku_no_mtls.py --junitxml=test-results-single-eku-no-mtls.xml" | |
| - name: Dump single-EKU (no mTLS) diagnostics on failure | |
| if: failure() && steps.single_eku_no_mtls_tests.outcome == 'failure' | |
| run: | | |
| echo '===== docker compose ps -a =====' | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku-no-mtls.yml \ | |
| ps -a || true | |
| echo '===== knox container logs =====' | |
| docker compose \ | |
| -f ./.github/workflows/compose/docker-compose.yml \ | |
| -f ./.github/workflows/compose/docker-compose.single-eku-no-mtls.yml \ | |
| logs --no-color knox || true | |
| echo '===== gateway.log =====' | |
| cat ./.github/workflows/compose/logs/gateway.log || true | |
| - name: Collect Knox Logs and Conf | |
| if: always() | |
| run: | | |
| mkdir -p .github/workflows/artifacts/knox-logs | |
| mkdir -p .github/workflows/artifacts/knox-conf | |
| docker compose -f ./.github/workflows/compose/docker-compose.yml cp knox:/knox-runtime/logs .github/workflows/artifacts/knox-logs | |
| docker compose -f ./.github/workflows/compose/docker-compose.yml cp knox:/knox-runtime/conf .github/workflows/artifacts/knox-conf | |
| - name: Upload Test Results | |
| if: (!cancelled()) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results | |
| path: | | |
| .github/workflows/tests/test-results.xml | |
| .github/workflows/tests/test-results-single-eku.xml | |
| .github/workflows/tests/test-results-single-eku-no-mtls.xml | |
| .github/workflows/tests/test-results-federation.xml | |
| - name: Archive Knox Logs | |
| if: always() | |
| run: tar -cvzf knox-logs.tar.gz -C .github/workflows/artifacts/knox-logs . | |
| - name: Upload Knox Logs | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: knox-logs | |
| path: knox-logs.tar.gz | |
| - name: Archive Knox Conf | |
| if: always() | |
| run: tar -cvzf knox-conf.tar.gz -C .github/workflows/artifacts/knox-conf . | |
| - name: Upload Knox Conf | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: knox-conf | |
| path: knox-conf.tar.gz | |
| - name: Upload Event File | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Event File | |
| path: ${{ github.event_path }} | |
| - name: Tear Down Docker Compose | |
| if: always() | |
| run: | | |
| docker compose -f ./.github/workflows/compose/docker-compose.yml down --volumes | |
| TAG=${IMAGE_TAG:-master} | |
| if docker image inspect "apache/knox-dev:$TAG" >/dev/null 2>&1; then | |
| docker rmi "apache/knox-dev:$TAG" | |
| fi |