Scribe GitHub Action for `valint bom`
Scribe offers the use of GitHub Actions to enable the embedding of evidence collection and integrity validation into your pipeline as a way to help secure your software supply chain.
valint bom
is used to collect evidence and generate an SBOM.
Further documentation GitHub integration.
Bom Action
The command allows users to generate sbom and third party evidence.
- CycloneDX 1.4 SBOM support.
- Generates detailed SBOMs for images, directories, files and git repositories targets.
- Store and manage evidence on Scribe service.
- Attach evidence to any OCI registry.
- Generate evidence directly from your private OCI registry.
- Extensive SBOM component relation graph including, file to package, file and package to layer, commit history and file to commit relations.
- SBOM including package CPEs and Licensing information.
- Customizable SBOM with environments, labels.
- Customizable SBOM with your required component groups.
- Attach any external reports to your SBOM.
- Signing - Generate In-Toto Attestation.
- Support Sigstore keyless verifying as well as GitHub workload identity.
- Attach GitHub workflows environment context (git url , commit, workflow, job, run id ..).
Containerized actions limit's the ability to generate evidence on a target located outside the working directory (directory or git targets).
To overcome the limitation install tool directly - installer.
Input arguments
target:
description: Target object name format=[<image:tag>, <dir path>, <git url>]
required: true
attach-regex:
description: Attach files content by regex
attest-config:
description: Attestation config path
attest-default:
description: Attestation default config, options=[sigstore sigstore-github x509 x509-env kms pubkey]
author-email:
description: Set author email
author-name:
description: Set author name
author-phone:
description: Set author phone
ca:
description: x509 CA Chain path
cert:
description: x509 Cert path
components:
description: Select sbom components groups, options=[metadata layers packages syft files dep commits]
crl:
description: x509 CRL path
crl-full-chain:
description: Enable Full chain CRL verfication
depth:
description: Git clone depth
disable-crl:
description: Disable certificate revocation verificatoin
filter-regex:
description: Filter out files by regex
filter-scope:
description: Filter packages by scope
force:
description: Force overwrite cache
format:
description: Evidence format, options=[cyclonedx-json cyclonedx-xml attest-cyclonedx-json statement-cyclonedx-json attest-slsa statement-slsa statement-generic attest-generic]
git-auth:
description: 'Git repository authentication info, [format: ''username:password'']'
git-branch:
description: Git branch in the repository
git-commit:
description: Git commit hash in the repository
git-tag:
description: Git tag in the repository
key:
description: x509 Private key path
kms:
description: Provide KMS key reference
oci:
description: Enable OCI store
oci-repo:
description: Select OCI custom attestation repo
package-exclude-type:
description: Exclude package type, options=[ruby python javascript java dpkg apk rpm go dotnet r rust binary sbom nix conan alpm cocoapods swift dart elixir php erlang github portage haskell kernel wordpress lua]
package-group:
description: Select package group, options=[index install all]
package-type:
description: Select package type, options=[ruby python javascript java dpkg apk rpm go dotnet r rust binary sbom nix conan alpm cocoapods swift dart elixir php erlang github portage haskell kernel wordpress lua]
pass:
description: Private key password
payload:
description: path of the decoded payload
platform:
description: Select target platform, examples=windows/armv6, arm64 ..)
provenance:
description: Include SLSA Provenance evidence
pubkey:
description: Public key path
supplier-email:
description: Set supplier email
supplier-name:
description: Set supplier name
supplier-phone:
description: Set supplier phone
supplier-url:
description: Set supplier url
cache-enable:
description: Enable local cache
config:
description: Configuration file path
deliverable:
description: Mark as deliverable, options=[true, false]
env:
description: Environment keys to include in evidence
gate:
description: Policy Gate name
label:
description: Add Custom labels
level:
description: Log depth level, options=[panic fatal error warning info debug trace]
log-context:
description: Attach context to all logs
log-file:
description: Output log to file
output-directory:
description: Output directory path
default: ./scribe/valint
output-file:
description: Output file name
pipeline-name:
description: Pipeline name
predicate-type:
description: Custom Predicate type (generic evidence format)
product-key:
description: Product Key
product-version:
description: Product Version
scribe-client-id:
description: Scribe Client ID (deprecated)
scribe-client-secret:
description: Scribe Client Token
scribe-disable:
description: Disable scribe client
scribe-enable:
description: Enable scribe client (deprecated)
scribe-url:
description: Scribe API Url
structured:
description: Enable structured logger
timeout:
description: Timeout duration
verbose:
description: Log verbosity level [-v,--verbose=1] = info, [-vv,--verbose=2] = debug
Output arguments
OUTPUT_PATH:
description: 'evidence output file path'
Usage
Containerized action can be used on Linux runners as following
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@v1.5.12
with:
target: 'busybox:latest'
Composite Action can be used on Linux or Windows runners as following
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom-cli@v1.5.12
with:
target: 'hello-world:latest'
Use
master
instead of tag to automatically pull latest version.
1. Obtain a Scribe Hub API Token
-
Sign in to Scribe Hub. If you don't have an account you can sign up for free here.
-
Create a API token in Scribe Hub > Settings > Tokens. Copy it to a safe temporary notepad until you complete the integration.
The token is a secret and will not be accessible from the UI after you finalize the token generation.
2. Add the API token to Github secrets
Set your Scribe Hub API token in Github with a key named SCRIBE_TOKEN as instructed in *GitHub instructions](https://docs.github.com/en/actions/security-guides/encrypted-secrets/ "GitHub Instructions")
3. Instrument your build scripts
Usage
name: scribe_github_workflow
on:
push:
tags:
- "*"
jobs:
scribe-sign-verify:
runs-on: ubuntu-latest
steps:
- uses: scribe-security/action-bom@master
with:
target: [target]
format: [attest, statement]
scribe-client-secret: ${{ secrets.SCRIBE_TOKEN }}
- uses: scribe-security/action-verify@master
with:
target: [target]
input-format: [attest, statement]
scribe-client-secret: ${{ secrets.SCRIBE_TOKEN }}
Configuration
If you prefer using a custom configuration file instead of specifying arguments directly, you have two choices. You can either place the configuration file in the default path, which is .valint.yaml
, or you can specify a custom path using the config
argument.
For a comprehensive overview of the configuration file's structure and available options, please refer to the CLI configuration documentation.
Attestations
Attestations allow you to sign and verify your targets.
Attestations allow you to connect PKI-based identities to your evidence and policy management.
Supported outputs:
- In-toto statements CycloneDX SBOM (unsigned evidence).
- In-toto attestations CycloneDX SBOM (signed evidence).
Select default configuration using --attest.default
flag.
Select a custom configuration by providing cocosign
field in the configuration or custom path using --attest.config
.
Scribe uses the cocosign library we developed to deal with digital signatures signing and verification.
By default GitHub actions use
sigstore-github
flow, GitHub provided workload identities, this will allow using the workflow identity (token-id
permissions is required).
Storing Keys in Secret Vault
GitHub exposes secrets from its vault using environment variables, you may provide these environment as secret to Valint.
Paths names prefixed with
env://[NAME]
are read from the environment matching the name.
GitHub Secret Vault
X509 Signer enables the utilization of environments for supplying key, certificate, and CA files in order to sign and verify attestations. It is commonly employed in conjunction with Secret Vaults, where secrets are exposed through environments.
path names prefixed with
env://[NAME]
are extracted from the environment corresponding to the specified name.
For example the following configuration and Job.
Configuration File, .valint.yaml
attest:
default: "" # Set custom configuration
cocosign:
signer:
x509:
enable: true
private: env://SIGNER_KEY
cert: env://SIGNER_CERT
ca: env://COMPANY_CA
verifier:
x509:
enable: true
cert: env://SIGNER_CERT
ca: env://COMPANY_CA
Job example
name: github_vault_workflow
on:
push:
tags:
- "*"
jobs:
scribe-sign-verify:
runs-on: ubuntu-latest
steps:
uses: scribe-security/action-bom@master
with:
target: busybox:latest
format: attest
env:
SIGNER_KEY: ${{ secrets.SIGNER_KEY }}
SIGNER_CERT: ${{ secrets.SIGNER_CERT }}
COMPANY_CA: ${{ secrets.COMPANY_CA }}
uses: scribe-security/action-verify@master
with:
target: busybox:latest
input-format: attest
env:
SIGNER_CERT: ${{ secrets.SIGNER_CERT }}
COMPANY_CA: ${{ secrets.COMPANY_CA }}
Running action as non root user
By default, the action runs in its own pid namespace as the root user. You can change the user by setting specific USERID
and USERNAME
environment variables.
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
format: json
env:
USERID: 1001
USERNAME: runner
Details
Non root user with HIGH UID/GID
By default, the action runs in its own pid namespace as the root user. If the user uses a high UID or GID, you must specify all the following environment variables. You can change the user by setting specificUSERID
and USERNAME
variables. Additionally, you may group the process by setting specific GROUPID
and GROUP
variables.- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
format: json
env:
USERID: 888000888
USERNAME: my_user
GROUPID: 777000777
GROUP: my_group
Platform-Specific Image Handling
The Valint tool is compatible with both Linux and Windows images. Set the desired platform using the 'platform' field in your configuration:
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
target: hello-world:latest
platform: linux/amd64
format: json
Docker is configured by default to pull images matching the runner's platform. For analyzing images across different platforms, you need to pull the image from the registry and specify the platform.
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
target: registry:hello-world:latest
platform: windows/amd64
format: json
Windows Runner Compatibility
On Windows Github runners, containerized actions are currently not supported. It's recommended to use CLI actions in such cases.
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom-cli@master
with:
target: hello-world:latest
format: json
Basic examples
Attach sbom to product
Create SBOM for remote busybox:latest
image and attach it to a specific product version.
- name: Generate cyclonedx json SBOM attached to a product
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
product-key: my_product
product-version: 3
format: json
Set Git sbom as deliverable artifact
Create SBOM for Deliverable mongo-express/mongo-express
Git repository.
- name: Generate cyclonedx json SBOM for a deliverable Git repo
uses: scribe-security/action-bom@master
with:
target: git:https://github.com/mongo-express/mongo-express.git
product-key: my_product
product-version: 3
deliverable: true
format: json
Public registry image
Create SBOM for remote busybox:latest
image.
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
format: json
Docker built image
Create SBOM for image built by local docker image_name:latest
.
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
type: docker
target: 'image_name:latest'
format: json
force: true
Private registry image
Create SBOM for image hosted by a private registry.
DOCKER_CONFIG
environment will allow the containerized action to access the private registry.
env:
DOCKER_CONFIG: $HOME/.docker
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
target: 'scribesecurity.jfrog.io/scribe-docker-local/example:latest'
force: true
Custom metadata
Custom metadata added to SBOM.
- name: Generate cyclonedx json SBOM - add metadata - labels, envs
id: valint_labels
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
format: json
force: true
env: test_env
label: test_label
env:
test_env: test_env_value
NTIA Custom metadata
Custom NTIA metadata added to SBOM.
- name: Generate cyclonedx json SBOM - add NTIA metadata
id: valint_ntia
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
format: json
force: true
author-name: bob
author-email: bob@company.com
author-phone: 000
supplier-name: alice
supplier-url: company2.com
supplier-email: alice@company2.com
supplier-phone: 001
Save evidence as artifact
Using action OUTPUT_PATH
output argument you can access the generated SBOM and store it as an artifact.
Use action
output-file: <my_custom_path>
input argument to set a custom output path.
- name: Generate cyclonedx json SBOM
id: valint_json
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
output-file: my_sbom.json
format: json
- uses: actions/upload-artifact@v4
with:
name: scribe-sbom
path: ${{ steps.valint_json.outputs.OUTPUT_PATH }}
- uses: actions/upload-artifact@v4
with:
name: scribe-evidence
path: scribe/
Docker archive image
Create SBOM for local docker save ...
output.
- name: Build and save local docker archive
uses: docker/build-push-action@v2
with:
context: .
file: .GitHub/workflows/fixtures/Dockerfile_stub
tags: scribesecurity.jfrog.io/scribe-docker-local/example:latest
outputs: type=docker,dest=stub_local.tar
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
type: docker-archive
target: '/GitHub/workspace/stub_local.tar'
OCI archive image
Create SBOM for the local OCI archive.
- name: Build and save local oci archive
uses: docker/build-push-action@v2
with:
context: .
file: .GitHub/workflows/fixtures/Dockerfile_stub
tags: scribesecurity.jfrog.io/scribe-docker-local/example:latest
outputs: type=oci,dest=stub_oci_local.tar
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
type: oci-archive
target: '/GitHub/workspace/stub_oci_local.tar'
Directory target
Create SBOM for a local directory.
- name: Create dir
run: |
mkdir testdir
echo "test" > testdir/test.txt
- name: valint attest dir
id: valint_attest_dir
uses: scribe-security/action-bom@master
with:
type: dir
target: 'testdir'
Git target
Create SBOM for mongo-express
remote git repository.
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
type: git
target: 'https://github.com/mongo-express/mongo-express.git'
format: json
Create SBOM for my_repo
local git repository.
- uses: actions/checkout@v3
with:
fetch-depth: 0
path: my_repo
- name: Generate cyclonedx json SBOM
uses: scribe-security/action-bom@master
with:
type: git
target: 'my_repo'
format: json
Attest target
Create and sign SBOM targets.
By default the sigstore-github
flow is used, GitHub workload identity and Sigstore (Fulcio, Rekor).
Default attestation config Required
id-token
permission access.
job_example:
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: valint attest
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
format: attest
Attest File evidence
Create and sign file as evidence.
By default the sigstore-github
flow is used, GitHub workload identity and Sigstore (Fulcio, Rekor).
Default attestation config Required
id-token
permission access.
job_example:
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: valint attest
uses: scribe-security/action-evidence@master
with:
target: './file.go'
format: attest
Verify target
Verify targets against a signed attestation.
Default attestation config: sigstore-github
- Sigstore (Fulcio, Rekor).
Valint will look for an SBOM describing the image to verify against.
- name: valint verify
uses: scribe-security/action-verify@master
with:
target: 'busybox:latest'
Verify Policy flow - image target (Signed SBOM)
Full job example of a image signing and verifying flow.
valint-busybox-test:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: valint attest
id: valint_attest
uses: scribe-security/action-bom@master
with:
target: 'busybox:latest'
format: attest
force: true
- name: valint verify
id: valint_verify
uses: scribe-security/action-verify@master
with:
target: 'busybox:latest'
- uses: actions/upload-artifact@v4
with:
name: valint-busybox-test
path: scribe/valint
Verify Policy flow - Directory target (Signed SBOM)
Full job example of a directory signing and verifying flow.
valint-dir-test:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: valint attest workdir
id: valint_attest_dir
uses: scribe-security/action-bom@master
with:
type: dir
target: '/GitHub/workspace/'
format: attest
force: true
- name: valint verify workdir
id: valint_verify_dir
uses: scribe-security/action-verify@master
with:
type: dir
target: '/GitHub/workspace/'
- uses: actions/upload-artifact@v4
with:
name: valint-workdir-evidence
path: |
scribe/valint
Verify Policy flow - Git repository target (Signed SBOM)
Full job example of a git repository signing and verifying flow.
Support for both local (path) and remote git (URL) repositories.
valint-dir-test:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: valint attest local repo
id: valint_attest_dir
uses: scribe-security/action-bom@master
with:
type: git
target: '/GitHub/workspace/my_repo'
format: attest
force: true
- name: valint verify local repo
id: valint_verify_dir
uses: scribe-security/action-verify@master
with:
type: git
target: '/GitHub/workspace/my_repo'
- uses: actions/upload-artifact@v4
with:
name: valint-git-evidence
path: |
scribe/valint
Attest and verify evidence on OCI SBOM
Store any evidence on any OCI registry.
Support storage for all targets and both SBOM formats.
Use input variable
format
to select between supported formats.
Write permission tooci-repo
is required.
valint-dir-test:
runs-on: ubuntu-latest
permissions:
id-token: write
env:
DOCKER_CONFIG: $HOME/.docker
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_TOKEN }}
- uses: scribe-security/action-bom@master
id: valint_attest
with:
target: busybox:latest
force: true
format: attest
oci: true
oci-repo: ${{ env.REGISTRY_URL }}/attestations
Following actions can be used to verify a target over the OCI store.
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_TOKEN }}
- uses: scribe-security/action-verify@master
id: valint_attest
with:
target: busybox:latest
input-format: attest
oci: true
oci-repo: ${{ env.REGISTRY_URL }}/attestations
Read permission to
oci-repo
is required.
Install Valint (tool)
Install Valint as a tool
- name: install valint
uses: scribe-security/action-installer@master
- name: valint run
run: |
valint --version
valint bom busybox:latest
Alternative evidence stores
You can learn more about alternative stores here.
OCI Evidence store
Valint supports both storage and verification flows for attestations
and statement
objects utilizing OCI registry as an evidence store.
Using OCI registry as an evidence store allows you to upload, download and verify evidence across your supply chain in a seamless manner.
Related flags:
oci
Enable OCI store.oci-repo
- Evidence store location.
Before you begin
Evidence can be stored in any accusable registry.
- Write access is required for upload (generate).
- Read access is required for download (verify).
You must first login with the required access privileges to your registry before calling Valint.
For example, using docker login
command or docker/login-action
action.
Usage
name: scribe_github_workflow
on:
push:
tags:
- "*"
jobs:
scribe-sign-verify:
runs-on: ubuntu-latest
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.my_registry }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Generate evidence step
uses: scribe-security/action-bom@master
with:
target: [target]
format: [attest, statement]
oci: true
oci-repo: [oci_repo]
- name: Verify policy step
uses: scribe-security/action-verify@master
with:
target: [target]
input-format: [attest, statement]
oci: true
oci-repo: [oci_repo]
.gitignore
It's recommended to add output directory value to your .gitignore file.
By default add **/scribe
to your .gitignore
.