Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

nais/salsa

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

Deprecated - this repo is archived

This action is deprecated in favour of using Trivy and CycloneDX. See https://doc.nais.io/security/salsa/ for more information.


nais SLSA Provenance Action

Salsa build & release Salsa integration Salsa keyless integration Check pinned workflows
GitHub tag (latest by date) GitHub last commit GitHub license Go Report Card GitHub go.mod Go version (branch)

About

This is a GitHub Action for generating signed provenance about a build and its related artifacts. Provenance is an attestation (a "software bill of materials") about a software artifact or collection of artifacts, documenting how an artifact was produced - all in a common format.

Supply chain Levels for Software Artifacts, or SLSA (pronounced: salsa), is a security framework ( standards, guidelines etc.) to prevent tampering, improve integrity, and secure packages and infrastructure in your projects, businesses or enterprises.

The action implements the level 3 requirements of the SLSA Framework (as long as it is run in an ephemeral environment) producing a signed software attestation of your build and dependencies. The attestation is signed and uploaded to your container registry using Cosign and can be verified by the salsa cli (also provided in this repo) or using the cosign verify-attestation command.

Signing attestation with KMS (Key Management Service), verification requires access to the corresponding public keys.

  • The keys for the navikt and nais organizations can be found at our website (for now), if you use this action at other organizations you need to host your keys somewhere appropriate.

Signing attestation with Cosign Keyless, verification do not require access to the corresponding public keys.

cosign verify-attestation --type=slsaprovenance image:tag

Disclaimer: This is not an official GitHub Action maintained by the SLSA team. It is created by the nais.io team for the purpose of securing supply chains in NAV. However, we encourage other organizations/users to use it and even contribute as it is built with open source in mind.

Built with

golang
Cosign
GitHub Actions

Formats/Standards implemented

Statement type: in-toto v0.1
Signing envelope: DSSE
Predicate type: Provenance v0.2

Materials

This actions creates attestations with materials based on both runtime and transitive dependencies, using a supported build tool.

Supported build tools

JVM

gradle
maven

JS

yarn
npm

Other

golang
php (with known limitation: there is no digest over dependencies)

Getting started

How to use

Requirements

The nais salsa action supports KMS providers or Cosign Keyless for signing and/or upload of the attestation to the registry.

An authentication step in the Workflow must be set up explicit before the nais salsa action. Configure a KMS provider or a Workload Identity Federation before the nais salsa is run.

In the workflow examples we use google-github-actions/auth to authenticate with Google KMS or with a Workload identity.

actions/checkout is required prior to using this action as nais salsa must have access to your build manifest to digest over dependencies.

KMS - Key Management Service

The nais salsa action use Cosign with support of KMS to sign and verify the attestation. Cosign supports all the standard key management systems.

Google KMS Setup

KMS with Cosign requires some setup at the provider.

KMS is enabled in your Google project:

  • create a keyring
  • create key: Elliptic Curve P-256 key SHA256 Digest

Service account in project has roles:

  • Cloud KMS CryptoKey signer/verifier
  • Cloud KMS viewer Role
Other KMS providers

It is possible to use other KMS providers (this will probably require another GitHub action to be configured). Read the Cosign KMS documentation for more information about providers, their specific setup and key URI formats.

workflow with service account secrets
name: ci

on:
  push:
    branches:
      - 'main'

env:
  IMAGE: ttl.sh/nais/salsa-test:1h
  KEY: gcpkms://projects/$PROJECT/locations/$LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY/versions/$KEY_VERSION

jobs:
  provenance:
    runs-on: ubuntu-20.04
    steps:

      - name: Checkout Code
        uses: actions/checkout@v3

      - name: Build and push
        uses: docker/build-push-action@v3
        with:
          push: true
          tags: ${{ env.IMAGE }}

      - name: Authenticate to Google Cloud
        uses: google-github-actions/[email protected]
        with:
          credentials_json: ${{ secrets.GCP_CREDENTIALS }}

      - name: Provenance, upload and sign attestation
        uses: nais/[email protected]
        with:
          key: ${{ env.KEY }}
Google Authentication

with.credentials_json is the GitHub service account json key.

Nais Salsa

with.key is the key URI format for Google KMS. Format: gcpkms://projects/$PROJECT/locations/$LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY/versions/$KEY_VERSION

Keyless Signatures

nais salsa supports Cosign Keyless Signatures signing and verification of attestations.

Note: Cosign Keyless this is an experimental feature and is not recommended for production use.

Workload identity

Pre-requisites before using Keyless Signatures:

Create a Workload Identity Federation and follow steps to configure workload identity federation. This can be done with commands using the Google gcloud cli or in the browser Google Console.

Workflow with workload identity and keyless

name: slsa keyless signatures
on:
  push:
    branches:
      - 'main'
env:
  IMAGE: ttl.sh/nais/salsa-keyless-test:1h
jobs:
  keyless:
    permissions:
      contents: 'read'
      id-token: 'write'
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout Code
        uses: actions/checkout@v3

      - name: Build and push
        uses: docker/build-push-action@v3
        with:
          context: integration-test
          push: true
          tags: ${{ env.IMAGE }}

      - name: Authenticate to Google Cloud
        uses: google-github-actions/[email protected]
        id: google
        with:
          workload_identity_provider: ${{ secrets.SLSA_WORKLOAD_IDENTITY_PROVIDER }}
          service_account: [email protected]
          token_format: "id_token"
          id_token_audience: sigstore
          id_token_include_email: true

      - name: Generate provenance, sign and upload image
        uses: nais/[email protected]
        with:
          identity_token: ${{ steps.google.outputs.id_token }}
        env:
          COSIGN_EXPERIMENTAL: "true"
Google Authentication

The described with fields is required to enable Federation with workload identity and Cosign keyless signatures.

with.workload_identity_provider is the workload identity provider. The value is retrieved from the Federation instance created. Format: projects/$PROJECT/locations/$LOCATION/workloadIdentityPools/$POOL/providers/$PROVIDER

with.service_account is the service account to use for the workload identity. The value is retrieved from the service account created. Format: [email protected]

with.token_format is the token format to use. Cosign expects "id_token".

with.id_token_audience is the audience to use for the id_token. Cosign expects sigstore. sigstore audience must be added to the workload identity provider as an allowed audience.

with.id_token_include_email Cosign expects the email to be included in the token.

Nais Salsa

The described with fields is required for nais salsa.

with.identity_token is the output identity_token from the Google Auth Action. Format: steps.steps-id.outputs.id_token

with.env.COSIGN_EXPERIMENTAL is required to be set to true for Cosign to enable keyless signatures.

Signature repository

Cosign defaults to store signatures in the same repo as the image it is signing. It is possible to specify a different repo for signatures, you can set the COSIGN_REPOSITORY environment variable to store the cosign signatures and attestations, see more specification in the cosign docs

- name: Generate provenance, sign and upload image
  uses: nais/[email protected]
  with:
    key: ${{ secrets.SALSA_KMS_KEY }}
  env:
    COSIGN_REPOSITORY: "registry.io/signatures"

Actor must be sure that with.github_token has access to the signature repository.

Customizing

Inputs

Access private repositories

Salsa builds your application to retrieve running dependencies, when the build configuration contains private packages, the build needs a token with the proper access. Maven and gradle build tool can authenticate with a PAT. Use the with.github_token field to authenticate with the registry.

with.token_key_pattern can be used to specify a key pattern, other than default GITHUB_TOKEN.

Maven Options

with.mvn_opts - (optional) additional maven options in a comma-delimited string.

When specified, the options are separated by , and appended to the maven command line. Options with arguments like --settings must be seperated with a = sign and not space, for example: --settings=.mvn/settings.xml. Double --flag options can not be mixed with single -flag.

Useful when your project depends on a custom maven settings file or use dependencies from a private repository. If project depends on dependencies from a private repository, actor need to set GitHub private token with proper access right.

 - name: Generate provenance, sign and upload image
   uses: nais/[email protected]
   with:
     mvn_opts: "-s .mvn/settings.xml"
     github_token: ${{ secrets.PAT }}

GitHub context

with.github_context - (required) default to true to include the github context in the provenance.

The github context contains information about the workflow run and the event that triggered the run. By default, this action uses the GitHub context.

Runner Context

with.runner_context - (required) default to true to include the runner context in the provenance.

The runner context contains information about the runner that is executing the current job. By default, this action uses the Runner context.

The Following inputs can be used as step.with keys

Name Type Default Description Required
key String "" Private key (cosign.key) or kms provider, used for signing the attestation (Not required for keyless) true
registry String "" Identity token used for Cosign keyless authentication true
image_digest String "" The image digest to create a attestation for true
github_token String $GITHUB_TOKEN Detected automatically, use this to authenticate and read private packages, the token must have read:packages scope false
identity_token String "" Identity token used only for Cosign keyless authentication False
registry_access_token String "" Access token, when using workload identity tokens against registries similar to GAR False
token_key_pattern String GITHUB_TOKEN If a token is provided but the the key pattern is different from the default key pattern "GITHUB_TOKEN" False
image String $IMAGE The image tag to create a attestation for False
docker_user String $GITHUB_ACTOR User to login to container registry False
repo_name String $GITHUB_REPOSITORY The name of the repo/project False
repo_sub_dir String "" Specify a subdirectory if build file not found in working root directory False
build_started_on String "event.(type if any).head.commit" Specify a workflow build start time. Default is set to github_context e.g event.head_commit or event.workflow_run.head_commit depending on workflow False
mvn_opts String "" A comma-delimited string with additional maven cli options for the dependence build False
repo_dir String $GITHUB_WORKSPACE Internal value (do not set): Root of directory to look for build files False
github_context String ${{ toJSON(github) }} Internal value (do not set): the github context object in json False
runner_context String ${{ toJSON(runner) }} Internal value (do not set): the runner context object in json False
verify_attestation String "true" A boolean for enabling or disabling the verify stage of the attestation. False

Outputs

Release

Checksums

We generate a checksums.txt file and upload it with the release, so users can validate if the downloaded files are correct. All files are by default digested with algorithm sha256.

Verify signature

The release artifacts are signed with Cosign and can be verified by using the public signing key.

cosign verify-blob --key cosign.pub --signature salsa.tar.gz.sig salsa.tar.gz

Verified OK