4 Commits

Author SHA1 Message Date
dresber 83911b842f implement an edge tag and update image security check accordingly 2026-06-14 09:51:36 +02:00
dresber f92d92355a add docker image scanner 2026-06-12 15:10:21 +02:00
dresber 364171ebca fix(python-security-checks): use custom runner image instead of python slim
python:3.14-slim has no Node.js so actions/checkout@v4 fails with
'node: executable file not found in PATH'. Switch to the same
gitea_runner_python314 custom image used by python-checks.yml which
has both Python 3.14 and Node.js. Drop the python_version input as it
no longer drives the container selection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 14:43:38 +02:00
dresber 2be1150eec feat: add python-security-checks reusable workflow
Dedicated security-only workflow using python:VERSION-slim.
Runs Bandit (or any security tool) without pytest or coverage.
Supports python_version, install_command, security_command,
and working_directory inputs with sensible defaults.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 20:43:00 +02:00
3 changed files with 157 additions and 0 deletions
+49
View File
@@ -9,6 +9,15 @@ on:
dockerfile_path:
type: string
default: "."
floating_tag:
type: string
default: "edge"
run_image_scan:
type: boolean
default: true
scan_severity:
type: string
default: "HIGH,CRITICAL"
secrets:
REGISTRY_USERNAME: { required: true }
REGISTRY_PASSWORD: { required: true }
@@ -62,6 +71,11 @@ jobs:
-t "${FULL_IMAGE}:${SHA_SHORT}" \
${{ inputs.dockerfile_path }}
# Floating tag points at the most recent build on any branch/tag, so
# the nightly image-security scan always has a stable target even
# before a release exists. ":latest" stays release-only (below).
docker tag "${FULL_IMAGE}:${SHA_SHORT}" "${FULL_IMAGE}:${{ inputs.floating_tag }}"
if echo "${{ gitea.ref }}" | grep -q '^refs/tags/v'; then
VERSION="${{ gitea.ref_name }}"
VERSION="${VERSION#v}"
@@ -74,6 +88,38 @@ jobs:
docker tag "${FULL_IMAGE}:${SHA_SHORT}" "${FULL_IMAGE}:${MAJOR}"
fi
- name: Image Vulnerability Scan
if: ${{ inputs.run_image_scan }}
shell: bash
run: |
set -euo pipefail
# Fallback for runner images without Trivy baked in. Pinned version +
# checksum, never "latest": Trivy releases were compromised in the
# March 2026 supply-chain incident (malicious v0.69.4). Keep in sync
# with the ARGs in the PipelineImage Dockerfiles.
TRIVY_VERSION=0.71.0
TRIVY_SHA256=30a3d22b23f88c233f1658f562fb477cae3b3e8b4761109d515b7698daf85814
if ! command -v trivy >/dev/null 2>&1; then
echo "=== Trivy not in runner image, installing v${TRIVY_VERSION} ==="
curl -sSfLO "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
echo "${TRIVY_SHA256} trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz" | sha256sum -c -
tar -xzf "trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz" -C /usr/local/bin trivy
rm "trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
fi
trivy --version
SHA_SHORT="$(git rev-parse --short HEAD)"
FULL_IMAGE="${{ secrets.DOCKER_REGISTRY }}/${{ inputs.image_name }}"
echo "=== Scanning ${FULL_IMAGE}:${SHA_SHORT} (fail on fixable ${{ inputs.scan_severity }}) ==="
trivy image \
--exit-code 1 \
--severity "${{ inputs.scan_severity }}" \
--ignore-unfixed \
--scanners vuln,secret \
"${FULL_IMAGE}:${SHA_SHORT}"
- name: Push image
shell: bash
run: |
@@ -105,6 +151,9 @@ jobs:
echo "=== Push SHA tag ==="
docker push "${FULL_IMAGE}:${SHA_SHORT}"
echo "=== Push floating tag (${{ inputs.floating_tag }}) ==="
docker push "${FULL_IMAGE}:${{ inputs.floating_tag }}"
if echo "${{ gitea.ref }}" | grep -q '^refs/tags/v'; then
echo "=== Version tag detected ==="
@@ -0,0 +1,70 @@
name: Reusable Image Security Checks
on:
workflow_call:
inputs:
image_name:
required: true
type: string
image_tag:
type: string
default: "edge"
scan_severity:
type: string
default: "HIGH,CRITICAL"
secrets:
REGISTRY_USERNAME: { required: true }
REGISTRY_PASSWORD: { required: true }
DOCKER_REGISTRY: { required: true }
jobs:
scan:
runs-on: docker
container:
image: gitea.tech-buddy.at/bitbuddydev/gitea_runner_python314:dev-bda315b82bb23d83065b77d91fedf0e20d9accf1
credentials:
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
steps:
- name: Docker Login
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "${{ secrets.DOCKER_REGISTRY }}" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
- name: Pull Image
shell: bash
run: |
set -euo pipefail
FULL_IMAGE="${{ secrets.DOCKER_REGISTRY }}/${{ inputs.image_name }}:${{ inputs.image_tag }}"
echo "=== Pulling ${FULL_IMAGE} ==="
docker pull "${FULL_IMAGE}"
- name: Image Vulnerability Scan
shell: bash
run: |
set -euo pipefail
# Fallback for runner images without Trivy baked in. Pinned version +
# checksum, never "latest": Trivy releases were compromised in the
# March 2026 supply-chain incident (malicious v0.69.4). Keep in sync
# with the ARGs in the PipelineImage Dockerfiles.
TRIVY_VERSION=0.71.0
TRIVY_SHA256=30a3d22b23f88c233f1658f562fb477cae3b3e8b4761109d515b7698daf85814
if ! command -v trivy >/dev/null 2>&1; then
echo "=== Trivy not in runner image, installing v${TRIVY_VERSION} ==="
curl -sSfLO "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
echo "${TRIVY_SHA256} trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz" | sha256sum -c -
tar -xzf "trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz" -C /usr/local/bin trivy
rm "trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
fi
trivy --version
FULL_IMAGE="${{ secrets.DOCKER_REGISTRY }}/${{ inputs.image_name }}:${{ inputs.image_tag }}"
echo "=== Scanning ${FULL_IMAGE} (fail on fixable ${{ inputs.scan_severity }}) ==="
trivy image \
--exit-code 1 \
--severity "${{ inputs.scan_severity }}" \
--ignore-unfixed \
--scanners vuln,secret \
"${FULL_IMAGE}"
@@ -0,0 +1,38 @@
name: Reusable Python Security Checks
on:
workflow_call:
inputs:
install_command:
type: string
default: 'python -m pip install "bandit[toml]"'
security_command:
type: string
default: "python -m bandit -r app -c pyproject.toml"
working_directory:
type: string
default: "."
secrets:
REGISTRY_USERNAME: { required: true }
REGISTRY_PASSWORD: { required: true }
jobs:
security:
runs-on: docker
container:
image: gitea.tech-buddy.at/bitbuddydev/gitea_runner_python314:dev-bda315b82bb23d83065b77d91fedf0e20d9accf1
credentials:
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install security tools
working-directory: ${{ inputs.working_directory }}
run: ${{ inputs.install_command }}
- name: Run security scan
working-directory: ${{ inputs.working_directory }}
run: ${{ inputs.security_command }}