feat: add an option to print provenance (#87)

* add an option to print provenance

Signed-off-by: Asra Ali <asraa@google.com>

fix

Signed-off-by: Asra Ali <asraa@google.com>

* print provenaace

Signed-off-by: Asra Ali <asraa@google.com>
This commit is contained in:
asraa
2022-06-08 15:35:59 -05:00
committed by GitHub
parent 2a0dd1c120
commit a717cc5512
4 changed files with 53 additions and 44 deletions

View File

@@ -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
@@ -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

62
main.go
View File

@@ -17,12 +17,13 @@ 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"
@@ -30,68 +31,63 @@ 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() {
@@ -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 == "" {
@@ -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 {
@@ -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)
@@ -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()

View File

@@ -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)

View File

@@ -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
}