diff --git a/.github/workflows/chainloop-demo-build-container-image.yml b/.github/workflows/chainloop-demo-build-container-image.yml new file mode 100644 index 00000000000..aba3445dd7f --- /dev/null +++ b/.github/workflows/chainloop-demo-build-container-image.yml @@ -0,0 +1,118 @@ +name: Demo Spring Petclinic - Build Container Image +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + chainloop_init: + runs-on: ubuntu-latest + outputs: + att_id: ${{ steps.att_init.outputs.att_id }} + version: ${{ steps.att_init.outputs.version }} + steps: + - uses: actions/checkout@v4 + - name: Install Chainloop + run: | + curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s + - name: Initialize Attestation + id: att_init + run: | + VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout) + att_id=$(chainloop attestation init --workflow build-container-image --project demo-spring-petclinic --contract demo-spring-petclinic --version "$VERSION" --remote-state -o json | jq -r .attestationID) + echo "att_id=$att_id" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT + env: + CHAINLOOP_TOKEN: ${{ secrets.CHAINLOOP_TOKEN}} + + build_container: + runs-on: ubuntu-latest + env: + CHAINLOOP_TOKEN: ${{ secrets.CHAINLOOP_TOKEN }} + ATTESTATION_ID: ${{ needs.chainloop_init.outputs.att_id }} + VERSION: ${{ needs.chainloop_init.outputs.version }} + permissions: + packages: write + needs: chainloop_init + strategy: + matrix: + java: [ '17' ] + 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: Install dependencies and tools. + run: | + mkdir -p metadata + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin + curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + - name: Install cosign + uses: sigstore/cosign-installer@v2.5.0 + - name: Docker login to Github Packages + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build the jar file and generate SBOM. + run: | + chainloop attestation init --workflow build-container-image-jar --project demo-spring-petclinic --contract demo-spring-petclinic --version ${{ env.VERSION }} + + ./mvnw -B -Dmaven.test.skip=true clean package + syft packages -o cyclonedx-json=./metadata/jar.sbom.cyclonedx.json target/spring-petclinic-*.jar + + chainloop attestation add --name jar --value target/*.jar + chainloop attestation add --name jar-sbom --value ./metadata/jar.sbom.cyclonedx.json + + chainloop attestation push + + - name: Build a container image push to Github Packages. + run: | + docker build -t ghcr.io/${{ github.repository }}/spring-petclinic-demo:latest . + docker push ghcr.io/${{ github.repository }}/spring-petclinic-demo:latest + # cosign sign --key=env://COSIGN_PRIVATE_KEY ghcr.io/${{ github.repository }}/spring-petclinic-demo:latest + syft packages -o cyclonedx-json=./metadata/image.sbom.cyclonedx.json docker:ghcr.io/${{ github.repository }}/spring-petclinic-demo:latest + env: + COSIGN_PRIVATE_KEY: ${{secrets.COSIGN_PRIVATE_KEY}} + COSIGN_PASSWORD: ${{secrets.COSIGN_PASSWORD}} + + - name: Chainloop Attestation for the whole action and the container image (using remote state, requires attestation id). + run: | + chainloop att add --name image --value ghcr.io/${{ github.repository }}/spring-petclinic-demo:latest --attestation-id ${{ env.ATTESTATION_ID }} --remote-state + chainloop att add --name image-sbom --value ./metadata/image.sbom.cyclonedx.json --attestation-id ${{ env.ATTESTATION_ID }} --remote-state + chainloop att push --attestation-id ${{ env.ATTESTATION_ID }} --remote-state + + - name: Vulnerabilities Scan for the JAR file + run: | + chainloop attestation init --workflow vulnerabilities-scan-jar --project demo-spring-petclinic --contract demo-spring-petclinic --version ${{ env.VERSION }} + trivy rootfs target/*.jar --format sarif -o ./metadata/cve-scan-report-jar.sarif + chainloop att add --name jar --value target/*.jar + chainloop att add --name cve-scan-report --value ./metadata/cve-scan-report-jar.sarif + if [ $(chainloop att status -o json | jq .hasPolicyViolations) == "true" ]; then + echo "Policy Violations found for the JAR file" + exit 1 + fi + chainloop att push + + - name: Vulnerabilities Scan for the container image + run: | + chainloop attestation init --workflow vulnerabilities-scan-image --project demo-spring-petclinic --contract demo-spring-petclinic --version ${{ env.VERSION }} + trivy image ghcr.io/${{ github.repository }}/spring-petclinic-demo:latest --format sarif -o ./metadata/cve-scan-report-image.sarif + chainloop att add --name image --value ghcr.io/${{ github.repository }}/spring-petclinic-demo:latest + chainloop att add --name cve-scan-report --value ./metadata/cve-scan-report-image.sarif + chainloop att push + + - uses: actions/upload-artifact@v4 + with: + name: artifacts + path: target/*.jar + - uses: actions/upload-artifact@v4 + with: + name: metadata + path: metadata/* \ No newline at end of file diff --git a/.github/workflows/chainloop-demo-test.yml b/.github/workflows/chainloop-demo-test.yml new file mode 100644 index 00000000000..3765f23a1a6 --- /dev/null +++ b/.github/workflows/chainloop-demo-test.yml @@ -0,0 +1,39 @@ +name: Demo Spring Petclinic - Testing +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + test: + runs-on: ubuntu-latest + env: + CHAINLOOP_TOKEN: ${{ secrets.CHAINLOOP_TOKEN }} + strategy: + matrix: + java: [ '17' ] + 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: Install dependencies and tools. + run: | + mkdir -p metadata + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin + curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s + + - name: Build the jar file and generate SBOM. + run: | + VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout) + chainloop attestation init --workflow test --project demo-spring-petclinic --contract demo-spring-petclinic --version "$VERSION" + + ./mvnw clean verify jacoco:report > test.log 2>&1 + chainloop attestation add --name test-log --value ./test.log + chainloop attestation add --name test-report --value target/site/jacoco/jacoco.xml + + chainloop attestation push + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..893b19f5416 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM bellsoft/liberica-runtime-container:jdk-21-stream-musl as builder +WORKDIR /home/app +COPY target/*.jar . + +FROM bellsoft/liberica-runtime-container:jdk-21-stream-musl as optimizer +WORKDIR /home/app +COPY --from=builder /home/app/*.jar petclinic.jar +RUN java -Djarmode=layertools -jar petclinic.jar extract + +FROM bellsoft/liberica-runtime-container:jre-21-stream-musl +ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"] +COPY --from=optimizer /home/app/dependencies/ ./ +COPY --from=optimizer /home/app/spring-boot-loader/ ./ +COPY --from=optimizer /home/app/snapshot-dependencies/ ./ +COPY --from=optimizer /home/app/application/ ./