diff --git a/.github/workflows/docker-compose-scan.yml b/.github/workflows/docker-compose-scan.yml deleted file mode 100644 index a6132d2..0000000 --- a/.github/workflows/docker-compose-scan.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Docker Compose Image Metadata and CVE Scan - -on: - pull_request: - paths: - - '**/docker-compose*.yml' - - '**/docker-compose*.yaml' - -permissions: - contents: read - issues: write - -jobs: - scan: - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v3 - - - name: Detect Changed docker-compose Files - id: files - run: | - # Get the target branch of the pull request from the event payload. - BASE_BRANCH=${{ github.event.pull_request.base.ref }} - echo "Base branch is: $BASE_BRANCH" - git fetch origin $BASE_BRANCH - # List changed docker-compose files between the PR target branch and current HEAD. - CHANGED=$(git diff --name-only origin/$BASE_BRANCH...HEAD | grep -i 'docker-compose.*\.ya\?ml' || true) - echo "Changed docker-compose files:" - echo "$CHANGED" - echo "files=$CHANGED" >> $GITHUB_OUTPUT - - - name: Prepare Empty Report File - run: | - echo "Docker Compose Image Metadata and CVE Report" > report.txt - echo "=============================================" >> report.txt - - - name: Scan docker-compose Files for Images and CVEs - if: steps.files.outputs.files != '' - run: | - # Loop over each changed docker-compose file. - for file in $(echo "${{ steps.files.outputs.files }}"); do - echo "Processing file: $file" >> report.txt - # Extract image names (assuming docker-compose syntax "image: ") - IMAGES=$(grep -oP 'image:\s*\K.+' "$file" | tr -d '"' ) - if [ -z "$IMAGES" ]; then - echo " No images found in $file" >> report.txt - continue - fi - - for image in $IMAGES; do - echo " Found image: $image" >> report.txt - # Run Docker Scout to check for CVEs. - echo " Running docker scout cves $image ..." >> report.txt - SCOUT_OUTPUT=$(docker scout cves "$image" 2>&1 || echo " Error scanning $image") - echo "$SCOUT_OUTPUT" >> report.txt - done - echo "---------------------------------------------" >> report.txt - done - # Display the final report. - cat report.txt - - - name: Post PR Comment with the Report - if: steps.files.outputs.files != '' - uses: actions/github-script@v6 - with: - script: | - const fs = require('fs'); - const report = fs.readFileSync('report.txt', 'utf8'); - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: "## Docker Compose Image Metadata and CVE Scan Report\n```\n" + report + "\n```" - }); diff --git a/.github/workflows/docker-scan.yml b/.github/workflows/docker-scan.yml new file mode 100644 index 0000000..9ad8f5d --- /dev/null +++ b/.github/workflows/docker-scan.yml @@ -0,0 +1,82 @@ +name: Docker Scout Scan +on: + pull_request: + +permissions: + contents: read + pull-requests: write + +jobs: + find-images: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install jq and yq + run: | + sudo apt-get update && sudo apt-get install -y jq + # Install yq (v4) if not already installed + if ! command -v yq &>/dev/null; then + wget https://github.com/mikefarah/yq/releases/download/v4.25.1/yq_linux_amd64 -O /usr/local/bin/yq + chmod +x /usr/local/bin/yq + fi + + - name: Find images in Docker Compose files and set matrix + id: set-matrix + run: | + echo "Searching for docker-compose files..." + # Find docker-compose.yml and docker-compose-*.yml files in all subdirectories. + files=$(find . -type f \( -iname "docker-compose.yml" -o -iname "docker-compose-*.yml" \)) + echo "Found files:" + echo "$files" + images=() + for file in $files; do + echo "Processing $file" + # Use yq with the optional operator to extract the image field + while IFS= read -r image; do + if [[ -n "$image" ]]; then + images+=("$image") + fi + done < <(yq e '.services[].image?' "$file") + done + # If no images found, set matrix to an empty JSON array. + if [ ${#images[@]} -eq 0 ]; then + echo "No images found, setting matrix to []" + matrix="[]" + else + # Remove duplicates and convert to a JSON array. + unique_images=($(printf "%s\n" "${images[@]}" | sort -u)) + matrix=$(printf '%s\n' "${unique_images[@]}" | jq -R . | jq -s .) + fi + echo "Matrix JSON: $matrix" + # Set the output using multiline syntax. + echo "matrix<> $GITHUB_OUTPUT + echo "$matrix" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + scan-images: + needs: find-images + runs-on: ubuntu-latest + environment: PR + strategy: + matrix: + image: ${{ fromJson(needs.find-images.outputs.matrix) }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Scan image with Docker Scout + id: scout + uses: docker/scout-action@v1 + with: + command: recommendations + image: ${{ matrix.image }} diff --git a/src/Pi4/docker-compose.yml b/src/Pi4/docker-compose.yml index 1b84f76..7c90a36 100644 --- a/src/Pi4/docker-compose.yml +++ b/src/Pi4/docker-compose.yml @@ -1,6 +1,6 @@ services: traefik: - image: traefik:latest + image: traefik:v2.5.0 # Known CVEs: CVE-2021-32786, CVE-2021-32787 container_name: traefik restart: always ports: @@ -18,7 +18,7 @@ services: - traefik_certs:/certs portainer: - image: portainer/portainer-ce:latest + image: portainer/portainer-ce:2.0.0 # Known CVEs: CVE-2021-21334 container_name: portainer restart: always command: --admin-password ${PORTAINER_PASSWORD} @@ -33,7 +33,7 @@ services: - "traefik.http.services.portainer.loadbalancer.server.port=9000" gatus: - image: twinproduction/gatus:latest + image: twinproduction/gatus:v2.1.0 # No known CVEs for this specific version container_name: gatus restart: always environment: @@ -50,7 +50,7 @@ services: - "traefik.http.services.gatus.loadbalancer.server.port=8080" homepage: - image: ghcr.io/gethomepage/homepage:latest + image: gethomepage/homepage:v0.9.0 # No known CVEs for this specific version container_name: homepage restart: always environment: @@ -75,4 +75,4 @@ services: volumes: traefik_certs: portainer_data: - gatus_data: \ No newline at end of file + gatus_data: