Skip to content

Fixes: https://gitlab.com/l3montree/geschaeftsentwicklung/-/issues/463 #18

Fixes: https://gitlab.com/l3montree/geschaeftsentwicklung/-/issues/463

Fixes: https://gitlab.com/l3montree/geschaeftsentwicklung/-/issues/463 #18

Workflow file for this run

# DevSecOps Workflow Definition
name: DevSecOps Workflow
on:
push:
permissions:
contents: read
jobs:
# Secret scanning job to detect secrets in codebase
secret-scanning:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4 # Check out the repository content to the runner
with:
fetch-depth: 0
- name: Run Gitleaks Scan
# Running Gitleaks to scan the code for secrets
run: |
docker run --rm -v $(pwd):/code -u $(id -u):$(id -g) zricethezav/gitleaks:v8.18.4@sha256:75bdb2b2f4db213cde0b8295f13a88d6b333091bbfbf3012a4e083d00d31caba -s /code detect -v
# Software Composition Analysis (SCA) to find vulnerabilities in project dependencies
sca:
runs-on: ubuntu-latest
continue-on-error: true
permissions:
contents: read
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner in fs mode
# Running Trivy to scan the filesystem for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
scan-type: "fs"
scan-ref: "."
exit-code: '1'
ignore-unfixed: true
severity: "CRITICAL,HIGH"
iac:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Test with Checkov
id: checkov
uses: bridgecrewio/checkov-action@master
with:
directory: .
quiet: true
# Static Application Security Testing (SAST) to identify security vulnerabilities in source code
sast:
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Semgrep
# Running Semgrep for static code analysis to identify security issues
uses: docker://returntocorp/semgrep
with:
args: semgrep scan /github/workspace
# Docker image build job
build-image:
permissions:
packages: write
contents: read
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v4
- name: Set IMAGE_TAG if tagged
# Setting the image tag if the push is a tag push
run: |
export IMAGE_TAG="ghcr.io/${{ github.repository }}:${GITHUB_REF#refs/tags/}"
export IMAGE_TAG=$(echo $IMAGE_TAG | tr '[:upper:]' '[:lower:]')
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
echo $IMAGE_TAG > image-tag.txt
if: startsWith(github.ref, 'refs/tags/')
- name: Set IMAGE_TAG if not tagged
run: |
branch=${GITHUB_REF##*/}
sha=${GITHUB_SHA::8}
ts=$(date +%s)
export IMAGE_TAG="ghcr.io/${{ github.repository }}:${branch}-${sha}-${ts}"
export IMAGE_TAG=$(echo $IMAGE_TAG | tr '[:upper:]' '[:lower:]')
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
echo $IMAGE_TAG > image-tag.txt
if: github.ref == 'refs/heads/main'
- name: Build Docker image with Kaniko
# Building the Docker image using Kaniko
id: build_image
uses: docker://gcr.io/kaniko-project/executor:v1.23.2
with:
args: --destination=${{ env.IMAGE_TAG }} --context=/github/workspace --dockerfile=/github/workspace/Dockerfile --no-push --tarPath /github/workspace/image.tar
- name: Setup crane
uses: imjasonh/[email protected]
- name: Use crane to get the digest
run: crane digest --tarball=image.tar > digest.txt
- name: Upload artifact
# Uploading the built Docker image as an artifact
uses: actions/upload-artifact@v4
with:
name: docker-image
path: image.tar
- name: Upload digest
# Uploading the built Docker image digest as an artifact
uses: actions/upload-artifact@v4
with:
name: digest
path: digest.txt
- name: Upload image tag
uses: actions/upload-artifact@v4
with:
name: image-tag
path: image-tag.txt
# Image scanning job to detect vulnerabilities in the built Docker image
image-scanning:
needs: build-image
continue-on-error: true
permissions:
contents: read
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: docker-image
path: .
- name: Run Trivy vulnerability scanner in tarball mode
# Running Trivy to scan the Docker image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
input: /github/workspace/image.tar
exit-code: '1'
ignore-unfixed: true
severity: "CRITICAL,HIGH"
# Publish job to push the Docker image to a registry
publish:
needs: [build-image, image-scanning, secret-scanning, sca, sast, iac]
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/download-artifact@v4
with:
name: docker-image
path: .
- uses: actions/download-artifact@v4
with:
name: image-tag
path: .
- name: set IMAGE_TAG env
run: |
export IMAGE_TAG=$(cat image-tag.txt)
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
- uses: imjasonh/[email protected]
- name: Push Docker image to GitHub image Registry
# Pushing the Docker image to GitHub Container Registry
run: crane push image.tar ${{ env.IMAGE_TAG }}
sbom:
runs-on: ubuntu-latest # Specify the runner
needs: [build-image]
container:
image: alpine:3.20@sha256:77726ef6b57ddf65bb551896826ec38bc3e53f75cdde31354fbffb4f25238ebd
steps:
- name: Install curl
run: apk add --update curl
- name: Install Syft
run: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- name: Download artifact from previous build
uses: actions/download-artifact@v4
with:
name: docker-image
- name: Generate SBOM with Syft
run: syft ./image.tar -o cyclonedx-json=sbom.json
- name: Upload SBOM as an artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
sign-image:
permissions:
packages: write
contents: read
runs-on: ubuntu-latest
needs: publish
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- name: cosign-installer
uses: sigstore/[email protected]
with:
cosign-release: 'v2.2.3' # optional
- name: Download digest
uses: actions/download-artifact@v4
with:
name: digest
path: .
- name: Download image tag
uses: actions/download-artifact@v4
with:
name: image-tag
path: .
- name: Read digest and image tag from file
run: |
export IMAGE_DIGEST=$(cat digest.txt)
echo "IMAGE_DIGEST=$IMAGE_DIGEST" >> $GITHUB_ENV
export IMAGE_TAG=$(cat image-tag.txt)
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Write signing key to disk (only needed for `cosign sign --key`)
run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key
- name: Sign the published Docker image
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
run: cosign sign --yes --key cosign.key "$(cat image-tag.txt)@${{ env.IMAGE_DIGEST }}"
sign-sbom:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
needs: publish
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/devsecops-ci'
steps:
- name: cosign-installer
uses: sigstore/[email protected]
with:
cosign-release: 'v2.2.3' # optional
- name: Download digest
uses: actions/download-artifact@v4
with:
name: digest
path: .
- name: Download image tag
uses: actions/download-artifact@v4
with:
name: image-tag
path: .
- name: Download sbom tag
uses: actions/download-artifact@v4
with:
name: sbom
path: .
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Write signing key to disk (only needed for `cosign sign --key`)
run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key
- name: Sign SBOM
run: cosign attest --yes --predicate ./sbom.json --key cosign.key "$(cat image-tag.txt)@$(cat digest.txt)"
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}