Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding CI/CD security features and version CLI command #39

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .github/actions/publish-release/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: Publish release

description: Publish release, container image, SBOMS, signs artifacts.

inputs:
go-version:
required: true
description: go version to install on the runner
github_token:
required : true
description: github token used for the release
registry_username:
required: true
description: Container registry username
registry_password:
required: true
description: Container registry password
registry:
required: true
description: registry used to publish container images


outputs:
hashes:
value: ${{ steps.binary.outputs.hashes }}
description: hash of the cheksum file in base64
name:
value: ${{ steps.image.outputs.name }}
description: name of the published container image
digest:
value: ${{ steps.image.outputs.digest }}
description: published image digest

runs:
using: composite
steps:
# Install go with specific version
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ inputs.go-version }} # same version than the one in the go.mod or in the .go-version
# Register to ghcr.io container Registry
- name: 'Login to GitHub Container Registry'
uses: docker/login-action@v1
with:
registry: ${{ inputs.registry}}
username: ${{ inputs.registry_username }}
password: ${{ inputs.registry_password }}
# Install ko to publish container images
- name: Set up Ko
uses: ko-build/[email protected]
# Install cosign to sign artfacts with goreleaser
- name: Install Cosign
uses: sigstore/[email protected]
# Get LDFLAGS with a makefile command
- shell: bash
name: Get LDFLAGS
id: get_ldlflags # need to define id to pass the variable to other steps
run : |
echo "ldflags= $(make get-ldflags)" >> "$GITHUB_OUTPUT"
# Install other dependencies like scanners and go librairies
- shell: bash
name : Install dependencies
run : |
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.49.1
# Run command goreleaser release based on .goreleaser.yml
# LDFLAGS are passed thanks to the steps.job_id.outputs.variable_name variable
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
id: goreleaser
with:
distribution: goreleaser
version: latest
args: release
env:
GITHUB_TOKEN: ${{ inputs.github_token }}
LDFLAGS: ${{steps.get_ldlflags.outputs.ldflags}}
# Get artifacts from goreleaser's step outputs to generate cheksums file abse64 hashes
# Provenance generator action needs to have a base64 hash for generating blobs provenance
# The hash is passed as an output of goreleaser job
- shell: bash
name: Generate binary hashes
id: binary
env:
ARTIFACTS: "${{ steps.goreleaser.outputs.artifacts }}"
run: |
set -euo pipefail
checksum_file=$(echo "$ARTIFACTS" | jq -r '.[] | select (.type=="Checksum") | .path')
echo "hashes=$(cat $checksum_file | base64 -w0)" >> "$GITHUB_OUTPUT"
# Get artifacts from the goreleaser's step outputs to retrieve Docker Manifest containing the image and its digest
# Image Provenance generator action needs to have the image name and a digest for generating provenance and publish it to the container registry
- shell: bash
name: Image digest
id: image
env:
ARTIFACTS: "${{ steps.goreleaser.outputs.artifacts }}"
run: |
set -euo pipefail
image_and_digest=$(echo "$ARTIFACTS" | jq -r '.[] | select (.type=="Docker Manifest") | .path')
image=$(echo "${image_and_digest}" | cut -d'@' -f1 | cut -d':' -f1)
digest=$(echo "${image_and_digest}" | cut -d'@' -f2)
echo "name=$image" >> "$GITHUB_OUTPUT"
echo "digest=$digest" >> "$GITHUB_OUTPUT"
# Sign image with cosign sign command
- shell: bash
name: Generate Image Signature
env:
#COSIGN_REPOSITORY: ghcr.io/${{github.owner}}/signatures # need to use this variable for having a dfiferent signature repository
IMAGE: ${{ steps.image.outputs.name }}@${{ steps.image.outputs.digest }}
run : |
cosign sign --yes \
${{ env.IMAGE }}
42 changes: 42 additions & 0 deletions .github/actions/verify-attestations/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Verify SLSA attestations

description: Use slsa-verifier to verify provenance attestations

inputs:
go-version:
required: true
description: go version to install on the runner
github_token:
required : true
description: github token used for the release
image:
required: true
description: Image to verify.
tag:
required : false
description : Version of the software.
checksum_file:
required : true
description : Name of the checksum.


runs:
using: composite
steps:
# Install go with specific version
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ inputs.go-version }} # same version than the one in the go.mod or in the .go-version

- shell: bash
name : Install dependencies
run : |
go install github.com/slsa-framework/slsa-verifier/v2/cli/[email protected]
- shell: bash
name: verify image provenance
id: image-provenance
run: |
slsa-verifier verify-image ${{ inputs.image }} \
--source-uri github.com/${{github.repository}} \
--builder-id https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v1.10.0
84 changes: 84 additions & 0 deletions .github/workflows/Goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# .github/workflows/release.yml
name: goreleaser

on:
pull_request:
push:
# run only against tags
tags:
- "*"

jobs:

goreleaser:
runs-on: ubuntu-latest
env:
WORKSPACE: ${{github.workspace}}
# Define job outputs from steps outputs
# It is
outputs:
hashes: ${{ steps.publish-artifacts.outputs.hashes }}
image: ${{ steps.publish-artifacts.outputs.name }}
digest: ${{ steps.publish-artifacts.outputs.digest }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Publish Artifacts
id : publish-artifacts
uses: ./.github/actions/publish-release
with:
go-version: 1.21.6
github_token : ${{ secrets.GITHUB_TOKEN }}
registry: ghcr.io
registry_username: ${{ github.actor }}
registry_password: ${{ secrets.GITHUB_TOKEN }}

# Job generating provenance for blobs artifacts requiring checksum hash in base64 format
# upload-assets is set to true to add in-toto attestation to the release
binary-provenance:
needs: [goreleaser]
permissions:
actions: read # To read the workflow path.
id-token: write # To sign the provenance.
contents: write # To add assets to a release.
uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
with:
base64-subjects: "${{ needs.goreleaser.outputs.hashes }}"
upload-assets: true
# Job generating provenance for container images requiring an image and an image digest
image-provenance:
needs: [goreleaser]
permissions:
actions: read
id-token: write
packages: write
uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
with:
image: ${{ needs.goreleaser.outputs.image }}
digest: ${{ needs.goreleaser.outputs.digest }}
registry-username: ${{ github.actor }}
secrets:
registry-password: ${{ secrets.GITHUB_TOKEN }}
verify-provenance:
needs: [goreleaser, binary-provenance,image-provenance]
runs-on: ubuntu-latest
env:
WORKSPACE: ${{github.workspace}}
permissions:
actions: read
id-token: write
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Verify provenance attestations
id : slsa-verifier
uses: ./.github/actions/verify-attestations
with:
go-version: 1.21.6
github_token : ${{ secrets.GITHUB_TOKEN }}
image: ${{needs.goreleaser.outputs.image}}@${{needs.goreleaser.outputs.digest}}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ build/
generated/
deployed.json
.socket
k8s-kms-plugin

# dev
pkg/crypto11
Expand Down
21 changes: 21 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# .gitlab-ci.yml
variables:
RUNNER_GENERATE_ARTIFACTS_METADATA: "true"

stages:
- release
# Maybe syft is not installed, so it'll need to add another job or action in the script section to install syft on the runner
# https://goreleaser.com/ci/gitlab/#basic-releasing
release:
stage: release
image:
name: goreleaser/goreleaser
entrypoint: [""]
only:
- tags
variables:

GIT_DEPTH: 0
script:
# GITLAB_TOKEN is needed to create GitLab releases.
- make release
Loading