Files
MSE-PI-E2EEDA-Plein-de-eeee…/.github/workflows/notification-service.yml
khalil-bot 8cba5f7710 ci(notification-service): add SAST, dependency scan and DAST security gates
Add CodeQL (SAST), SpotBugs+FindSecBugs (SAST via verify), OWASP Dependency Check
and OWASP ZAP baseline scan (DAST) to the CI/CD pipeline.
Docker deploy is gated behind ci, sast-codeql and dast jobs.
Fix DM_DEFAULT_ENCODING spotted by SpotBugs: use StandardCharsets.UTF_8 in Basic Auth encoding.
2026-06-01 12:37:35 +02:00

239 lines
7.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Notification Service CI/CD
on:
workflow_dispatch:
push:
paths:
- notification_service/**
- .github/workflows/notification-service.yml
pull_request:
branches: [main]
paths:
- notification_service/**
- .github/workflows/notification-service.yml
jobs:
# ── 1. Build & test ──────────────────────────────────────────────────────────
ci:
name: Build & test
runs-on: ubuntu-latest
defaults:
run:
working-directory: notification_service
steps:
- uses: actions/checkout@v4
- name: Setup Java 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
cache: maven
- name: Build & test (SpotBugs included via verify)
run: mvn verify -q
# ── 2. SAST CodeQL ─────────────────────────────────────────────────────────
sast-codeql:
name: SAST CodeQL
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: Setup Java 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
cache: maven
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: java
queries: security-and-quality
- name: Build for CodeQL
run: mvn compile -q -f notification_service/pom.xml
- name: Analyze
uses: github/codeql-action/analyze@v3
with:
category: /language:java
# ── 3. Dependency vulnerability scan (OWASP) ─────────────────────────────────
dependency-check:
name: Dependency vulnerability scan
runs-on: ubuntu-latest
defaults:
run:
working-directory: notification_service
steps:
- uses: actions/checkout@v4
- name: Setup Java 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
cache: maven
- name: Cache NVD database
uses: actions/cache@v4
with:
path: ~/.m2/repository/org/owasp/dependency-check-data
key: nvd-${{ runner.os }}-${{ hashFiles('notification_service/pom.xml') }}
restore-keys: nvd-${{ runner.os }}-
- name: OWASP Dependency Check
run: mvn dependency-check:check -q
continue-on-error: true
- name: Upload dependency check report
if: always()
uses: actions/upload-artifact@v4
with:
name: dependency-check-report
path: notification_service/target/dependency-check-report.*
retention-days: 14
# ── 4. DAST OWASP ZAP ──────────────────────────────────────────────────────
dast:
name: DAST OWASP ZAP
runs-on: ubuntu-latest
needs: ci
steps:
- uses: actions/checkout@v4
- name: Setup Java 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
cache: maven
- name: Build JAR
run: mvn package -DskipTests -q -f notification_service/pom.xml
- name: Start service
run: |
java -jar notification_service/target/notification-service-*.jar &
timeout 60 bash -c 'until curl -sf http://localhost:8080/actuator/health; do sleep 2; done'
env:
TELEGRAM_BOT_TOKEN: dummy-token
TELEGRAM_CHAT_ID: "0"
AIR_QUALITY_API_URL: http://localhost:9999
API_USERNAME: dummy
API_PASSWORD: dummy
MOCK_MODE: "true"
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.12.0
with:
target: http://localhost:8080
fail_action: false
allow_issue_writing: false
- name: Upload ZAP report
if: always()
uses: actions/upload-artifact@v4
with:
name: zap-report
path: report_html.html
retention-days: 14
# ── 5. Docker build & push ───────────────────────────────────────────────────
docker:
name: Docker build & push
runs-on: ubuntu-latest
needs: [ci, sast-codeql, dast]
if: github.ref == 'refs/heads/main'
outputs:
sha_tag: ${{ steps.tag.outputs.sha }}
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Compute image tags
id: tag
run: |
OWNER="${{ github.repository_owner }}"
IMAGE_LC="ghcr.io/${OWNER,,}/notification-service"
echo "image=${IMAGE_LC}" >> $GITHUB_OUTPUT
echo "sha=${IMAGE_LC}:${{ github.sha }}" >> $GITHUB_OUTPUT
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
echo "extra=${IMAGE_LC}:latest" >> $GITHUB_OUTPUT
else
BRANCH="${{ github.head_ref || github.ref_name }}"
echo "extra=${IMAGE_LC}:branch-${BRANCH//\//-}" >> $GITHUB_OUTPUT
fi
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build & push
uses: docker/build-push-action@v5
with:
context: notification_service
push: true
tags: |
${{ steps.tag.outputs.sha }}
${{ steps.tag.outputs.extra }}
# ── 6. Deploy to physical server (SSH) ───────────────────────────────────────
deploy:
name: Deploy
runs-on: ubuntu-latest
needs: docker
if: github.ref == 'refs/heads/main'
steps:
- name: SSH deploy
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SSH_CERT: ${{ secrets.SSH_CERTIFICATE }}
SHA_TAG: ${{ needs.docker.outputs.sha_tag }}
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
AIR_QUALITY_API_URL: ${{ secrets.AIR_QUALITY_API_URL }}
API_USERNAME: ${{ secrets.API_USERNAME }}
API_PASSWORD: ${{ secrets.API_PASSWORD }}
run: |
echo "$SSH_KEY" > /tmp/deploy_key
echo "$SSH_CERT" > /tmp/deploy_key-cert.pub
chmod 600 /tmp/deploy_key
ssh -i /tmp/deploy_key \
-p ${{ secrets.SSH_PORT }} \
-o StrictHostKeyChecking=no \
-o IdentitiesOnly=yes \
${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} \
"sudo -iu e << 'EOF'
docker pull $SHA_TAG
docker stop notification-service 2>/dev/null || true
docker rm notification-service 2>/dev/null || true
docker run -d --name notification-service --restart unless-stopped \
-e TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN \
-e TELEGRAM_CHAT_ID=$TELEGRAM_CHAT_ID \
-e AIR_QUALITY_API_URL=$AIR_QUALITY_API_URL \
-e API_USERNAME=$API_USERNAME \
-e API_PASSWORD=$API_PASSWORD \
-e MOCK_MODE=false \
$SHA_TAG
EOF"
rm /tmp/deploy_key /tmp/deploy_key-cert.pub