Skip to content

Latest commit

 

History

History
386 lines (287 loc) · 13.6 KB

getting-started.md

File metadata and controls

386 lines (287 loc) · 13.6 KB

Getting Started

This document should allow you to stand up a fully functioning sigstore stack, including:

  • Fulcio
  • Rekor
  • CTLog
  • Trillian - backing Rekor and CTLog
  • Tuf mirror

Using scaffolding on your own GitHub actions

There's a reusable action that you can use as is.

Prerequisites

You need to install yq. You can do this like so:

go install github.com/mikefarah/yq/v4@latest

You also need ko a tool for building lighter, more secure container images.

go install github.com/google/ko@latest

There are further install options on the ko website.

Running locally on KinD

You should be able to install KinD and Knative bits by running (from head, after cloning the repo):

./hack/setup-kind.sh

Or by downloading a release version of the script

curl -fLo /tmp/setup-kind.sh https://github.com/sigstore/scaffolding/releases/download/v0.7.1/setup-kind.sh
chmod u+x /tmp/setup-kind.sh
/tmp/setup-kind.sh

NOTE If you run the script multiple times, you will have to delete the cluster and uninstall the docker registry container between running the setup-kind.sh it spins up a registry container in a daemon mode. To clean a previously running registry, you can do one of these:

YOLO:

docker rm -f `docker ps -a | grep 'registry:2' | awk -F " " '{print $1}'`

Or to check things first:

docker ps -a | grep registry
b1e3f3238f7a   registry:2                        "/entrypoint.sh /etc…"   15 minutes ago   Up 15 minutes               0.0.0.0:5000->5000/tcp, :::5001->5001/tcp   registry.local

So that's the running version of the registry, so first kill and then remove it:

docker rm -f b1e3f3238f7a

Install sigstore-scaffolding pieces

From the release

curl -Lo /tmp/setup-scaffolding-from-release.sh https://github.com/sigstore/scaffolding/releases/download/v0.7.1/setup-scaffolding-from-release.sh
chmod u+x /tmp/setup-scaffolding-from-release.sh
/tmp/setup-scaffolding-from-release.sh

From checked out repo

If you're deploying to kind cluster created above, tell ko where it is, or change to where you're deploying your images.

export KO_DOCKER_REPO=registry.local:5001/sigstore
./hack/setup-scaffolding.sh

Outputs

The step above creates 5 namespaces:

  • trillian-system
  • ctlog-system
  • fulcio-system
  • rekor-system
  • tuf-system

trillian-system namespace

trillian-system namespace contains all things related to Trillian. This means there will be two services log-server, log-signer, and a mysql pod.

To access these services from the cluster, you'd use:

  • log-server.trillian-system.svc
  • log-signer.trillian-system.svc
  • mysql-trillian.trillian-system.svc

ctlog-system namespace

ctlog-system namespace contains the ctlog service and can be accessed with:

  • ctlog.ctlog-system.svc

fulcio-system namespace

fulcio-system namespace contains Fulcio and Fulcio can be accessed in the cluster with:

  • fulcio.fulcio-system.svc for HTTP or
  • fulcio-grpc.fulcio-system.svc for GRPC

rekor-system namespace

rekor-system namespace contains Rekor and Rekor can be accessed in the cluster with:

  • rekor.rekor-system.svc

tuf-system namespace

tuf-system namespace contains TUF root mirror that we need to point cosign and other tools to, because the root of trust is not the public cosign instance. Tuf can be accessed in the cluster with:

  • tuf.tuf-system.svc

default namespace

To make it easier to test keyless signing without going through the browser based auth, you can install OIDC issuer on your TEST cluster. It does no authentication, so do not install this on anything except your local kind test cluster. Just by doing a curl against it will give you an OIDC token that you can use as --identity-token on the calls with cosign.

ko apply -BRf ./testdata/config/gettoken

Accessing your new cluster endpoints

In order to access the services running in the cluster, we utilize port-forwarding provided by Kubernetes.

Network access

Setup port forwarding:

kubectl -n kourier-system port-forward service/kourier-internal 8080:80 &

Adding localhost entries to make tools usable

Add the following entries to your /etc/hosts file

127.0.0.1 rekor.rekor-system.svc
127.0.0.1 fulcio.fulcio-system.svc
127.0.0.1 ctlog.ctlog-system.svc
127.0.0.1 gettoken.default.svc
127.0.0.1 tuf.tuf-system.svc

Setting up environmental variables

Instead of having to specify these in various flags when calling cosign and long URLs, let's create some up front:

export REKOR_URL=http://rekor.rekor-system.svc:8080
export FULCIO_URL=http://fulcio.fulcio-system.svc:8080
export FULCIO_GRPC_URL=http://fulcio-grpc.fulcio-system.svc:8080
export ISSUER_URL=http://gettoken.default.svc:8080
export TUF_MIRROR=http://tuf.tuf-system.svc:8080

Setting up an OIDC issuer running on the cluster.

For testing keyless signing we need an OIDC token provider, so let's create one that runs on the cluster and issues OIDC tokens.

ko apply -BRf ./testdata/config/gettoken

Testing Your new Sigstore Kind Cluster

Let's first run a quick smoke test that does a cosign sign followed by making sure that the rekor entry is created for it.

  1. Get TUF root from the tuf-system namespace
kubectl -n tuf-system get secrets tuf-root -ojsonpath='{.data.root}' | base64 -d > ./root.json
  1. Initialize cosign with our root.
cosign initialize --mirror $TUF_MIRROR --root ./root.json

An example invocation of this on my machine looked like this:

vaikas@villes-mbp scaffolding % cosign initialize --mirror $TUF_MIRROR --root ./root.json
Root status:
 {
	"local": "/Users/vaikas/.sigstore/root",
	"remote": "http://tuf.tuf-system.svc:8080",
	"metadata": {
		"root.json": {
			"version": 1,
			"len": 2178,
			"expiration": "04 Feb 23 23:28 UTC",
			"error": ""
		},
		"snapshot.json": {
			"version": 1,
			"len": 618,
			"expiration": "04 Feb 23 23:28 UTC",
			"error": ""
		},
		"targets.json": {
			"version": 1,
			"len": 1028,
			"expiration": "04 Feb 23 23:28 UTC",
			"error": ""
		},
		"timestamp.json": {
			"version": 1,
			"len": 619,
			"expiration": "04 Feb 23 23:28 UTC",
			"error": ""
		}
	},
	"targets": [
		"rekor.pub",
		"ctfe.pub",
		"fulcio_v1.crt.pem"
	]
}

If you have an image that you want to play with, great, you can also create one easily like this (that gets then uploaded to our local registry):

KO_DOCKER_REPO=registry.local:5001/sigstore
pushd $(mktemp -d)
go mod init example.com/demo
cat <<EOF > main.go
package main
import "fmt"
func main() {
   fmt.Println("hello world")
}
EOF
demoimage=`ko publish -B example.com/demo`
export demoimage=$demoimage
echo Created image $demoimage
popd

Then let's sign it (or change $demoimage to something else).

cosign sign --rekor-url $REKOR_URL --fulcio-url $FULCIO_URL --yes --allow-insecure-registry $demoimage --identity-token $(curl -s $ISSUER_URL)

An example invocation from my local instance is like so:

vaikas@villes-mbp scaffolding % cosign sign --rekor-url $REKOR_URL --fulcio-url $FULCIO_URL --yes --allow-insecure-registry $demoimage --identity-token $(curl -s $ISSUER_URL)
Generating ephemeral keys...
Retrieving signed certificate...

        Note that there may be personally identifiable information associated with this signed artifact.
        This may include the email address associated with the account with which you authenticate.
        This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
Successfully verified SCT...
tlog entry created with index: 0
Pushing signature to: registry.local:5001/sigstore/demo

Then let's verify the signature.

cosign verify --rekor-url $REKOR_URL --allow-insecure-registry $demoimage --certificate-identity=https://kubernetes.io/namespaces/default/serviceaccounts/default --certificate-oidc-issuer=https://kubernetes.default.svc.cluster.local

An example invocation from my local instance is like so:

vaikas@villes-mbp scaffolding % cosign verify --rekor-url $REKOR_URL --allow-insecure-registry $demoimage --certificate-identity=https://kubernetes.io/namespaces/default/serviceaccounts/default --certificate-oidc-issuer=https://kubernetes.default.svc.cluster.local
**Warning** Missing fallback target fulcio.crt.pem, skipping

Verification for registry.local:5001/sigstore/demo@sha256:b6cfc6e87706304be13f607b238d905db1096619c0217c82f4151117e0112025 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - Any certificates were verified against the Fulcio roots.

[{"critical":{"identity":{"docker-reference":"registry.local:5000/sigstore/demo"},"image":{"docker-manifest-digest":"sha256:b6cfc6e87706304be13f607b238d905db1096619c0217c82f4151117e0112025"},"type":"cosign container image signature"},"optional":{"Bundle":{"SignedEntryTimestamp":"MEUCIQD8MdBVswffTOuubuvTHIWw4BMkOmUmgrQEavmAnWZ1MAIgSNO+gf4ldCql0botNgtb23RWPD4iYv0Qq93sheWf5wo=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4w<SNIPPED_HERE_FOR_READABILITY>b45b4573e2a7e5f876bdff025b06f3243"}},"Issuer":"https://kubernetes.default.svc","Subject":"https://kubernetes.io/namespaces/default/serviceaccounts/default"}}]

And the **Warning** is just letting us know that there's no custom metadata on TUF, and we fallback on the hard-coded names, and that's one of the ones we expect for Fulcio (and the other is the one we use: fulcio_v1.crt.pem)

echo -n 'foobar test attestation' > ./predicate-file
cosign attest --predicate ./predicate-file --fulcio-url $FULCIO_URL --rekor-url $REKOR_URL --allow-insecure-registry --yes $demoimage --identity-token $(curl -s $ISSUER_URL)

An example invocation from my local instance:

vaikas@villes-mbp scaffolding % echo -n 'foobar test attestation' > ./predicate-file
cosign attest --predicate ./predicate-file --fulcio-url $FULCIO_URL --rekor-url $REKOR_URL --allow-insecure-registry --yes $demoimage --identity-token $(curl -s $ISSUER_URL)

Generating ephemeral keys...
Retrieving signed certificate...

        Note that there may be personally identifiable information associated with this signed artifact.
        This may include the email address associated with the account with which you authenticate.
        This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
Successfully verified SCT...
Using payload from: ./predicate-file
tlog entry created with index: 1

And then finally let's verify the attestation we just created:

cosign verify-attestation --rekor-url $REKOR_URL --allow-insecure-registry $demoimage --certificate-identity=https://kubernetes.io/namespaces/default/serviceaccounts/default --certificate-oidc-issuer=https://kubernetes.default.svc.cluster.local

An example invocation from my local instance:

vaikas@villes-mbp scaffolding % cosign verify-attestation --rekor-url $REKOR_URL --allow-insecure-registry $demoimage --certificate-identity=https://kubernetes.io/namespaces/default/serviceaccounts/default --certificate-oidc-issuer=https://kubernetes.default.svc.cluster.local
**Warning** Missing fallback target fulcio.crt.pem, skipping

Verification for registry.local:5001/sigstore/demo@sha256:b6cfc6e87706304be13f607b238d905db1096619c0217c82f4151117e0112025 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - Any certificates were verified against the Fulcio roots.
Certificate subject:  https://kubernetes.io/namespaces/default/serviceaccounts/default
Certificate issuer URL:  https://kubernetes.default.svc
{"payloadType":"application/vnd.in-toto+json","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJjb3NpZ24uc2lnc3RvcmUuZGV2L2F0dGVzdGF0aW9uL3YxIiwic3ViamVjdCI6W3sibmFtZSI6InJlZ2lzdHJ5LmxvY2FsOjUwMDAvc2lnc3RvcmUvZGVtbyIsImRpZ2VzdCI6eyJzaGEyNTYiOiJiNmNmYzZlODc3MDYzMDRiZTEzZjYwN2IyMzhkOTA1ZGIxMDk2NjE5YzAyMTdjODJmNDE1MTExN2UwMTEyMDI1In19XSwicHJlZGljYXRlIjp7IkRhdGEiOiJmb29iYXIgdGVzdCBhdHRlc3RhdGlvbiIsIlRpbWVzdGFtcCI6IjIwMjItMDgtMDdUMDM6NTU6NDhaIn19","signatures":[{"keyid":"","sig":"MEUCIHXTVuffNLmCtnYg2AqCZ1YZfN87Ct3jL6Opx6ZA1czAAiEAs4BG3wEHP49Kg2YB+7gcFqg64J77aS/IDKb6sSbmRzU="}]}

And you can inspect the payload of the attestation by base64 decoding the payload, so for me:

vaikas@villes-mbp scaffolding % echo 'eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJjb3NpZ24uc2lnc3RvcmUuZGV2L2F0dGVzdGF0aW9uL3YxIiwic3ViamVjdCI6W3sibmFtZSI6InJlZ2lzdHJ5LmxvY2FsOjUwMDAvc2lnc3RvcmUvZGVtbyIsImRpZ2VzdCI6eyJzaGEyNTYiOiJiNmNmYzZlODc3MDYzMDRiZTEzZjYwN2IyMzhkOTA1ZGIxMDk2NjE5YzAyMTdjODJmNDE1MTExN2UwMTEyMDI1In19XSwicHJlZGljYXRlIjp7IkRhdGEiOiJmb29iYXIgdGVzdCBhdHRlc3RhdGlvbiIsIlRpbWVzdGFtcCI6IjIwMjItMDgtMDdUMDM6NTU6NDhaIn19' | base64 -d
{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"cosign.sigstore.dev/attestation/v1","subject":[{"name":"registry.local:5001/sigstore/demo","digest":{"sha256":"b6cfc6e87706304be13f607b238d905db1096619c0217c82f4151117e0112025"}}],"predicate":{"Data":"foobar test attestation","Timestamp":"2022-08-07T03:55:48Z"}}%

Notice our predicate is foobar test attestation as was in our predicate file.