Skip to content

Commit

Permalink
feat: add an option to print provenance (slsa-framework#87)
Browse files Browse the repository at this point in the history
* add an option to print provenance

Signed-off-by: Asra Ali <[email protected]>

fix

Signed-off-by: Asra Ali <[email protected]>

* print provenaace

Signed-off-by: Asra Ali <[email protected]>
  • Loading branch information
asraa authored Jun 8, 2022
1 parent 1605d32 commit 684c2f4
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 44 deletions.
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ $ go run . --help
path to an artifact to verify
-branch string
expected branch the binary was compiled from (default "main")
-print-provenance
output the verified provenance
-provenance string
path to a provenance file
-source string
Expand All @@ -74,22 +76,20 @@ $ go run . --help
### Example

```bash
$ go run . --artifact-path ~/Downloads/binary-linux-amd64 --provenance ~/Downloads/binary-linux-amd64.intoto.jsonl --source github.com/origin/repo

Verified against tlog entry 1544571
verified SLSA provenance produced at
$ go run . -artifact-path ~/Downloads/slsa-verifier-linux-amd64 -provenance ~/Downloads/slsa-verifier-linux-amd64.intoto.jsonl -source github.com/slsa-framework/slsa-verifier -tag v1.0.0
Verified signature against tlog entry index 2592016 at URL: https://rekor.sigstore.dev/api/v1/log/entries/d77621eaf1de74592546f773192f49ed995e8b12f2e5eeed02057ae32b24aa95
Signing certificate information:
{
"caller": "origin/repo",
"commit": "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
"job_workflow_ref": "/slsa-framework/slsa-github-generator/blob/main/.github/workflows/builder_go_slsa3.yml",
"trigger": "workflow_dispatch",
"issuer": "https://token.actions.githubusercontent.com"
"caller": "slsa-framework/slsa-verifier",
"commit": "c1b6db643d6134285dc929206fdcfa3712a877eb",
"job_workflow_ref": "/slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml@refs/tags/v0.0.1",
"trigger": "push",
"issuer": "https://token.actions.githubusercontent.com"
}
{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"https://slsa.dev/provenance/v0.2","subject":[{"name":"binary-linux-amd64","digest":{"sha256":"723ccb85318bc8b1a9dd29340612ce1268cd3418d70f68e775edbdc16d1d9158"}}],"predicate":{...}}
successfully verified SLSA provenance
PASSED: Verified SLSA provenance
```

The verified in-toto statement is written to stdout and can be used to pipe into policy engines.
The verified in-toto statement may be written to stdout with the `--print-provenance` flag to pipe into policy engines.

## Technical design

Expand Down
62 changes: 32 additions & 30 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,81 +17,77 @@ import (
)

var (
provenancePath string
artifactPath string
source string
branch string
tag string
versiontag string
provenancePath string
artifactPath string
source string
branch string
tag string
versiontag string
printProvenance bool
)

var defaultRekorAddr = "https://rekor.sigstore.dev"

func verify(ctx context.Context,
provenance []byte, artifactHash, source, branch string,
tag, versiontag *string,
) error {
) ([]byte, error) {
rClient, err := rekor.NewClient(defaultRekorAddr)
if err != nil {
return err
return nil, err
}

/* Verify signature on the intoto attestation. */
env, cert, err := pkg.VerifyProvenanceSignature(ctx, rClient, provenance, artifactHash)
if err != nil {
return err
return nil, err
}

/* Verify properties of the signing identity. */
// Get the workflow info given the certificate information.
workflowInfo, err := pkg.GetWorkflowInfoFromCertificate(cert)
if err != nil {
return err
return nil, err
}

b, err := json.MarshalIndent(workflowInfo, "", "\t")
if err != nil {
return err
return nil, err
}
fmt.Fprintf(os.Stderr, "verified signature on SLSA provenance produced at \n %s\n", b)
fmt.Fprintf(os.Stderr, "Signing certificate information:\n %s\n", b)

/* Verify properties of the SLSA provenance. */
// Verify the workflow identity.
if err := pkg.VerifyWorkflowIdentity(workflowInfo, source); err != nil {
return err
return nil, err
}

// Unpack and verify info in the provenance, including the Subject Digest.
if err := pkg.VerifyProvenance(env, artifactHash); err != nil {
return err
return nil, err
}

// Verify the branch.
if err := pkg.VerifyBranch(env, branch); err != nil {
return err
return nil, err
}

// Verify the tag.
if tag != nil {
if err := pkg.VerifyTag(env, *tag); err != nil {
return err
return nil, err
}
}

// Verify the versioned tag.
if versiontag != nil {
if err := pkg.VerifyVersionedTag(env, *versiontag); err != nil {
return err
return nil, err
}
}

// Print verified provenance to stdout.
pyld, err := base64.StdEncoding.DecodeString(env.Payload)
if err != nil {
return fmt.Errorf("%w: %s", pkg.ErrorInvalidDssePayload, "decoding payload")
}
fmt.Fprintf(os.Stdout, "%s\n", string(pyld))
return nil
// Return verified provenance.
return base64.StdEncoding.DecodeString(env.Payload)
}

func main() {
Expand All @@ -101,6 +97,7 @@ func main() {
flag.StringVar(&branch, "branch", "main", "expected branch the binary was compiled from")
flag.StringVar(&tag, "tag", "", "[optional] expected tag the binary was compiled from")
flag.StringVar(&versiontag, "versioned-tag", "", "[optional] expected version the binary was compiled from. Uses semantic version to match the tag")
flag.BoolVar(&printProvenance, "print-provenance", false, "print the verified provenance to std out")
flag.Parse()

if provenancePath == "" || artifactPath == "" || source == "" {
Expand All @@ -122,13 +119,18 @@ func main() {
os.Exit(1)
}

if err := runVerify(artifactPath, provenancePath, source, branch,
ptag, pversiontag); err != nil {
fmt.Fprintf(os.Stderr, "verification failed: %v\n", err)
verifiedProvenance, err := runVerify(artifactPath, provenancePath, source, branch,
ptag, pversiontag)
if err != nil {
fmt.Fprintf(os.Stderr, "FAILED: SLSA verification failed: %v\n", err)
os.Exit(2)
}

fmt.Fprintf(os.Stderr, "successfully verified SLSA provenance\n")
fmt.Fprintf(os.Stderr, "PASSED: Verified SLSA provenance\n")

if printProvenance {
fmt.Fprintf(os.Stdout, "%s\n", string(verifiedProvenance))
}
}

func isFlagPassed(name string) bool {
Expand All @@ -143,7 +145,7 @@ func isFlagPassed(name string) bool {

func runVerify(artifactPath, provenancePath, source, branch string,
ptag, pversiontag *string,
) error {
) ([]byte, error) {
f, err := os.Open(artifactPath)
if err != nil {
log.Fatal(err)
Expand All @@ -152,7 +154,7 @@ func runVerify(artifactPath, provenancePath, source, branch string,

provenance, err := os.ReadFile(provenancePath)
if err != nil {
return err
return nil, err
}

h := sha256.New()
Expand Down
2 changes: 1 addition & 1 deletion main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ func Test_runVerify(t *testing.T) {
artifactPath = filepath.Clean(fmt.Sprintf("./testdata/%v/%s", v, tt.artifact))
provenancePath = fmt.Sprintf("%s.intoto.jsonl", artifactPath)

err := runVerify(artifactPath,
_, err := runVerify(artifactPath,
provenancePath,
tt.source, branch,
tt.ptag, tt.pversiontag)
Expand Down
9 changes: 8 additions & 1 deletion pkg/provenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,15 @@ func FindSigningCertificate(ctx context.Context, uuids []string, dssePayload dss
if err := cosign.CheckExpiry(cert, it); err != nil {
continue
}
uuid, err := cosign.ComputeLeafHash(entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Error computing leaf hash for tlog entry at index: %d\n", *entry.LogIndex)
continue
}

// success!
fmt.Fprintf(os.Stderr, "Verified against tlog entry %d\n", *entry.LogIndex)
url := fmt.Sprintf("%v/%v/%v", defaultRekorAddr, "api/v1/log/entries", hex.EncodeToString(uuid))
fmt.Fprintf(os.Stderr, "Verified signature against tlog entry index %d at URL: %s\n", *entry.LogIndex, url)
return cert, nil
}

Expand Down

0 comments on commit 684c2f4

Please sign in to comment.