Coder Social home page Coder Social logo

salsa's Introduction

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

salsa's People

Contributors

anderssonw avatar christeredvartsen avatar dependabot[bot] avatar jksolbakken avatar sindrerh2 avatar thokra-nav avatar tommytroen avatar ybelmekk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

anderssonw

salsa's Issues

Handle n maven input

Describe the bug
As for today we make it simple, we only add an single maven option, and it is for settings.xml, the logic for cmds need to be fixed in order to handle more input.

Remove docker_pwd only use github_token

Describe the bug

If your using maven or gradle private deps, you need to have both, thats not right

 docker_pwd: ${{ secrets.GITHUB_TOKEN }}
 github_token: ${{ secrets.GITHUB_TOKEN }}

docker_pwd to github_token, release new version with simpler setup.

cosign and the ability to refer to images by tag will be removed in a future release

Cosign 1.13.1 sends out this warning:

WARNING: Image reference ghcr.io/nais/salsa:v0.3.20221019220030 uses a tag, not a digest, to identify the image to sign.

This can lead you to sign a different image than the intended one. Please use a
digest (example.com/ubuntu@sha256:abc123...) rather than tag
(example.com/ubuntu:latest) for the input to cosign. The ability to refer to
images by tag will be removed in a future release.
Pushing signature to: ghcr.io/nais/salsa
WARNING: Image reference ghcr.io/nais/salsa:v0.3 uses a tag, not a digest, to identify the image to sign.

This can lead you to sign a different image than the intended one. Please use a
digest (example.com/ubuntu@sha256:abc123...) rather than tag
(example.com/ubuntu:latest) for the input to cosign. The ability to refer to
images by tag will be removed in a future release.
Pushing signature to: ghcr.io/nais/salsa

add: ability to provide input settings for maven

issue is described here: https://nav-it.slack.com/team/UMZM47VFZ

in short:

if we could send with our own maven parameters then it would have been useful for private repos.
for my workflow now, I only want to build this for an app, so normally I run --projects :pip-api --also-make and we have a separate settings.xml file, so should have included --settings ./. mvn/settings.xml
so if you had found a way that I could only send extra arguments into SLSA, it would have made things easier and faster for us with monorepos.

Split verify into its own subcommand of verify

Is your feature request related to a problem? Please describe.
attest-verify is janky, as it is not really a part of the attest command, but rather a flag/subcommand

Describe the solution you'd like
verify should be its own subcommand under attest, with its own flags and defaults. a few of the flags will be duplicated, so should probably move these to some utility

Release pipeline

Is your feature request related to a problem? Please describe.
The release changelog has only a single commit.
See goreleaser

Describe the solution you'd like
Draft should be updated with new commit, not creating a new one.

BuildStartedOn

For local build the starting time of the generation of provenace is ok. But for a remote build env. we need to use the actual commit time when the build started, it can be found in the build context (github etc..)

update: release pipline

Is your feature request related to a problem? Please describe.

How should we handle releases?

Support build.gradle in jvm

Is your feature request related to a problem? Please describe.
Support build.gradle. Today we only support build.gradle.kts

fix: readme for action

Add new readme for action, move current contribution or some place where development is specified.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.