diff --git a/.github/workflows/post-build-attest.yml b/.github/workflows/post-build-attest.yml index ffe268a3..54f829d4 100644 --- a/.github/workflows/post-build-attest.yml +++ b/.github/workflows/post-build-attest.yml @@ -27,12 +27,13 @@ env: SERVICE_ACCOUNT: ${{ inputs.service_account }} IMAGE_URL: ${{ inputs.image_url }} ATTESTOR_PROJECT_ID: kubernetes-dev-94b9 + REGISTRY: ghcr.io jobs: setup-env: runs-on: ubuntu-latest outputs: - workload_identity_provider: ${{ steps.set-output.outputs.WORKLOAD_IDENTITY_PROVIDER }} + WORKLOAD_IDENTITY_PROVIDER: ${{ steps.set-output.outputs.WORKLOAD_IDENTITY_PROVIDER }} steps: - name: Set vars id: set-output @@ -62,6 +63,13 @@ jobs: workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ env.SERVICE_ACCOUNT }} + - name: Log into registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Get Image Digest URL from Image Tag URL id: image-digest-url run: | @@ -121,6 +129,13 @@ jobs: workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ env.SERVICE_ACCOUNT }} + - name: Log into registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Get Image Digest URL from Image Tag URL id: image-digest-url run: | diff --git a/.github/workflows/run-security-scans.yml b/.github/workflows/run-security-scans.yml index d2c61c42..0c78a354 100644 --- a/.github/workflows/run-security-scans.yml +++ b/.github/workflows/run-security-scans.yml @@ -6,7 +6,7 @@ on: # The image reference generated by a build job. image_url: description: "An image_url of the form registry/repository:tag." - required: true + required: false type: string auth_project_number: description: "The GCP Project Number used for authentication. A 12-digit number used as a unique identifier for the project. Used to find workload identity pool." @@ -37,12 +37,16 @@ env: SERVICE_ACCOUNT: ${{ inputs.service_account }} IMAGE_URL: ${{ inputs.image_url }} ATTESTOR_PROJECT_ID: kubernetes-dev-94b9 + REGISTRY: ghcr.io + BRANCH: ${{ github.ref_name }} + HEAD_REF: ${{ github.head_ref }} + EVENT_NAME: ${{ github.event_name }} jobs: setup-env: runs-on: ubuntu-latest outputs: - workload_identity_provider: ${{ steps.set-output.outputs.WORKLOAD_IDENTITY_PROVIDER }} + WORKLOAD_IDENTITY_PROVIDER: ${{ steps.set-output.outputs.WORKLOAD_IDENTITY_PROVIDER }} steps: - name: Set vars id: set-output @@ -79,13 +83,20 @@ jobs: trivy: name: Trivy - if: inputs.trivy == true && github.event.pull_request.draft == false + if: inputs.trivy == true && inputs.image_url != '' && github.event.pull_request.draft == false needs: [setup-env] runs-on: ubuntu-latest # Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest defaults: run: shell: bash + permissions: + contents: read + packages: write + # required for authentication to GCP + id-token: write + actions: read + security-events: write env: WORKLOAD_IDENTITY_PROVIDER: ${{ needs.setup-env.outputs.WORKLOAD_IDENTITY_PROVIDER }} steps: @@ -93,8 +104,18 @@ jobs: - name: Checkout code uses: actions/checkout@v3 + - name: Log into registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker pull image + run: docker pull $IMAGE_URL + - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@9ab158e8597f3b310480b9a69402b419bc03dbd5 with: image-ref: ${{ env.IMAGE_URL }} format: sarif @@ -172,15 +193,24 @@ jobs: - name: Check for Critical and High Severity id: severity_check run: | - severity_check=$(curl -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/code-scanning/alerts | jq -e '[.[] | select(.state == "open" and (.rule.security_severity_level == "high" or .rule.security_severity_level == "critical"))] | any') - if [[ $severity_check == 'true' ]] + severity_check=$(curl -s -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/code-scanning/alerts?ref=${{github.ref}} | jq '[.[] | select(.state == "open" and (.rule.security_severity_level == "high" or .rule.security_severity_level == "critical"))] | any') + if [[ $severity_check == 'true' && $EVENT_NAME == 'pull_request' ]] then - echo "Error: High or critical vulnerabilities detected. Go to the Code Scanning section of the Github Security-tab to review these vulnerabilities." - exit 1 + pr_number=$( echo $BRANCH | sed 's/\/.*//') + echo "Error: High or critical vulnerabilities detected on pull-request. Go to the Code Scanning section of the Github Security-tab and search for 'is:open pr:$pr_number' to review these vulnerabilities."; + exit 1; + elif [[ $severity_check == 'true' && ($BRANCH == 'main' || $BRANCH == 'master')]] + then + echo "Error: High or critical vulnerabilities detected on main/master branch. Go to the Code Scanning section of the Github Security-tab to review these vulnerabilities."; + exit 1; + else + echo "Success! No high or critical code scanning alerts." fi + attest: name: Attest Github Security Code Scanning + if: inputs.image_url != '' needs: [tfsec, trivy, check-github-security, setup-env] runs-on: ubuntu-latest # Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest @@ -200,6 +230,13 @@ jobs: workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ env.SERVICE_ACCOUNT }} + - name: Log into registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Get Image Digest URL from Image Tag URL id: image-digest-url run: | diff --git a/.github/workflows/run-terraform.yml b/.github/workflows/run-terraform.yml index 77d0e3be..92431047 100644 --- a/.github/workflows/run-terraform.yml +++ b/.github/workflows/run-terraform.yml @@ -108,6 +108,7 @@ env: TF_OPTION_1: ${{ inputs.terraform_option_1 }} TF_OPTION_2: ${{ inputs.terraform_option_2 }} TF_OPTION_3: ${{ inputs.terraform_option_3 }} + REGISTRY: ghcr.io jobs: setup-env: @@ -149,7 +150,7 @@ jobs: # Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token - name: Setup Terraform - uses: hashicorp/setup-terraform@v2 + uses: hashicorp/setup-terraform@v2.0.3 - name: Authenticate with Google Cloud uses: google-github-actions/auth@v1 @@ -219,7 +220,7 @@ jobs: - name: Setup Terraform # Change to v2.1.0 when released. We require the below fix: # https://github.com/hashicorp/setup-terraform/pull/125 - uses: hashicorp/setup-terraform@78ea3ac2fbe8fe4dab277d1cbd1e6435a91a49cc + uses: hashicorp/setup-terraform@v2.0.3 - name: Authenticate with Google Cloud uses: google-github-actions/auth@v1 @@ -453,7 +454,7 @@ jobs: # Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token - name: Setup Terraform - uses: hashicorp/setup-terraform@v2 + uses: hashicorp/setup-terraform@v2.0.3 with: terraform_wrapper: false @@ -527,6 +528,13 @@ jobs: workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ env.SERVICE_ACCOUNT }} + - name: Log into registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Get Image Digest URL from Image Tag URL id: image-digest-url run: | diff --git a/README.md b/README.md index 4bf3665d..b5673ca0 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,12 @@ This workflow plans and applies Terraform config to deploy to an environment. ```yaml jobs: + build: + # ... + + post-build-attest: + # call to post-build-attest.yml with build image + dev: name: Deploy to dev permissions: @@ -147,7 +153,8 @@ Note the format of the image_url parameter. ```yaml jobs: - build: ... + build: + # ... post-build-attest: needs: [build] @@ -179,7 +186,8 @@ jobs: ## run-security-scans This workflow runs security scans and performs binary attestation if no _high_ or _critical_ vulnerabilities are found. -Note, in order to not limit/interfere with the developement process, the scans do not run on draft pull requests. +Note, in order to not limit/interfere with the developement process, the scans do not run on draft pull requests. +Additionally, if image_url is not supplied neither Trivy nor Binary Attestation will be performed (i.e. only TFSec scan will run). ### Features @@ -213,6 +221,18 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + # Sets tag 'latest' for images built on main/master branch and tag 'prebuild-temp' on all other image builds + - name: Set tag + id: set-tag + env: + BRANCH: ${{ github.ref_name }} + run: | + if [[ "$BRANCH" == "main" || "$BRANCH" == "master" ]]; then + echo "image_tag=latest" >> $GITHUB_OUTPUT + else + echo "image_tag=prebuild-temp" >> $GITHUB_OUTPUT + fi + # Login against a Docker registry except on draft-PR # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} @@ -231,7 +251,9 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # Note: checkout https://github.com/docker/metadata-action#tags-input for tag format options - tags: type=sha,format=long + tags: | + type=sha,format=long + type=raw,value=${{ steps.set-tag.outputs.image_tag }} # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action @@ -275,7 +297,7 @@ jobs: with: auth_project_number: "123456789123" service_account: x - image_url: ${{ needs.build.outputs.image_tag_url}} # format is /: + image_url: ${{ needs.build.outputs.image_tag_url}} # optional, must have format /: trivy: tfsec: @@ -291,6 +313,6 @@ jobs: | auth_project_number | string | X | The GCP Project Number used as the active project. A 12-digit number used as a unique identifier for the project. Used to find workload identity pool. | | workload_identity_provider_override | string | | The ID of the provider to use for authentication. Only used for overriding the default workload identity provider based on project number. It should be in the format of `projects/{{project_number}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers/{{workload_identity_pool_provider_id}}`. | | service_account | string | X | The GCP service account connected to the identity pool that will be used by Terraform. | -| image_url | string | X | The Docker image url must be of the form `registry/repository:tag` for the run-security-scans workflow | +| image_url | string | | The Docker image url must be of the form `registry/repository:tag` for run-security-scans. It is not required; however, in order to run Trivy and aquire attestations an image_url must be supplied. workflow | | trivy | boolean | | An optional boolean that determins whether trivy-scan will be run. Defaults to 'true'. | | tfsec | boolean | | An optional boolean that determins whether tfsec-scan will be run. Defaults to 'true'. |