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.
This commit is contained in:
123
.github/workflows/notification-service.yml
vendored
123
.github/workflows/notification-service.yml
vendored
@@ -31,14 +31,129 @@ jobs:
|
||||
distribution: temurin
|
||||
cache: maven
|
||||
|
||||
- name: Run tests
|
||||
- name: Build & test (SpotBugs included via verify)
|
||||
run: mvn verify -q
|
||||
|
||||
# ── 2. Docker build & push ───────────────────────────────────────────────────
|
||||
# ── 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
|
||||
needs: [ci, sast-codeql, dast]
|
||||
if: github.ref == 'refs/heads/main'
|
||||
outputs:
|
||||
sha_tag: ${{ steps.tag.outputs.sha }}
|
||||
@@ -80,7 +195,7 @@ jobs:
|
||||
${{ steps.tag.outputs.sha }}
|
||||
${{ steps.tag.outputs.extra }}
|
||||
|
||||
# ── 3. Deploy to physical server (SSH) ───────────────────────────────────────
|
||||
# ── 6. Deploy to physical server (SSH) ───────────────────────────────────────
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -63,6 +63,40 @@
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- SAST: SpotBugs + FindSecBugs -->
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<version>4.8.3.1</version>
|
||||
<configuration>
|
||||
<effort>Max</effort>
|
||||
<threshold>High</threshold>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.h3xstream.findsecbugs</groupId>
|
||||
<artifactId>findsecbugs-plugin</artifactId>
|
||||
<version>1.13.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals><goal>check</goal></goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Dependency vulnerability scan: OWASP -->
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>9.0.9</version>
|
||||
<configuration>
|
||||
<failBuildOnCVSS>7</failBuildOnCVSS>
|
||||
<formats>HTML,JSON</formats>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestClient;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
@@ -41,7 +42,7 @@ public class AirQualityService {
|
||||
var request = restClient.get().uri(url);
|
||||
|
||||
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
|
||||
String encoded = Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
|
||||
String encoded = Base64.getEncoder().encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8));
|
||||
request = request.header(HttpHeaders.AUTHORIZATION, "Basic " + encoded);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user