Skip to content

Commit

Permalink
510 - SBOM attestation stdout (anchore#785)
Browse files Browse the repository at this point in the history
add syft attest command to produce an attestation as application/vnd.in-toto+json to standard out using on disk PKI

Signed-off-by: Christopher Phillips <[email protected]>
  • Loading branch information
spiffcs authored Feb 23, 2022
1 parent ff6eab7 commit ac08883
Show file tree
Hide file tree
Showing 20 changed files with 2,697 additions and 144 deletions.
13 changes: 10 additions & 3 deletions .github/workflows/validations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,16 @@ jobs:
restore-keys: |
${{ runner.os }}-go-${{ env.GO_VERSION }}-
- name: (cache-miss) Bootstrap go dependencies
if: steps.go-cache.outputs.cache-hit != 'true'
run: make bootstrap-go
- name: Restore tool cache
id: tool-cache
uses: actions/[email protected]
with:
path: ${{ github.workspace }}/.tmp
key: ${{ runner.os }}-tool-${{ hashFiles('Makefile') }}

- name: (cache-miss) Bootstrap all project dependencies
if: steps.tool-cache.outputs.cache-hit != 'true' || steps.go-cache.outputs.cache-hit != 'true'
run: make bootstrap

- name: Build key for tar cache
run: make cli-fingerprint
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ bin/
# macOS Finder metadata
.DS_STORE

*.profile
*.profile

# attestation
cosign.key
cosign.pub
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ TEMPDIR = ./.tmp
RESULTSDIR = test/results
COVER_REPORT = $(RESULTSDIR)/unit-coverage-details.txt
COVER_TOTAL = $(RESULTSDIR)/unit-coverage-summary.txt
LINTCMD = $(TEMPDIR)/golangci-lint run --tests=false --timeout=2m --config .golangci.yaml
LINTCMD = $(TEMPDIR)/golangci-lint run --tests=false --timeout=4m --config .golangci.yaml
RELEASE_CMD=$(TEMPDIR)/goreleaser release --rm-dist
SNAPSHOT_CMD=$(RELEASE_CMD) --skip-publish --snapshot
VERSION=$(shell git describe --dirty --always --tags)
Expand Down Expand Up @@ -111,6 +111,7 @@ bootstrap-tools: $(TEMPDIR)
curl -sSfL https://raw.githubusercontent.com/anchore/chronicle/main/install.sh | sh -s -- -b $(TEMPDIR)/ v0.3.0
.github/scripts/goreleaser-install.sh -d -b $(TEMPDIR)/ v1.4.1
GOBIN="$(shell realpath $(TEMPDIR))" go install github.com/neilpa/[email protected]
GOBIN="$(shell realpath $(TEMPDIR))" go install github.com/sigstore/cosign/cmd/[email protected]

.PHONY: bootstrap-go
bootstrap-go:
Expand Down
43 changes: 34 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ A CLI tool and Go library for generating a Software Bill of Materials (SBOM) fro

## Features
- Catalog container images and filesystems to discover packages and libraries.
- Generate in-toto attestations where an SBOM is included as the payload.
- Supports packages and libraries from various ecosystems (APK, DEB, RPM, Ruby Bundles, Python Wheel/Egg/requirements.txt, JavaScript NPM/Yarn, Java JAR/EAR/WAR/PAR/SAR, Jenkins plugins JPI/HPI, Go modules, PHP Composer)
- Linux distribution identification (supports Alpine, BusyBox, CentOS/RedHat, Debian/Ubuntu flavored distributions)
- Supports Docker and OCI image formats
Expand Down Expand Up @@ -68,7 +69,8 @@ nix-shell -p syft

## Getting started

To generate an SBOM for a Docker or OCI image:
#### SBOM
To generate an SBOM for an OCI image:
```
syft <image>
```
Expand All @@ -85,6 +87,17 @@ To include software from all image layers in the SBOM, regardless of its presenc
syft packages <image> --scope all-layers
```

#### SBOM Attestation
To generate an attested SBOM for an OCI image as the predicate of an in-toto attestation
```
syft attest --output [FORMAT] --key [KEY] [SOURCE] [flags]
```

The above output is in the form of the [DSSE envelope](https://github.com/secure-systems-lab/dsse/blob/master/envelope.md#dsse-envelope).
The payload is a base64 encoded `in-toto` statement with the SBOM as the predicate, the payload type is `application/vnd.in-toto+json`, and the signatures array is populated
with the contents needed for public key verification. For details on workflows using this command see [here](#adding-an-sbom-to-an-image-as-an-attestation-using-syft).


### Supported sources

Syft can generate a SBOM from a variety of sources:
Expand Down Expand Up @@ -396,6 +409,16 @@ registry:
token: ""
# - ... # note, more credentials can be provided via config file only

# generate an attested SBOM
attest:
# path to the private key file to use for attestation
# SYFT_ATTEST_KEY env var
key: "cosign.key"

# password to decrypt to given private key
# SYFT_ATTEST_PASSWORD env var, additionally responds to COSIGN_PASSWORD
password: ""

log:
# use structured logging
# same as SYFT_LOG_STRUCTURED env var
Expand Down Expand Up @@ -432,30 +455,32 @@ anchore:
dockerfile: ""
```
### Adding an SBOM to an image as an attestation
### Adding an SBOM to an image as an attestation using Syft
`syft attest --output [FORMAT] --key [KEY] [SOURCE] [flags]`

SBOMs themselves can serve as input to different analysis tools. The Anchore organization offers the vulnerability scanner
[grype](https://github.com/anchore/grype) as one such tool.
One of the foundational approaches to "trust" between tools is for producers to use the artifacts generated by syft as attestations to their images.
The SBOM output of syft can be used with the [cosign](https://github.com/sigstore/cosign) tool to generate an attestation that is attached to a signed image.
The DSSE output of `syft attest` can be used with the [cosign](https://github.com/sigstore/cosign) tool to attach an attestation to an image.

#### Example attest
Note for the following example replace `test/image:latest` with an image you own. You should also have push access to
Note for the following example replace `docker.io/image:latest` with an image you own. You should also have push access to
its remote reference. Replace $MY_PRIVATE_KEY with a private key you own or have generated with cosign.

```bash
cosign sign --key $MY_PRIVATE_KEY test/image:latest
syft test/image:latest -o json > test_latest_sbom.json
cosign attest --predicate test_latest_sbom.json --key $MY_PRIVATE_KEY test/image:latest
syft attest --key $MY_PRIVATE_KEY docker.io/image:latest > image_latest_sbom_attestation.json
cosign attach attestation --attestation image_latest_sbom_attestation.json docker.io/image:latest
```

Verify the new attestation exists on your image
```bash
cosign verify-attestation -key $MY_PUBLIC_KEY test/image:latest | jq '.payload |= @base64d | .payload | fromjson | .predicate.Data | fromjson | .'
cosign verify-attestation -key $MY_PUBLIC_KEY docker.io/image:latest | jq '.payload | @base64d | .payload | fromjson | .predicate'
```

You should see this output along with the attached SBOM.
```
Verification for test/image:latest --
Verification for docker.io/image:latest --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
Expand Down
Loading

0 comments on commit ac08883

Please sign in to comment.