This action is deprecated in favour of using Trivy and CycloneDX. See https://doc.nais.io/security/salsa/ for more information.
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.
Statement type: in-toto v0.1
Signing envelope: DSSE
Predicate type: Provenance v0.2
This actions creates attestations with materials based on both runtime and transitive dependencies, using a supported build tool.
golang
php (with
known limitation: there is no digest over
dependencies)
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.
The nais salsa
action use Cosign with support
of KMS to sign and verify the attestation. Cosign
supports all the standard key management systems.
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
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.
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 }}
with.credentials_json
is the GitHub service
account json key.
with.key
is the key URI format for Google KMS.
Format: gcpkms://projects/$PROJECT/locations/$LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY/versions/$KEY_VERSION
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.
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.
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"
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.
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.
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.
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
.
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 }}
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.
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 |
provenance_file_path
SLSA provenanceraw_file_path
Signed Cosign dsse attestation
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
.
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