diff --git a/.github/workflows/shared-steps.yml b/.github/workflows/shared-steps.yml new file mode 100644 index 0000000..0510741 --- /dev/null +++ b/.github/workflows/shared-steps.yml @@ -0,0 +1,64 @@ +on: + workflow_call: + inputs: + registry: + required: true + type: string + do_tag: + required: true + type: string # boolean exists, but that will be a string as ENV VAR. Set to YES or NOPE + secrets: + token: + required: false + +jobs: + reusable: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + if: ${{github.event_name != 'pull_request'}} + uses: docker/login-action@v3 + with: + registry: ${{ inputs.registry }} + username: ${{ github.actor }} + password: ${{ secrets.token }} + + - name: Do some shell magic + shell: bash + id: sh_settings + env: + DO_TAG: ${{inputs.do_tag}} + run: | + if [ $DO_TAG = 'YES' ]; then + echo "tag=lite-${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + else + echo "tag=lite" >> $GITHUB_OUTPUT + fi + echo "repository=${GITHUB_REPOSITORY@L}" >> $GITHUB_OUTPUT + + - name: '[LITE] Build container image, (and push)' + id: push + uses: docker/build-push-action@v6 + with: + cache-from: ${{inputs.registry}}/${{github.repository}}/tools:${{ steps.sh_settings.outputs.tag }} + file: docker/Dockerfile.lite + context: docker + tags: ${{inputs.registry}}/${{ steps.sh_settings.outputs.repository }}/tools:${{ steps.sh_settings.outputs.tag }} + platforms: linux/amd64,linux/arm64 + push: ${{github.event_name != 'pull_request'}} + + - name: '[LITE] Generate artifact attestation' + if: ${{github.event_name != 'pull_request'}} + uses: actions/attest-build-provenance@v1 + with: + subject-name: ${{ inputs.registry }}//${{ steps.sh_settings.outputs.repository }} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true + \ No newline at end of file diff --git a/.github/workflows/tools-lite-container-latest.yml b/.github/workflows/tools-lite-container-latest.yml new file mode 100644 index 0000000..13929db --- /dev/null +++ b/.github/workflows/tools-lite-container-latest.yml @@ -0,0 +1,26 @@ +name: '[LITE] Tools Container - Publish Latest' + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - 'docker/**' + - '.github/**' + +jobs: + publish_latest: + name: Push latest [LITE] container image to GitHub Packages + permissions: + contents: read + packages: write + attestations: write + id-token: write + uses: ./.github/workflows/shared-steps.yml + with: + registry: ghcr.io + do_tag: 'NOPE' + secrets: + token: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.github/workflows/tools-lite-container-pr.yaml b/.github/workflows/tools-lite-container-pr.yaml new file mode 100644 index 0000000..570a7ae --- /dev/null +++ b/.github/workflows/tools-lite-container-pr.yaml @@ -0,0 +1,15 @@ +name: '[LITE] Tools Container - PR Validation' + +on: + workflow_dispatch: + pull_request: + paths: + - 'docker/**' + +jobs: + pr_validation: + name: '[LITE] PR Validation' + uses: ./.github/workflows/shared-steps.yml + with: + registry: ghcr.io + do_tag: 'NOPE' diff --git a/.github/workflows/tools-lite-container-tag.yaml b/.github/workflows/tools-lite-container-tag.yaml new file mode 100644 index 0000000..c724512 --- /dev/null +++ b/.github/workflows/tools-lite-container-tag.yaml @@ -0,0 +1,22 @@ +name: '[LITE] Tools Container - Publish Tag' + +on: + workflow_dispatch: + release: + types: + - published + +jobs: + publish_latest: + name: '[LITE] Push tagged container image to GitHub Packages' + permissions: + contents: read + packages: write + attestations: write + id-token: write + uses: ./.github/workflows/shared-steps.yml + with: + registry: ghcr.io + do_tag: 'YES' + secrets: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/docker/Dockerfile b/docker/Dockerfile index f90acfe..a4a39b7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.21 as tf-prepare-builder +FROM golang:1.21 AS tf-prepare-builder WORKDIR /workspace COPY ./go-tf-prepare/go.mod ./go-tf-prepare/go.sum ./ @@ -12,7 +12,7 @@ FROM debian:12.2-slim #Base RUN apt-get update -y RUN apt-get install -y git curl openssl pip make unzip gpg wget apt-utils -RUN apt-get install -y ansible=7.3.0+dfsg-1 +RUN apt-get install -y ansible=7.7.0+dfsg-3+deb12u1 RUN mkdir -p /tmp/install /usr/src /work WORKDIR /tmp/install diff --git a/docker/Dockerfile.lite b/docker/Dockerfile.lite new file mode 100644 index 0000000..15a26e2 --- /dev/null +++ b/docker/Dockerfile.lite @@ -0,0 +1,76 @@ +FROM golang:1.23-bookworm AS tf-prepare-builder +WORKDIR /workspace +ARG TARGETARCH + +COPY ./go-tf-prepare/go.mod ./go-tf-prepare/go.sum ./ +RUN go mod download +COPY ./go-tf-prepare/main.go main.go +COPY ./go-tf-prepare/pkg/ pkg/ +RUN GOOS=linux GOARCH=$TARGETARCH GO111MODULE=on go build -o tf-prepare main.go + +FROM debian:bookworm-slim + +#Base +RUN apt-get update -y +RUN apt-get install -y git curl openssl pip make unzip gpg wget apt-utils + +RUN mkdir -p /tmp/install /usr/src /work +WORKDIR /tmp/install + +# Install Azure CLI +COPY install-scripts/azure-cli-lite.sh /usr/src/install-scripts/azure-cli.sh +RUN /usr/src/install-scripts/azure-cli.sh --version="2.64.0" + +# Install tflint +COPY install-scripts/tflint-lite.sh /usr/src/install-scripts/tflint.sh +RUN /usr/src/install-scripts/tflint.sh --version="v0.53.0" +COPY config/.tflint.hcl /work/.tflint.d/.tflint.hcl + +# Install tflint ruleset +COPY install-scripts/tflint-ruleset-lite.sh /usr/src/install-scripts/tflint-ruleset.sh +RUN /usr/src/install-scripts/tflint-ruleset.sh --ruleset="azurerm" --version="v0.27.0" + +# Install terraform (tfenv) +COPY install-scripts/tfenv.sh /usr/src/install-scripts/tfenv.sh +RUN /usr/src/install-scripts/tfenv.sh --latest-terraform-version="1.9.5" --tfenv-version="v3.0.0" + +# Install tfsec +COPY install-scripts/tfsec-lite.sh /usr/src/install-scripts/tfsec.sh +RUN /usr/src/install-scripts/tfsec.sh --version="v1.28.10" + +# Install Open Policy Agent, version 0.43.0 ??? +COPY install-scripts/opa-lite.sh /usr/src/install-scripts/opa.sh +RUN /usr/src/install-scripts/opa.sh --version="v0.68.0" + +# Install sops +COPY install-scripts/sops-lite.sh /usr/src/install-scripts/sops.sh +RUN /usr/src/install-scripts/sops.sh --version="v3.9.0" + +# Install GitHub CLI +COPY install-scripts/github-cli-lite.sh /usr/src/install-scripts/github-cli.sh +RUN /usr/src/install-scripts/github-cli.sh --version="2.58.0" + +# Install jq +COPY install-scripts/jq-lite.sh /usr/src/install-scripts/jq.sh +RUN /usr/src/install-scripts/jq.sh --version="1.6-2.1" + +# Install yq +COPY install-scripts/yq.sh /usr/src/install-scripts/yq.sh +RUN /usr/src/install-scripts/yq.sh --version="3.1.0-3" + +# Install tfprepare +COPY --from=tf-prepare-builder /workspace/tf-prepare /usr/local/bin/tf-prepare +RUN chmod +x /usr/local/bin/tf-prepare + +#Cleanup +RUN apt-get autoremove && \ + apt-get clean + +RUN rm -rf /tmp/install + +COPY opa-policies /opt/opa-policies +COPY terraform.sh /opt/terraform.sh + +ENV HOME=/work + +WORKDIR /work diff --git a/docker/install-scripts/azure-cli-lite.sh b/docker/install-scripts/azure-cli-lite.sh new file mode 100755 index 0000000..5f71142 --- /dev/null +++ b/docker/install-scripts/azure-cli-lite.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +echo "Adding keys to the keyring..." +mkdir -p /etc/apt/keyrings +curl -sLS https://packages.microsoft.com/keys/microsoft.asc | + gpg --dearmor | tee /etc/apt/keyrings/microsoft.gpg > /dev/null +echo "Keys added to the keyring, setting permissions..." +chmod go+r /etc/apt/keyrings/microsoft.gpg + +#AZ_DIST=$(lsb_release -cs) +AZ_DIST=$(grep -ioP '^VERSION_CODENAME=\K.+' /etc/os-release) +ARCHITECTURE=$(dpkg --print-architecture) +echo "Adding sources to the sources list, DIST=${AZ_DIST} and ARCH=${ARCHITECTURE}..." + +echo "Types: deb +URIs: https://packages.microsoft.com/repos/azure-cli/ +Suites: ${AZ_DIST} +Components: main +Architectures: ${ARCHITECTURE} +Signed-by: /etc/apt/keyrings/microsoft.gpg" | tee /etc/apt/sources.list.d/azure-cli.sources + +echo "Sources added to the sources list, updating apt and installing AZ CLI..." +apt-get update +apt-get install -y azure-cli=${VERSION}-1~${AZ_DIST} + +echo "AZ CLI installed..." +az version + +echo "Adding DEVOPS extension..." +az extension add --yes --allow-preview false --upgrade --name azure-devops +echo "Adding MANAGEMENTPARTNER extension..." +az extension add --yes --allow-preview false --upgrade --name managementpartner +echo "AZ CLI installation complete." \ No newline at end of file diff --git a/docker/install-scripts/github-cli-lite.sh b/docker/install-scripts/github-cli-lite.sh new file mode 100755 index 0000000..372835d --- /dev/null +++ b/docker/install-scripts/github-cli-lite.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +(type -p wget >/dev/null || (apt update && apt-get install wget -y)) \ + && mkdir -p -m 755 /etc/apt/keyrings \ + && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ + && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null + +apt update +apt install -y gh=${VERSION} \ No newline at end of file diff --git a/docker/install-scripts/jq-lite.sh b/docker/install-scripts/jq-lite.sh new file mode 100755 index 0000000..3224c12 --- /dev/null +++ b/docker/install-scripts/jq-lite.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +apt-get install -y jq=${VERSION} diff --git a/docker/install-scripts/opa-lite.sh b/docker/install-scripts/opa-lite.sh new file mode 100755 index 0000000..5eb6c0e --- /dev/null +++ b/docker/install-scripts/opa-lite.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +ARCHITECTURE=$(dpkg --print-architecture) + +wget -nv https://github.com/open-policy-agent/opa/releases/download/${VERSION}/opa_linux_${ARCHITECTURE}_static + +chmod +x opa_linux_${ARCHITECTURE}_static +mv opa_linux_${ARCHITECTURE}_static /usr/local/bin/opa diff --git a/docker/install-scripts/sops-lite.sh b/docker/install-scripts/sops-lite.sh new file mode 100755 index 0000000..edddff2 --- /dev/null +++ b/docker/install-scripts/sops-lite.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +ARCHITECTURE=$(dpkg --print-architecture) +wget -nv https://github.com/getsops/sops/releases/download/${VERSION}/sops-${VERSION}.linux.${ARCHITECTURE} + +chmod +x sops-${VERSION}.linux.${ARCHITECTURE} +mv sops-${VERSION}.linux.${ARCHITECTURE} /usr/local/bin/sops diff --git a/docker/install-scripts/tflint-lite.sh b/docker/install-scripts/tflint-lite.sh new file mode 100755 index 0000000..a5be627 --- /dev/null +++ b/docker/install-scripts/tflint-lite.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +ARCHITECTURE=$(dpkg --print-architecture) +wget -nv https://github.com/terraform-linters/tflint/releases/download/${VERSION}/tflint_linux_${ARCHITECTURE}.zip + +unzip tflint_linux_${ARCHITECTURE}.zip +rm tflint_linux_${ARCHITECTURE}.zip +mv tflint /usr/local/bin/tflint +mkdir -p /work/.tflint.d \ No newline at end of file diff --git a/docker/install-scripts/tflint-ruleset-lite.sh b/docker/install-scripts/tflint-ruleset-lite.sh new file mode 100755 index 0000000..9aba87e --- /dev/null +++ b/docker/install-scripts/tflint-ruleset-lite.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --ruleset=*) + RULESET="${1#*=}" + ;; + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +ARCHITECTURE=$(dpkg --print-architecture) +wget -nv https://github.com/terraform-linters/tflint-ruleset-${RULESET}/releases/download/${VERSION}/tflint-ruleset-${RULESET}_linux_${ARCHITECTURE}.zip + +unzip tflint-ruleset-${RULESET}_linux_${ARCHITECTURE}.zip +rm tflint-ruleset-${RULESET}_linux_${ARCHITECTURE}.zip +mkdir -p /work/.tflint.d/plugins/ +mv tflint-ruleset-${RULESET} /work/.tflint.d/plugins/tflint-ruleset-${RULESET} diff --git a/docker/install-scripts/tfsec-lite.sh b/docker/install-scripts/tfsec-lite.sh new file mode 100755 index 0000000..1f851dd --- /dev/null +++ b/docker/install-scripts/tfsec-lite.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +while [ $# -gt 0 ]; do + case "$1" in + --version=*) + VERSION="${1#*=}" + ;; + *) + echo "Error: Invalid argument." + exit 1 + esac + shift +done + +ARCHITECTURE=$(dpkg --print-architecture) +wget -nv https://github.com/aquasecurity/tfsec/releases/download/${VERSION}/tfsec-linux-${ARCHITECTURE} + +chmod +x tfsec-linux-${ARCHITECTURE} +mv tfsec-linux-${ARCHITECTURE} /usr/local/bin/tfsec