From c444702b93897896ba77c2cfce90cb0c6e65e2ee Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:16:35 +0000 Subject: [PATCH 1/9] ci: add concurrency control to all workflows to cancel stale runs https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- .github/workflows/build-test.yml | 16 ++++++++++ .../dockerhub-description-update.yml | 8 +++++ .github/workflows/lint-dockerfile.yml | 15 +++++++++ .github/workflows/push-latest.yml | 9 ++++++ .github/workflows/release.yml | 32 +++++++++++++++++++ 5 files changed, 80 insertions(+) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index c14160d..f651aed 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -18,6 +18,21 @@ on: - ".dockerignore" - "hadolint.yaml" - ".github/workflows/build-test.yml" + pull_request: + branches: + - master + paths: + - "Dockerfile" + - "supported_versions.json" + - "tests/**" + - ".github/workflows/build-test.yml" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read env: IMAGE_NAME: "terraform-aws-cli" @@ -97,5 +112,6 @@ jobs: AWS_CLI_VERSION=${{ matrix.awscli_versions }} tags: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} push: false + load: false cache-from: type=gha cache-to: type=gha,mode=max diff --git a/.github/workflows/dockerhub-description-update.yml b/.github/workflows/dockerhub-description-update.yml index 6e3fc2c..b7e5913 100644 --- a/.github/workflows/dockerhub-description-update.yml +++ b/.github/workflows/dockerhub-description-update.yml @@ -9,6 +9,14 @@ on: paths: - README.md - .github/workflows/dockerhub-description.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + jobs: dockerHubDescription: runs-on: ubuntu-22.04 diff --git a/.github/workflows/lint-dockerfile.yml b/.github/workflows/lint-dockerfile.yml index 020a694..2ae6b61 100644 --- a/.github/workflows/lint-dockerfile.yml +++ b/.github/workflows/lint-dockerfile.yml @@ -12,7 +12,22 @@ on: - "!master" paths: - "Dockerfile" + - "hadolint.yaml" - ".github/workflows/lint-dockerfile.yml" + pull_request: + branches: + - master + paths: + - "Dockerfile" + - "hadolint.yaml" + - ".github/workflows/lint-dockerfile.yml" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read jobs: lint: diff --git a/.github/workflows/push-latest.yml b/.github/workflows/push-latest.yml index eda62d0..5e1125e 100644 --- a/.github/workflows/push-latest.yml +++ b/.github/workflows/push-latest.yml @@ -3,6 +3,7 @@ name: push-latest # trigger on push to master # only on Dockerfile related modifications on: + workflow_dispatch: push: branches: - "master" @@ -16,6 +17,14 @@ on: - "supported_platforms.json" - "tests/**" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + packages: write + jobs: build_push_latest: runs-on: ubuntu-22.04 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 494c841..d1f73b6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,6 +5,15 @@ on: release: types: [published] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + packages: write + id-token: write # required for cosign keyless OIDC signing + jobs: load_supported_versions: runs-on: ubuntu-22.04 @@ -61,3 +70,26 @@ jobs: push: true cache-from: type=gha cache-to: type=gha,mode=max + + - name: Generate SBOM + uses: anchore/sbom-action@v0.24.0 + with: + image: zenika/terraform-aws-cli:release-${{ env.RELEASE_TAG }}_terraform-${{ matrix.tf_versions }}_awscli-${{ matrix.awscli_versions }} + format: spdx-json + output-file: sbom-tf${{ matrix.tf_versions }}-aws${{ matrix.awscli_versions }}.spdx.json + + - name: Upload SBOM to release + uses: anchore/sbom-action/publish-sbom@v0.24.0 + with: + sbom-artifact-match: ".*\\.spdx\\.json$" + + - name: Install cosign + uses: sigstore/cosign-installer@v4.1.1 + + - name: Sign published image + env: + COSIGN_EXPERIMENTAL: "true" + run: | + IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' \ + zenika/terraform-aws-cli:release-${{ env.RELEASE_TAG }}_terraform-${{ matrix.tf_versions }}_awscli-${{ matrix.awscli_versions }}) + cosign sign --yes "${IMAGE_DIGEST}" From d9848979653477a3823495c13f8b38f813b11a26 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:16:36 +0000 Subject: [PATCH 2/9] fix(dev.sh): implement getopts argument parsing and semver validation Replace positional argument parsing with getopts, add -a/-t/-i flags, and validate AWS and Terraform versions against semver regex before use. https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- dev.sh | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/dev.sh b/dev.sh index c9f83f4..461a9fd 100755 --- a/dev.sh +++ b/dev.sh @@ -1,27 +1,58 @@ #!/usr/bin/env bash -set -eo pipefail +set -euo pipefail -# FIXME: use getopts function to parse aguments -# FIXME: if provided, both TF and AWS CLI semvers should be regex-validated +trap 'echo "Error: script failed at line ${LINENO}" >&2' ERR + +usage() { + echo "Usage: $0 [-a AWS_CLI_VERSION] [-t TF_VERSION] [-i IMAGE_TAG]" + echo " -a AWS CLI version (default: latest from supported_versions.json)" + echo " -t Terraform version (default: latest from supported_versions.json)" + echo " -i Image tag (default: dev)" + exit 1 +} + +while getopts "a:t:i:h" opt; do + case ${opt} in + a) AWS_VERSION="${OPTARG}" ;; + t) TF_VERSION="${OPTARG}" ;; + i) IMAGE_TAG="${OPTARG}" ;; + h) usage ;; + *) usage ;; + esac +done # Set AWS and TF CLI to latest supported versions if not specified -[[ -n $1 ]] && AWS_VERSION=$1 || AWS_VERSION=$(jq -r '.awscli_versions | sort | .[-1]' supported_versions.json) -[[ -n $2 ]] && TF_VERSION=$2 || TF_VERSION=$(jq -r '.tf_versions | sort | .[-1]' supported_versions.json) +AWS_VERSION="${AWS_VERSION:-$(jq -r '.awscli_versions | sort | .[-1]' supported_versions.json)}" +TF_VERSION="${TF_VERSION:-$(jq -r '.tf_versions | sort | .[-1]' supported_versions.json)}" # Set image name and tag (dev if not specified) IMAGE_NAME="zenika/terraform-aws-cli" -[[ -n $3 ]] && IMAGE_TAG=$3 || IMAGE_TAG="dev" +IMAGE_TAG="${IMAGE_TAG:-dev}" + +SEMVER_REGEX="^[0-9]+\.[0-9]+\.[0-9]+$" + +validate_semver() { + local version="$1" + local name="$2" + if [[ ! "${version}" =~ ${SEMVER_REGEX} ]]; then + echo "Error: ${name} '${version}' is not a valid semver (expected X.Y.Z)" + exit 1 + fi +} + +validate_semver "${AWS_VERSION}" "AWS_CLI_VERSION" +validate_semver "${TF_VERSION}" "TERRAFORM_VERSION" -# Set platform for Hadolint image (only linux/arm64 or linux/arm64 supported) -PLATEFORM="linux/$(uname -m)" +# Set platform for Hadolint image (only linux/amd64 or linux/arm64 supported) +PLATFORM="linux/$(uname -m)" # Lint Dockerfile echo "Linting Dockerfile..." docker container run --rm --interactive \ --volume "${PWD}":/data \ --workdir /data \ - --platform "${PLATEFORM}" \ + --platform "${PLATFORM}" \ hadolint/hadolint:2.12.0-alpine /bin/hadolint \ --config hadolint.yaml Dockerfile echo "Lint Successful!" @@ -30,7 +61,7 @@ echo "Lint Successful!" echo "Building images with AWS_CLI_VERSION=${AWS_VERSION} and TERRAFORM_VERSION=${TF_VERSION}..." docker buildx build \ --progress plain \ - --platform "${PLATEFORM}" \ + --platform "${PLATFORM}" \ --build-arg AWS_CLI_VERSION="${AWS_VERSION}" \ --build-arg TERRAFORM_VERSION="${TF_VERSION}" \ --tag ${IMAGE_NAME}:${IMAGE_TAG} . From 9718a020a4353e7e13d3ebcfe460f477ccac3112 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:16:46 +0000 Subject: [PATCH 3/9] refactor(dockerfile): consolidate apt-get install layers in build stages Merge separate RUN apt-get install calls in the terraform and aws-cli stages into a single RUN with apt-get clean to reduce image layer count. https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- Dockerfile | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2af6f55..9c42882 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,12 +8,14 @@ ARG DEBIAN_FRONTEND=noninteractive FROM debian:${DEBIAN_VERSION} as terraform ARG TARGETARCH ARG TERRAFORM_VERSION -RUN apt-get update -# RUN apt-get install --no-install-recommends -y libcurl4=7.74.0-1.3+deb11u7 -RUN apt-get install --no-install-recommends -y ca-certificates=20230311 -RUN apt-get install --no-install-recommends -y curl=7.88.1-10+deb12u4 -RUN apt-get install --no-install-recommends -y gnupg=2.2.40-1.1 -RUN apt-get install --no-install-recommends -y unzip=6.0-28 +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + ca-certificates=20230311 \ + curl=7.88.1-10+deb12u4 \ + gnupg=2.2.40-1.1 \ + unzip=6.0-28 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* WORKDIR /workspace RUN curl --silent --show-error --fail --remote-name https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_${TARGETARCH}.zip COPY security/hashicorp.asc ./ @@ -26,13 +28,16 @@ RUN unzip -j terraform_${TERRAFORM_VERSION}_linux_${TARGETARCH}.zip # Install AWS CLI version 2 FROM debian:${DEBIAN_VERSION} as aws-cli ARG AWS_CLI_VERSION -RUN apt-get update -RUN apt-get install -y --no-install-recommends ca-certificates=20230311 -RUN apt-get install -y --no-install-recommends curl=7.88.1-10+deb12u4 -RUN apt-get install -y --no-install-recommends gnupg=2.2.40-1.1 -RUN apt-get install -y --no-install-recommends unzip=6.0-28 -RUN apt-get install -y --no-install-recommends git=1:2.39.2-1.1 -RUN apt-get install -y --no-install-recommends jq=1.6-2.1 +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates=20230311 \ + curl=7.88.1-10+deb12u4 \ + gnupg=2.2.40-1.1 \ + unzip=6.0-28 \ + git=1:2.39.2-1.1 \ + jq=1.6-2.1 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* WORKDIR /workspace RUN curl --show-error --fail --output "awscliv2.zip" --remote-name "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWS_CLI_VERSION}.zip" COPY security/awscliv2.asc ./ From a730f83da564a2c16a4158ef8d4024eb707e707f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:16:50 +0000 Subject: [PATCH 4/9] test: extend container structure tests with path and user verification Add commandTests to verify terraform and aws binaries are in PATH, confirm the container runs as nonroot (uid 1001), and that HOME is set. https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- tests/container-structure-tests.yml.template | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/container-structure-tests.yml.template b/tests/container-structure-tests.yml.template index 619fc87..efe73d4 100644 --- a/tests/container-structure-tests.yml.template +++ b/tests/container-structure-tests.yml.template @@ -33,6 +33,31 @@ commandTests: args: ["--version"] expectedOutput: ["aws-cli/${AWS_VERSION}"] + - name: "Check terraform is in PATH" + command: "which" + args: ["terraform"] + expectedOutput: ["/usr/local/bin/terraform"] + + - name: "Check aws is in PATH" + command: "which" + args: ["aws"] + expectedOutput: ["/usr/local/bin/aws"] + + - name: "Check running as non-root user" + command: "id" + args: ["-u"] + expectedOutput: ["1001"] + + - name: "Check running as nonroot user" + command: "id" + args: ["-un"] + expectedOutput: ["nonroot"] + + - name: "Check HOME directory is set" + command: "sh" + args: ["-c", "echo $HOME"] + expectedOutput: ["/home/nonroot"] + fileExistenceTests: - name: 'Check non-root user home' path: '/home/nonroot' From 3616dbba87edde9d4a4e69380bdd2bbd16786f40 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:17:15 +0000 Subject: [PATCH 5/9] docs: add CONTRIBUTING.md with conventional commits guide and dev workflow https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- CONTRIBUTING.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..476c938 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,67 @@ +# Contributing + +Thank you for your interest in contributing to this project! + +## How to contribute + +1. Fork the repository +2. Create a branch from `master`: `git checkout -b feat/my-feature` +3. Make your changes +4. Ensure tests pass locally: `./dev.sh` +5. Commit using [Conventional Commits](#commit-convention) +6. Push and open a Pull Request targeting `master` + +## Commit convention + +This project follows the [Conventional Commits](https://www.conventionalcommits.org/) specification. + +Format: `(): ` + +Common types: +| Type | Use for | +|------|---------| +| `feat` | New feature | +| `fix` | Bug fix | +| `chore` | Maintenance, dependency updates | +| `ci` | CI/CD changes | +| `docs` | Documentation only | +| `refactor` | Code refactoring | +| `test` | Test additions or fixes | +| `security` | Security improvements | + +Examples: +``` +feat: add support for terraform 2.0 +fix(dev.sh): correct platform detection on arm64 +chore(deps): update debian base image to bookworm-20250101-slim +ci: add trivy vulnerability scanning +``` + +PR titles must also follow this convention — the title becomes the squash-merge commit message. + +## Local development + +Requirements: Docker, `jq`, `envsubst` + +```bash +# Build and test with latest supported versions +./dev.sh + +# Build and test with specific versions +./dev.sh -a 2.17.0 -t 1.9.0 + +# Build with a custom tag +./dev.sh -a 2.17.0 -t 1.9.0 -i my-test +``` + +## Adding a new tool version + +When Terraform or AWS CLI releases a new version: + +1. Add the version to `supported_versions.json` +2. Download the verification files to `security/` — see [`docs/binaries-verifications.md`](docs/binaries-verifications.md) +3. Open a PR with the changes + +## Code review + +All PRs require at least one approval. The CI must pass (lint, build, tests) before merging. From d4054554eb18e3a889517cd3a34f290fb1acb37e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:17:18 +0000 Subject: [PATCH 6/9] ci: add CODEOWNERS for critical files https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- .github/CODEOWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..b5e5c09 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,8 @@ +# Global owner +* @bgauduch + +# Critical files require explicit review +Dockerfile @bgauduch +.github/workflows/ @bgauduch +security/ @bgauduch +supported_versions.json @bgauduch From b5f676d7fed9c864ed5eaad3d9dc3d533a6c1262 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:17:20 +0000 Subject: [PATCH 7/9] ci: add OpenSSF Scorecard workflow https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- .github/workflows/scorecard.yml | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..ac39f2f --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,37 @@ +name: scorecard +on: + branch_protection_rule: + schedule: + - cron: "30 1 * * 1" + push: + branches: + - master + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-22.04 + permissions: + security-events: write + id-token: write + contents: read + actions: read + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: ossf/scorecard-action@v2.4.3 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + - uses: actions/upload-artifact@v4 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + - uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif From d56bb19c7ea86eee61a2c3962230dfe16f6c712e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:17:23 +0000 Subject: [PATCH 8/9] docs: add badges and security/contributing links to README https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 68d7af0..bd60ab0 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ # Terraform and AWS CLI Docker image +[![CI](https://github.com/bgauduch/terraform-aws-cli/actions/workflows/build-test.yml/badge.svg)](https://github.com/bgauduch/terraform-aws-cli/actions/workflows/build-test.yml) +[![Latest Release](https://img.shields.io/github/v/release/bgauduch/terraform-aws-cli)](https://github.com/bgauduch/terraform-aws-cli/releases/latest) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/bgauduch/terraform-aws-cli/badge)](https://securityscorecards.dev/viewer/?uri=github.com/bgauduch/terraform-aws-cli) + ## 📦 Supported tags and respective Dockerfile links Available image tags can be found on the Docker Hub registry: [zenika/terraform-aws-cli](https://hub.docker.com/r/zenika/terraform-aws-cli/tags) @@ -90,6 +94,14 @@ TERRAFORM_VERSION=1.5.2 ## 🙏 Contributions Do not hesitate to contribute by [filling an issue](https://github.com/Zenika/terraform-aws-cli/issues) or [a PR](https://github.com/Zenika/terraform-aws-cli/pulls) ! +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to contribute to this project. + +## Security + +See [SECURITY.md](SECURITY.md) for the security policy and how to report vulnerabilities. + ## 📚 Documentations * [Dependencies upgrades checklist](https://github.com/zenika-open-source/terraform-aws-cli/tree/master/docs/dependencies-upgrades.md) From 86b0bb6afcfdf5836276f630fbfe08995cd027c5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 18:17:26 +0000 Subject: [PATCH 9/9] docs: update dependencies upgrade guide for renovate automation https://claude.ai/code/session_01RsmDFm6w4jVXwvzmRd9BCv --- docs/dependencies-upgrades.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/dependencies-upgrades.md b/docs/dependencies-upgrades.md index 7819ffe..9c9e2e8 100644 --- a/docs/dependencies-upgrades.md +++ b/docs/dependencies-upgrades.md @@ -1,5 +1,11 @@ # ⬆️ Dependencies upgrades checklist +> **Note:** Dependency management is now partially automated via [Renovate](https://docs.renovatebot.com/): +> - **GitHub Actions** versions are updated automatically by Renovate. +> - **Base Debian image** version is updated automatically by Renovate. +> +> **Tool versions (Terraform, AWS CLI) still require manual steps:** when adding a new supported version, the binary verification files must be downloaded manually to `security/` — see [`docs/binaries-verifications.md`](binaries-verifications.md). + * Supported tools versions: * [Report to the doc](https://github.com/zenika-open-source/terraform-aws-cli/tree/master/docs/binaries-verifications.md) to add required security files when adding a new supported versions * check available **AWS CLI** version on the [project release page](https://github.com/aws/aws-cli/tags)