Java CI with Maven #59
This file contains 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
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time | |
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven | |
name: Java CI with Maven | |
on: | |
#push: | |
#branches: [ main ] | |
#pull_request: | |
#branches: [ main ] | |
workflow_dispatch: | |
jobs: | |
build: | |
permissions: | |
security-events: write | |
id-token: write | |
contents: read | |
attestations: write | |
packages: write | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
java: [ '17' ] | |
# outputs: | |
# my_output: ${{ steps.generate_sbom.outputs.result }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up JDK ${{ matrix.java }} | |
uses: actions/setup-java@v4 | |
with: | |
java-version: ${{ matrix.java }} | |
distribution: 'adopt' | |
cache: maven | |
- name: Build with Maven Wrapper | |
run: | | |
pwd | |
./mvnw -B package > app.jar | |
# - uses: actions/checkout@v4 | |
# with: | |
# fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | |
- name: Generate artifact attestation | |
uses: actions/attest-build-provenance@v1 | |
# outputs: | |
# Attestation: | |
with: | |
subject-path: ./app.jar | |
- name: verify jar attesttion | |
env: | |
GH_TOKEN: ${{secrets.GH_TOKEN}} | |
run: | | |
# gh attestation download app.jar -o github | |
# wget https://github.com/saurav631/spring-petclinic/attestations/1598170/download -o sigstore.json | |
# gh attestation verify github --owner saurav631 --bundle sigstore.json | |
# gh attestation verify app.jar --owner saurav631 --bundle ./saurav631-spring-petclinic-attestation-1598170.sigstore.json --format=json | |
gh attestation verify app.jar --owner saurav631 --format=json | |
# gh attestation verify app.jar --owner saurv631 --bundle application/vnd.dev.sigstore.bundle.v0.3+json --format=json | |
# gh attestation verify sigstore.json --owner saurav631 --format=json | |
# - name: Set up JDK 17 | |
# uses: actions/setup-java@v1 | |
# with: | |
# java-version: 17 | |
# - name: Cache SonarQube packages | |
# uses: actions/cache@v1 | |
# with: | |
# path: ~/.sonar/cache | |
# key: ${{ runner.os }}-sonar | |
# restore-keys: ${{ runner.os }}-sonar | |
# - name: Cache Maven packages | |
# uses: actions/cache@v1 | |
# with: | |
# path: ~/.m2 | |
# key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} | |
# restore-keys: ${{ runner.os }}-m2 | |
# - name: Build and analyze | |
# env: | |
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
# SONAR_HOST_URL: http://20.235.200.36:9000/ | |
# run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=PetClinic -Dsonar.projectName='PetClinic' | |
# - name: Check SonarQube Quality Gate | |
# run: | | |
# sleep 10 | |
# STATUS=$(curl -s -u ${{ secrets.SONAR_TOKEN }} "http://20.235.200.36:9000/api/qualitygates/project_status?projectKey=PetClinic" | jq -r '.projectStatus.status') | |
# echo "Quality Gate Status: $STATUS" | |
# if [ "$STATUS" != "OK" ]; then | |
# echo "SonarQube Quality Gate failed" | |
# exit 1 | |
# fi | |
# - name: Install & Running TruffleHog | |
# run: | | |
# pip install truffleHog | |
# trufflehog git_url https://github.com/saurav631/spring-petclinic/ --repo_path . | |
- name: Install Syft | |
run: | | |
curl -sSL https://github.com/anchore/syft/releases/download/v0.66.0/syft_0.66.0_linux_amd64.tar.gz | tar xz -C /usr/local/bin syft | |
- name: Generate SBOM with Syft | |
# id: generate_sbom | |
run: | | |
# echo "result=`syft dir:. -o cyclonedx-json > sbom.json`" >> $GITHUB_ENV | |
syft dir:. -o cyclonedx-json > sbom.json | |
- name: Upload SBOM | |
uses: actions/upload-artifact@v4 | |
with: | |
name: sbom | |
path: sbom.json | |
- name: Generate SBOM attestation | |
uses: actions/attest-sbom@v1 | |
with: | |
subject-path: ./sbom.json | |
sbom-path: ./sbom.json | |
- name: verify SBOM attesttion | |
env: | |
GH_TOKEN: ${{secrets.GH_TOKEN}} | |
run: | | |
# gh attestation verify sbom.json --owner saurav631 --bundle ./sbom.json | |
gh attestation verify ./sbom.json --owner saurav631 --format=json | |
# gh attestation verify app.jar --owner saurav631 --format=json | |
# gh attestation verify sbom.json --owner saurav631 --bundle ./saurav631-spring-petclinic-attestation-1599265.sigstore.json | |
# - name: Dependency Scanning with OWASP Dependency-Check | |
# run: | | |
# /opt/dependency-check/bin/dependency-check.sh --project my_project --out dependency-check-report --scan . | |
# - name: Upload Dependency Check Report | |
# uses: actions/upload-artifact@v3 | |
# with: | |
# name: dependency-check-report | |
# path: dependency-check-report | |
# - name: Scan Docker Images for Vulnerabilities | |
# run: | | |
# sudo apt-get update | |
# sudo apt-get install -y docker.io | |
# sudo systemctl start docker | |
# sudo systemctl enable docker | |
# curl -sSL https://github.com/aquasecurity/trivy/releases/download/v0.36.0/trivy_0.36.0_Linux-64bit.deb -o trivy.deb | |
# sudo dpkg -i trivy.deb | |
# trivy image my_microservice:latest | |
# - name: Deploy Microservices | |
# run: | | |
# kubectl apply -f k8s/deployment.yaml | |
- name: Build Docker Image | |
run: ./mvnw spring-boot:build-image | |
- name: Log in to GitHub Container Registry | |
uses: docker/login-action@v2 | |
with: | |
# username: ${{ secrets.CR_Username }} | |
username: ${{ github.actor }} | |
# password: ${{ secrets.CR_Password }} | |
password: ${{secrets.GH_TOKEN}} | |
registry: ghcr.io | |
- name: Tag Docker Image | |
run: | | |
docker tag docker.io/library/spring-petclinic:3.3.0-SNAPSHOT ghcr.io/saurav631/spring-petclinic:latest | |
- name: Push Docker Image | |
run: | | |
docker push ghcr.io/saurav631/spring-petclinic:latest | |
- name: Run Trivy Vulnerability Scanner | |
uses: aquasecurity/trivy-action@7b7aa264d83dc58691451798b4d117d53d21edfe | |
with: | |
image-ref: 'ghcr.io/saurav631/spring-petclinic:latest' | |
format: 'template' | |
template: '@/contrib/sarif.tpl' | |
output: 'trivy-results.sarif' | |
severity: 'CRITICAL,HIGH' | |
- name: Upload Trivy Scan Results to GitHub Security Tab | |
uses: github/codeql-action/upload-sarif@v3 | |
with: | |
sarif_file: 'trivy-results.sarif' | |
sign: | |
name: Sign Container Image | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: Check Out Source Code | |
uses: actions/checkout@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v2 | |
- name: Download file artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: sbom | |
- name: Log in to GitHub Container Registry | |
uses: docker/login-action@v2 | |
with: | |
# username: ${{ secrets.CR_Username }} | |
username: ${{github.actor}} | |
# password: ${{ secrets.CR_Password }} | |
password: ${{secrets.GH_TOKEN}} | |
registry: ghcr.io | |
# - name: Install Cosign CLI | |
# run: | | |
# curl -sSL -o /usr/local/bin/cosign https://github.com/sigstore/cosign/releases/download/v2.1.1/cosign-linux-amd64 | |
# chmod +x /usr/local/bin/cosign | |
# cosign version | |
- name: Install Cosign CLI | |
run: | | |
curl -sSL -o /usr/local/bin/cosign https://github.com/sigstore/cosign/releases/download/v2.2.3/cosign-linux-amd64 | |
chmod +x /usr/local/bin/cosign | |
cosign version | |
# - name: Create Decrypted Signing Key File | |
# run: | | |
# echo "${{ secrets.COSIGN_KEY }}" > cosign.key | |
# - name: Sign Docker Image with Cosign | |
# run: | | |
# cosign sign --key cosign.key ghcr.io/saurav631/spring-petclinic:latest | |
- name: sign container image | |
run: | | |
cosign sign --key env://COSIGN_KEY ghcr.io/saurav631/spring-petclinic:latest --yes | |
shell: bash | |
env: | |
COSIGN_KEY: ${{secrets.Cosign_Key}} | |
COSIGN_PASSWORD: ${{secrets.Cosign_Key_Password}} | |
# - name: Create Public Key File_ | |
# run: echo "${{ secrets.Cosign_Pub }}" > cosign.pub | |
- name: Public Key Creation | |
run: | | |
cosign public-key --key env://COSIGN_KEY > cosign.pub | |
shell: bash | |
env: | |
COSIGN_KEY: ${{secrets.Cosign_Key}} | |
COSIGN_PASSWORD: ${{secrets.Cosign_Key_Password}} | |
- name: Verify Docker Image Signature | |
run: | | |
cosign verify --key cosign.pub ghcr.io/saurav631/spring-petclinic:latest #--insecure-ignore-tlog #--check-claims=false | |
- name: Attach SBOM | |
id: attach-sbom | |
run: | | |
set -e # Exit on error | |
# Run the cosign attach sbom command and capture its output | |
# echo "sbom: ${{ needs.build.outputs.my_output }}" | |
# output=$(cosign attach sbom --sbom ${{ needs.build.outputs.my_output }} ghcr.io/saurav631/spring-petclinic:latest) || { echo "Failed to run cosign attach sbom"; exit 1; } | |
# output=$(cosign attach sbom --sbom sbom.json ghcr.io/saurav631/spring-petclinic:latest) || { echo "Failed to run cosign attach sbom"; exit 1; } | |
output=$(cosign attach sbom --sbom sbom.json ghcr.io/saurav631/spring-petclinic:latest 2>&1) || { echo "Failed to run cosign attach sbom"; exit 1; } | |
# output=$(cosign attach sbom --sbom sbom.json ghcr.io/saurav631/spring-petclinic:latest) || { echo "Failed to run cosign attach sbom"; exit 1; } | |
# cosign attest --predicate <FILE> --type <TYPE> --key cosign.key <IMAGE> | |
echo "cat output --> showing output below" | |
echo "$output" | |
# Extract the SHA from the output | |
sbom_filename=$(echo "$output" | grep -oP 'sha256-[\w\d]+\.sbom') || { echo "Failed to extract SBOM filename"; exit 1; } | |
echo "$sbom_filename" | |
# Check if the extraction was successful | |
if [ -z "$sbom_filename" ]; then | |
echo "Error: No SBOM filename found in the output" | |
exit 1 | |
fi | |
# Set the extracted SHA as an environment variable | |
echo "SBOM_FILENAME=$sbom_filename" >> $GITHUB_ENV | |
- name: Sign the SBOM attached with the Image | |
run: | | |
set -e # Exit on error | |
# Use the environment variable to construct the command | |
if [ -z "$SBOM_FILENAME" ]; then | |
echo "Error: SBOM_FILENAME environment variable is not set" | |
exit 1 | |
fi | |
echo "Signing SBOM with filename: $SBOM_FILENAME" | |
cosign sign --key env://COSIGN_KEY ghcr.io/saurav631/spring-petclinic:$SBOM_FILENAME --yes || { echo "Failed to sign with SBOM"; exit 1; } | |
shell: bash | |
env: | |
COSIGN_KEY: ${{secrets.Cosign_Key}} | |
COSIGN_PASSWORD: ${{secrets.Cosign_Key_Password}} | |
- name: Verify Sign of SBOM attached with the Image | |
run: | | |
set -e # Exit on error | |
cosign verify --key cosign.pub ghcr.io/saurav631/spring-petclinic:$SBOM_FILENAME || { echo "Failed to verify SBOM Sign"; exit 1; } | |
- name: Directly attest SBOM with the Image | |
run: | | |
set -e # Exit on error | |
output=$(cosign attest --key env://COSIGN_KEY --type cyclonedx --predicate sbom.json ghcr.io/saurav631/spring-petclinic:latest --yes 2>&1) || { echo "Failed to attest sbom with the image"; exit 1; } | |
echo "$output" | |
shell: bash | |
env: | |
COSIGN_KEY: ${{secrets.Cosign_Key}} | |
COSIGN_PASSWORD: ${{secrets.Cosign_Key_Password}} | |
- name: Verfiy the attested Image | |
run: | | |
set -e # Exit on error | |
output1=$(cosign verify-attestation --key cosign.pub ghcr.io/saurav631/spring-petclinic:latest | jq -r .payload | base64 -D | jq . 2>&1) || { echo "Failed to verify the attested image"; exit 1; } | |
echo "output: $output1" |