SLSA (Supply Chain Levels for Software Artifacts) provenance is a framework for recording and verifying the integrity and security of software components throughout their lifecycle, from development to deployment.
It is a set of standards and best practices designed to increase transparency and accountability in software supply chains. SLSA aims to provide a consistent way to communicate the security and integrity of software components and their dependencies, enabling organizations to make informed decisions about the software they use.
SLSA defines four levels of supply chain security, with each level building on the previous one. At each level, specific security measures are implemented and verified to ensure the integrity of the software supply chain. The four levels of SLSA are:
- Level 0: none
- Level 1: Attestation showing that the package was built as expected
- Level 2: Signed attestation, generated by a hosted build service
- Level 3: Hardened build service
SLSA is becoming increasingly important as more organizations rely on software components from third-party sources, and as the risks associated with supply chain attacks continue to rise.
SLSA Community provides a set of builders to help organizations implement SLSA requirements by using GitHub Action workflows that can be used to generate SLSA provenance for your projects.
In this example, we used SLSA 3 Generic Builder to generate SLSA provenance for a Go project. To get more detail, you can read the following blog post from the SLSA community:
https://slsa.dev/blog/2022/08/slsa-github-workflows-generic-ga
As a next step, you can verify your attestation by using a tool called slsa-verifier to verify the signature of the generated provenance file, as these builders use Sigstore utilities to sign the generated provenance file with a keyless approach which also means that they upload it to the transparency log server called Rekor.
- to install slsa-verifier:
nix-env -iA nixos.slsa-verifier
- to install rekor-cli:
nix-env -iA nixos.rekor-cli
To verify the artifacts, you should download the tarballs/binaries and the provenance file first:
gh release download -R developer-guy/goreleaser-slsa-provenance -p "*.intoto.jsonl"
gh release download -R developer-guy/goreleaser-slsa-provenance -p "*.tar.gz"
Then, you can grab the log entry UUID by searching the attestation checksum in the Rekor transparency log server::
$ rekor-cli search --artifact multiple.intoto.jsonl
Found matching entries (listed by UUID):
24296fb24b8ad77aa15437c51886ccc312ca822f1c67cb4c436cf79f57e1f637ed992cd162530242
Then, you can use rekor-cli
to get the log entry:
$ rekor-cli get --format=json --uuid 24296fb24b8ad77aa15437c51886ccc312ca822f1c67cb4c436cf79f57e1f637ed992c
d162530242 | jq -r '.Attestation' | jq
You can click to see the whole attestation file☝️
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "goreleaser-slsa-provenance_Linux_arm64.tar.gz",
"digest": {
"sha256": "348a036ba9cfb9f8db615dd1576e02f84179a7702af1a5b951605ad0ba3e8881"
}
},
{
"name": "goreleaser-slsa-provenance_Linux_i386.tar.gz",
"digest": {
"sha256": "41c08429b25207640b1bb85e073598576289c52e1b2b45de91d5f16f4b00d947"
}
},
{
"name": "goreleaser-slsa-provenance_Windows_x86_64.zip",
"digest": {
"sha256": "b906d86a8bc858418e6aea7cd7902b71bc49093b8dc9eb7289bf821c835d213b"
}
},
{
"name": "goreleaser-slsa-provenance_Windows_i386.zip",
"digest": {
"sha256": "c3c77ba71afda6fc604aae346d88fcf7c24d9fe14c65a722a4ac5043edd090a8"
}
},
{
"name": "goreleaser-slsa-provenance_Windows_arm64.zip",
"digest": {
"sha256": "d3e3013c414d12aae109ba1dff80403f53e739d0ec8d7aa8a07547762829fce4"
}
},
{
"name": "goreleaser-slsa-provenance_Linux_x86_64.tar.gz",
"digest": {
"sha256": "f470df89804b082de3f850bbe7c3b3525417b5593dd055c9c3a5b4ce3c869155"
}
},
{
"name": "goreleaser-slsa-provenance_Darwin_x86_64.tar.gz",
"digest": {
"sha256": "f6c4193d85726a7e2334b79ed272103c992f2ca154a6f828a508b2e26a7f8333"
}
},
{
"name": "goreleaser-slsa-provenance_Darwin_arm64.tar.gz",
"digest": {
"sha256": "fedddadb2fa79b655e0c5c53ccbdfcbe0675196b9e167e1ce557f9e120394f85"
}
}
],
"predicate": {
"builder": {
"id": "https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.5.0"
},
"buildType": "https://github.com/slsa-framework/slsa-github-generator/generic@v1",
"invocation": {
"configSource": {
"uri": "git+https://github.com/developer-guy/goreleaser-slsa-provenance@refs/tags/v0.1.0",
"digest": {
"sha1": "af2de62d809c3b5e3ccd2653f4b476a7bc968226"
},
"entryPoint": ".github/workflows/goreleaser.yml"
},
"parameters": {},
"environment": {
"github_actor": "developer-guy",
"github_actor_id": "16693043",
"github_base_ref": "",
"github_event_name": "push",
"github_event_payload": {
"after": "1fde625cd60958063efdbf68cfbe63bd1ab07c7d",
"base_ref": null,
"before": "dd75abd3b58033c7416bb631b9116863616358cd",
"commits": [],
"compare": "https://github.com/developer-guy/goreleaser-slsa-provenance/compare/dd75abd3b580...1fde625cd609",
"created": false,
"deleted": false,
"forced": true,
"head_commit": {
"author": {
"email": "[email protected]",
"name": "Batuhan Apaydın",
"username": "developer-guy"
},
"committer": {
"email": "[email protected]",
"name": "Batuhan Apaydın",
"username": "developer-guy"
},
"distinct": true,
"id": "af2de62d809c3b5e3ccd2653f4b476a7bc968226",
"message": "initial commit\n\nSigned-off-by: Batuhan Apaydın <[email protected]>",
"timestamp": "2023-03-23T22:40:10+03:00",
"tree_id": "e094c3bc9c86a896315564f7fdd3d4916ba10628",
"url": "https://github.com/developer-guy/goreleaser-slsa-provenance/commit/af2de62d809c3b5e3ccd2653f4b476a7bc968226"
},
"pusher": {
"email": "[email protected]",
"name": "developer-guy"
},
"ref": "refs/tags/v0.1.0",
"repository": {
"allow_forking": true,
"archive_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/{archive_format}{/ref}",
"archived": false,
"assignees_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/assignees{/user}",
"blobs_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/git/blobs{/sha}",
"branches_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/branches{/branch}",
"clone_url": "https://github.com/developer-guy/goreleaser-slsa-provenance.git",
"collaborators_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/collaborators{/collaborator}",
"comments_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/comments{/number}",
"commits_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/commits{/sha}",
"compare_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/compare/{base}...{head}",
"contents_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/contents/{+path}",
"contributors_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/contributors",
"created_at": 1679596019,
"default_branch": "master",
"deployments_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/deployments",
"description": "A demonstration of showing how to use SLSA 3 Generic Generator with GoReleaser to release artifacts while generating signed SLSA provenance",
"disabled": false,
"downloads_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/downloads",
"events_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/events",
"fork": false,
"forks": 0,
"forks_count": 0,
"forks_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/forks",
"full_name": "developer-guy/goreleaser-slsa-provenance",
"git_commits_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/git/commits{/sha}",
"git_refs_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/git/refs{/sha}",
"git_tags_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/git/tags{/sha}",
"git_url": "git://github.com/developer-guy/goreleaser-slsa-provenance.git",
"has_discussions": false,
"has_downloads": true,
"has_issues": true,
"has_pages": false,
"has_projects": true,
"has_wiki": true,
"homepage": "",
"hooks_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/hooks",
"html_url": "https://github.com/developer-guy/goreleaser-slsa-provenance",
"id": 618091561,
"is_template": false,
"issue_comment_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/issues/comments{/number}",
"issue_events_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/issues/events{/number}",
"issues_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/issues{/number}",
"keys_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/keys{/key_id}",
"labels_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/labels{/name}",
"language": "Go",
"languages_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/languages",
"license": {
"key": "apache-2.0",
"name": "Apache License 2.0",
"node_id": "MDc6TGljZW5zZTI=",
"spdx_id": "Apache-2.0",
"url": "https://api.github.com/licenses/apache-2.0"
},
"master_branch": "master",
"merges_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/merges",
"milestones_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/milestones{/number}",
"mirror_url": null,
"name": "goreleaser-slsa-provenance",
"node_id": "R_kgDOJNdUKQ",
"notifications_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/notifications{?since,all,participating}",
"open_issues": 0,
"open_issues_count": 0,
"owner": {
"avatar_url": "https://avatars.githubusercontent.com/u/16693043?v=4",
"email": "[email protected]",
"events_url": "https://api.github.com/users/developer-guy/events{/privacy}",
"followers_url": "https://api.github.com/users/developer-guy/followers",
"following_url": "https://api.github.com/users/developer-guy/following{/other_user}",
"gists_url": "https://api.github.com/users/developer-guy/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/developer-guy",
"id": 16693043,
"login": "developer-guy",
"name": "developer-guy",
"node_id": "MDQ6VXNlcjE2NjkzMDQz",
"organizations_url": "https://api.github.com/users/developer-guy/orgs",
"received_events_url": "https://api.github.com/users/developer-guy/received_events",
"repos_url": "https://api.github.com/users/developer-guy/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/developer-guy/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/developer-guy/subscriptions",
"type": "User",
"url": "https://api.github.com/users/developer-guy"
},
"private": false,
"pulls_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/pulls{/number}",
"pushed_at": 1679600419,
"releases_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/releases{/id}",
"size": 8,
"ssh_url": "[email protected]:developer-guy/goreleaser-slsa-provenance.git",
"stargazers": 0,
"stargazers_count": 0,
"stargazers_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/stargazers",
"statuses_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/statuses/{sha}",
"subscribers_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/subscribers",
"subscription_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/subscription",
"svn_url": "https://github.com/developer-guy/goreleaser-slsa-provenance",
"tags_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/tags",
"teams_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/teams",
"topics": [
"goreleaser",
"slsa",
"slsa-framework",
"slsa-generic-generator",
"slsa-provenance",
"slsa3",
"slsalevel3"
],
"trees_url": "https://api.github.com/repos/developer-guy/goreleaser-slsa-provenance/git/trees{/sha}",
"updated_at": "2023-03-23T19:32:02Z",
"url": "https://github.com/developer-guy/goreleaser-slsa-provenance",
"visibility": "public",
"watchers": 0,
"watchers_count": 0,
"web_commit_signoff_required": false
},
"sender": {
"avatar_url": "https://avatars.githubusercontent.com/u/16693043?v=4",
"events_url": "https://api.github.com/users/developer-guy/events{/privacy}",
"followers_url": "https://api.github.com/users/developer-guy/followers",
"following_url": "https://api.github.com/users/developer-guy/following{/other_user}",
"gists_url": "https://api.github.com/users/developer-guy/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/developer-guy",
"id": 16693043,
"login": "developer-guy",
"node_id": "MDQ6VXNlcjE2NjkzMDQz",
"organizations_url": "https://api.github.com/users/developer-guy/orgs",
"received_events_url": "https://api.github.com/users/developer-guy/received_events",
"repos_url": "https://api.github.com/users/developer-guy/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/developer-guy/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/developer-guy/subscriptions",
"type": "User",
"url": "https://api.github.com/users/developer-guy"
}
},
"github_head_ref": "",
"github_ref": "refs/tags/v0.1.0",
"github_ref_type": "tag",
"github_repository_id": "618091561",
"github_repository_owner": "developer-guy",
"github_repository_owner_id": "16693043",
"github_run_attempt": "2",
"github_run_id": "4504563596",
"github_run_number": "5",
"github_sha1": "af2de62d809c3b5e3ccd2653f4b476a7bc968226"
}
},
"metadata": {
"buildInvocationID": "4504563596-2",
"completeness": {
"parameters": true,
"environment": false,
"materials": false
},
"reproducible": false
},
"materials": [
{
"uri": "git+https://github.com/developer-guy/goreleaser-slsa-provenance@refs/tags/v0.1.0",
"digest": {
"sha1": "af2de62d809c3b5e3ccd2653f4b476a7bc968226"
}
}
]
}
}
or, you can use a fancy UI provided by the Chainguard team: search.sigstore.dev
:
Then, you can verify the signature of the generated provenance file and verify the artifacts by using the following command:
$ slsa-verifier verify-artifact \
--provenance-path multiple.intoto.jsonl \
--source-uri github.com/developer-guy/gorelaser-slsa-provenance \
--source-tag v0.1.0 \
goreleaser-slsa-provenance_Darwin_arm64.tar.gz
Verified signature against tlog entry index 16144987 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77aa15437c51886ccc312ca822f1c67cb4c436cf79f57e1f637ed992cd162530242
Verified build using builder https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.5.0 at commit af2de62d809c3b5e3ccd2653f4b476a7bc968226
PASSED: Verified SLSA provenance