diff --git a/.github/workflows/zap-owasp.yaml b/.github/workflows/zap-owasp.yaml index 0e11cf604f..b39873d057 100644 --- a/.github/workflows/zap-owasp.yaml +++ b/.github/workflows/zap-owasp.yaml @@ -6,51 +6,125 @@ on: env: PGUSER: postgres DJANGO_SECRET_KEY: ${{ secrets.DJANGO_SECRET_KEY }} + NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }} + KEYCLOAK_CLIENT_ID: ${{ secrets.KEYCLOAK_CLIENT_ID }} + KEYCLOAK_CLIENT_SECRET: ${{ secrets.KEYCLOAK_CLIENT_SECRET }} + KEYCLOAK_LOGIN_URL: ${{ secrets.KEYCLOAK_LOGIN_URL }} jobs: zap-scan: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: dev env setup - uses: ./.github/actions/dev-env-setup - - name: run app locally - uses: ./.github/actions/run-registration1-app + - name: Checkout Code + uses: actions/checkout@v4 + + # Install Docker and Docker Compose + - name: Install Docker Compose + run: | + sudo apt-get update + sudo apt-get install -y docker-compose + + # Start all services using Docker Compose + - name: Start Services with Docker Compose + run: | + echo "Starting services..." + docker-compose -f ./bciers/docker-compose-bciers-apps.yaml up -d + echo "Waiting for services to be ready..." + + # Wait for the backend API to be healthy + - name: Wait for Backend API Readiness + run: | + timeout 90s bash -c 'until curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8000/api | grep -q "200"; do sleep 3; done' || { echo "Backend API is not ready"; exit 1; } + + # Wait for Frontend Readiness (Dashboard) + - name: Wait for Dashboard Readiness + run: | + timeout 90s bash -c 'until curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000 | grep -q "200"; do sleep 3; done' || { echo "Dashboard is not ready"; exit 1; } + + # Run ZAP Scan for Backend API + - name: ZAP Scan - Backend API + uses: zaproxy/action-baseline@v0.14.0 with: - django_secret_key: ${{ env.DJANGO_SECRET_KEY }} - - name: ZAP Frontend Scan + token: ${{ secrets.GITHUB_TOKEN }} + docker_name: "ghcr.io/zaproxy/zaproxy:stable" + target: "http://127.0.0.1:8000/api" + cmd_options: "-a -d -T 5 -m 2" + issue_title: "OWASP Baseline - Backend API" + fail_action: false + allow_issue_writing: false + artifact_name: backend_zap_scan + + # Run ZAP Scan for Frontend Apps + - name: ZAP Scan - Dashboard Frontend uses: zaproxy/action-baseline@v0.14.0 with: token: ${{ secrets.GITHUB_TOKEN }} docker_name: "ghcr.io/zaproxy/zaproxy:stable" - target: "http://localhost:3000/" - rules_file_name: ".zap/rules-frontend.tsv" + target: "http://127.0.0.1:3000" cmd_options: "-a -d -T 5 -m 2" - issue_title: OWASP Baseline - Frontend + issue_title: "OWASP Baseline - Dashboard Frontend" fail_action: false allow_issue_writing: false - artifact_name: frontend_zap_scan - - name: ZAP Backend Scan + artifact_name: dashboard_zap_scan + + - name: ZAP Scan - Administration Frontend uses: zaproxy/action-baseline@v0.14.0 with: token: ${{ secrets.GITHUB_TOKEN }} docker_name: "ghcr.io/zaproxy/zaproxy:stable" - target: "http://0.0.0.0:8000/" - rules_file_name: ".zap/rules-backend.tsv" + target: "http://127.0.0.1:4001" cmd_options: "-a -d -T 5 -m 2" - issue_title: OWASP Baseline - Backend + issue_title: "OWASP Baseline - Administration Frontend" fail_action: false allow_issue_writing: false - artifact_name: backend_zap_scan + artifact_name: administration_zap_scan + + - name: ZAP Scan - Registration Frontend + uses: zaproxy/action-baseline@v0.14.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + docker_name: "ghcr.io/zaproxy/zaproxy:stable" + target: "http://127.0.0.1:4000" + cmd_options: "-a -d -T 5 -m 2" + issue_title: "OWASP Baseline - Registration Frontend" + fail_action: false + allow_issue_writing: false + artifact_name: registration_zap_scan + + - name: ZAP Scan - Compliance Frontend + uses: zaproxy/action-baseline@v0.14.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + docker_name: "ghcr.io/zaproxy/zaproxy:stable" + target: "http://127.0.0.1:7000" + cmd_options: "-a -d -T 5 -m 2" + issue_title: "OWASP Baseline - Compliance Frontend" + fail_action: false + allow_issue_writing: false + artifact_name: compliance_zap_scan + + - name: ZAP Scan - Reporting Frontend + uses: zaproxy/action-baseline@v0.14.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + docker_name: "ghcr.io/zaproxy/zaproxy:stable" + target: "http://127.0.0.1:5000" + cmd_options: "-a -d -T 5 -m 2" + issue_title: "OWASP Baseline - Reporting Frontend" + fail_action: false + allow_issue_writing: false + artifact_name: reporting_zap_scan + + - name: Tear Down Services + run: | + echo "Stopping services..." + docker-compose -f ./cas-registration/bciers/docker-compose-bciers-apps.yaml down - # Retry the workflow due to secondary rate limiting errors causing frequent failures + # Retry job in case of failure retry-on-failure: needs: zap-scan - if: failure() || needs.zap-scan.result != 'success' && fromJSON(github.run_attempt) < 3 && !cancelled() + if: failure() || (needs.zap-scan.result != 'success' && fromJSON(github.run_attempt) < 3 && !cancelled()) runs-on: ubuntu-latest steps: - - env: - GH_REPO: ${{ github.repository }} - GH_TOKEN: ${{ github.token }} - GH_DEBUG: api + - name: Retry ZAP Scan run: gh workflow run retry-workflow.yaml -F run_id=${{ github.run_id }} diff --git a/bciers/docker-compose-bciers-apps.yaml b/bciers/docker-compose-bciers-apps.yaml index b90e9fcd43..7005bb7b13 100644 --- a/bciers/docker-compose-bciers-apps.yaml +++ b/bciers/docker-compose-bciers-apps.yaml @@ -21,11 +21,10 @@ services: DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY} ALLOWED_HOSTS: localhost,0.0.0.0,127.0.0.1 ENVIRONMENT: dev - CI: true + CI: "true" depends_on: - - db # Ensures the database is up before the backend starts + - db network_mode: host - # Healthcheck to ensure the API is ready before reporting healthy healthcheck: test: curl --fail http://127.0.0.1:8000/api || exit 1 interval: 10s @@ -34,10 +33,9 @@ services: start_period: 60s dashboard: - # Use the dashboard-e2e image which has nextjs rewrite hosts built in image: ghcr.io/bcgov/cas-dash-e2e-frontend:${GITHUB_SHA} environment: - CI: true # This is used to disable secureCookie in the dashboard route.ts file + CI: "true" PORT: 3000 HOSTNAME: localhost NEXTAUTH_URL_INTERNAL: http://localhost:3000 @@ -48,8 +46,15 @@ services: KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET} KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID} depends_on: - - backend + backend: + condition: service_healthy # Wait for backend health check network_mode: host + healthcheck: + test: curl --fail http://127.0.0.1:3000 || exit 1 + interval: 10s + timeout: 10s + retries: 20 + start_period: 60s administration: image: ghcr.io/bcgov/cas-admin-frontend:${GITHUB_SHA} @@ -64,7 +69,8 @@ services: KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET} KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID} depends_on: - - backend + backend: + condition: service_healthy network_mode: host compliance: @@ -80,7 +86,8 @@ services: KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET} KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID} depends_on: - - backend + backend: + condition: service_healthy network_mode: host registration: @@ -96,7 +103,8 @@ services: KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET} KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID} depends_on: - - backend + backend: + condition: service_healthy network_mode: host reporting: @@ -112,7 +120,8 @@ services: KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET} KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID} depends_on: - - backend + backend: + condition: service_healthy network_mode: host volumes: