Skip to content

Commit

Permalink
✨ Send rekor tlog index to webapp when publishing results (#1169)
Browse files Browse the repository at this point in the history
* wip

Signed-off-by: Spencer Schrock <sschrock@google.com>

* Include rekor tlog index in POST to scorecard API.

Signed-off-by: Spencer Schrock <sschrock@google.com>

* Add tests for extractTlogIndex

Signed-off-by: Spencer Schrock <sschrock@google.com>

---------

Signed-off-by: Spencer Schrock <sschrock@google.com>
  • Loading branch information
spencerschrock committed Jul 7, 2023
1 parent 50599de commit 33bb591
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 2 deletions.
35 changes: 33 additions & 2 deletions signing/signing.go
Expand Up @@ -33,6 +33,7 @@ import (

sigOpts "github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
"github.com/sigstore/cosign/v2/pkg/cosign"

"github.com/ossf/scorecard-action/entrypoint"
"github.com/ossf/scorecard-action/options"
Expand All @@ -52,7 +53,8 @@ var (

// Signing is a signing structure.
type Signing struct {
token string
token string
rekorTlogIndex int64
}

// New creates a new Signing instance.
Expand All @@ -78,6 +80,14 @@ func New(token string) (*Signing, error) {

// SignScorecardResult signs the results file and uploads the attestation to the Rekor transparency log.
func (s *Signing) SignScorecardResult(scorecardResultsFile string) error {
f, err := os.CreateTemp("", "bundle")
if err != nil {
return fmt.Errorf("creating temporary bundle file: %w", err)
}
bundlePath := f.Name()
f.Close()
defer os.Remove(bundlePath) // clean up

// Prepare settings for SignBlobCmd.
rootOpts := &sigOpts.RootOptions{Timeout: sigOpts.DefaultTimeout} // Just the timeout.
keyOpts := sigOpts.KeyOpts{
Expand All @@ -86,9 +96,9 @@ func (s *Signing) SignScorecardResult(scorecardResultsFile string) error {
OIDCIssuer: sigOpts.DefaultOIDCIssuerURL, // OIDC provider to get ID token to auth for Fulcio.
OIDCClientID: "sigstore",
SkipConfirmation: true, // skip cosign's privacy confirmation prompt as we run non-interactively
BundlePath: bundlePath,
}

var err error
for _, backoff := range backoffSchedule {
// This command will use the provided OIDCIssuer to authenticate into Fulcio, which will generate the
// signing certificate on the scorecard result. This attestation is then uploaded to the Rekor transparency log.
Expand All @@ -107,6 +117,12 @@ func (s *Signing) SignScorecardResult(scorecardResultsFile string) error {
return fmt.Errorf("error signing payload: %w", err)
}

rekorTlogIndex, err := extractTlogIndex(bundlePath)
if err != nil {
return err
}
s.rekorTlogIndex = rekorTlogIndex

return nil
}

Expand Down Expand Up @@ -143,10 +159,12 @@ func (s *Signing) ProcessSignature(jsonPayload []byte, repoName, repoRef string)
Result string `json:"result"`
Branch string `json:"branch"`
AccessToken string `json:"accessToken"`
TlogIndex int64 `json:"tlogIndex"`
}{
Result: string(jsonPayload),
Branch: repoRef,
AccessToken: s.token,
TlogIndex: s.rekorTlogIndex,
}

payloadBytes, err := json.Marshal(resultsPayload)
Expand Down Expand Up @@ -209,3 +227,16 @@ func postResults(endpoint *url.URL, payload []byte) error {

return nil
}

func extractTlogIndex(bundlePath string) (int64, error) {
contents, err := os.ReadFile(bundlePath)
if err != nil {
return 0, fmt.Errorf("reading cosign bundle file: %w", err)
}
var payload cosign.LocalSignedPayload
err = json.Unmarshal(contents, &payload)
if err != nil || payload.Bundle == nil {
return 0, fmt.Errorf("invalid cosign bundle file: %w", err)
}
return payload.Bundle.Payload.LogIndex, nil
}
39 changes: 39 additions & 0 deletions signing/signing_test.go
Expand Up @@ -128,6 +128,45 @@ func TestProcessSignature(t *testing.T) {
}
}

func Test_extractTlogIndex(t *testing.T) {
t.Parallel()
tests := []struct {
name string
bundlePath string
want int64
wantErr bool
}{
{
name: "valid bundle",
bundlePath: "testdata/cosign.bundle",
want: 23548006,
},
{
name: "invalid bundle",
bundlePath: "testdata/invalid-cosign.bundle",
wantErr: true,
},
{
name: "missing bundle",
bundlePath: "testdata/does-not-exist.bundle",
wantErr: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := extractTlogIndex(tt.bundlePath)
if (err != nil) != tt.wantErr {
t.Fatalf("unexpected err: %v, wantErr: %t", err, tt.wantErr)
}
if got != tt.want {
t.Errorf("wrong tlog index: got %d, wanted %d", got, tt.want)
}
})
}
}

//nolint:paralleltest // we are using t.Setenv
func TestProcessSignature_retries(t *testing.T) {
tests := []struct {
Expand Down
1 change: 1 addition & 0 deletions signing/testdata/cosign.bundle
@@ -0,0 +1 @@
{"base64Signature":"MEUCIQD4rAvIUYt0WgrXVL6whlkgJerX2jyRNDct3AwWSsGdJgIgP0DCR56AM9FQD/aEnZwnNT1s22V8PW/ud0YHREr2n0U=","cert":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMwakNDQWxlZ0F3SUJBZ0lVYzRvZkdaWUlxSEMvaW0xY0JPQ0FXbk9BQUQ4d0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpNd05qRXlNakV5TlRNMldoY05Nak13TmpFeU1qRXpOVE0yV2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVzUGd2b2k0b3ZyN3dLRWxtRkR0R2VqZHBwTXFEMkZtc2tHQ2EKUFNLNlVSRUlhQ3h2Q1NrRlNwQnE1bmNhd0lscWtnMVBnKy9sMHhhcDExd0hrOWplNEtPQ0FYWXdnZ0Z5TUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVBNkI1CmE4TXdjS0M4UFdMNjc4UGF3N0FTY3Rjd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d0lRWURWUjBSQVFIL0JCY3dGWUVUYzNOamFISnZZMnRBWjI5dloyeGxMbU52YlRBc0Jnb3JCZ0VFQVlPLwpNQUVCQkI1b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdmJHOW5hVzR2YjJGMWRHZ3dMZ1lLS3dZQkJBR0R2ekFCCkNBUWdEQjVvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2Ykc5bmFXNHZiMkYxZEdnd2dZa0dDaXNHQVFRQjFua0MKQkFJRWV3UjVBSGNBZFFEZFBUQnF4c2NSTW1NWkhoeVpaemNDb2twZXVONDhyZitIaW5LQUx5bnVqZ0FBQVlpeApnQUl3QUFBRUF3QkdNRVFDSUJTN3lEOERVUTN2b3RnRXFCZzhXekFqbmFkNjJGRVgvZXZCUkNnZTdmeWpBaUJECkZseG8vOC9OVWNvN3VRSkNSazgrbDUvQXN5dG1jNU5vL3l0OW9tYkg5ekFLQmdncWhrak9QUVFEQXdOcEFEQm0KQWpFQWhjT1hBSmNyWGovWnlTYi9DYUY4aldSckE4bkthRWllRkREVFI0dFhKakk2bVE0ZEM2R05mWU8xdnRpMQpDUU1pQWpFQW9PWU44dnRDOEt5b3BWR3F1MkUxaHJuWFlCUXJUK1I4eFN5OEZRMHNTQVhGYzU0aGM0S2ZPemthClJIVXZlUUZSCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K","rekorBundle":{"SignedEntryTimestamp":"MEQCIG+3Fj1/9aYBP2fp9gbI9RpOc1/9aawUip5+aflRrtn/AiAo2nuSf3IIFwHpAgQL8eLkA3++gRiUkXDJzRZqjCXRhA==","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJiOWJiNzc2MGEyYjNiOWQwZjA4ZTI5OGVjYjg3Y2ZmMmQxMzkxMjJlM2Y2ZDI1ODI5MGZiODA3YmYxYWZlNjkyIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUQ0ckF2SVVZdDBXZ3JYVkw2d2hsa2dKZXJYMmp5Uk5EY3QzQXdXU3NHZEpnSWdQMERDUjU2QU05RlFEL2FFblp3bk5UMXMyMlY4UFcvdWQwWUhSRXIybjBVPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTXdha05EUVd4bFowRjNTVUpCWjBsVll6UnZaa2RhV1VseFNFTXZhVzB4WTBKUFEwRlhiazlCUVVRNGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcE5kMDVxUlhsTmFrVjVUbFJOTWxkb1kwNU5hazEzVG1wRmVVMXFSWHBPVkUweVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ6VUdkMmIyazBiM1p5TjNkTFJXeHRSa1IwUjJWcVpIQndUWEZFTWtadGMydEhRMkVLVUZOTE5sVlNSVWxoUTNoMlExTnJSbE53UW5FMWJtTmhkMGxzY1d0bk1WQm5LeTlzTUhoaGNERXhkMGhyT1dwbE5FdFBRMEZZV1hkblowWjVUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZCTmtJMUNtRTRUWGRqUzBNNFVGZE1OamM0VUdGM04wRlRZM1JqZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsUldVUldVakJTUVZGSUwwSkNZM2RHV1VWVVl6Tk9hbUZJU25aWk1uUkJXakk1ZGxveWVHeE1iVTUyWWxSQmMwSm5iM0pDWjBWRlFWbFBMd3BOUVVWQ1FrSTFiMlJJVW5kamVtOTJUREprY0dSSGFERlphVFZxWWpJd2RtSkhPVzVoVnpSMllqSkdNV1JIWjNkTVoxbExTM2RaUWtKQlIwUjJla0ZDQ2tOQlVXZEVRalZ2WkVoU2QyTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZa2M1Ym1GWE5IWmlNa1l4WkVkbmQyZFphMGREYVhOSFFWRlJRakZ1YTBNS1FrRkpSV1YzVWpWQlNHTkJaRkZFWkZCVVFuRjRjMk5TVFcxTldraG9lVnBhZW1ORGIydHdaWFZPTkRoeVppdElhVzVMUVV4NWJuVnFaMEZCUVZscGVBcG5RVWwzUVVGQlJVRjNRa2ROUlZGRFNVSlROM2xFT0VSVlVUTjJiM1JuUlhGQ1p6aFhla0ZxYm1Ga05qSkdSVmd2WlhaQ1VrTm5aVGRtZVdwQmFVSkVDa1pzZUc4dk9DOU9WV052TjNWUlNrTlNhemdyYkRVdlFYTjVkRzFqTlU1dkwzbDBPVzl0WWtnNWVrRkxRbWRuY1docmFrOVFVVkZFUVhkT2NFRkVRbTBLUVdwRlFXaGpUMWhCU21OeVdHb3ZXbmxUWWk5RFlVWTRhbGRTY2tFNGJrdGhSV2xsUmtSRVZGSTBkRmhLYWtrMmJWRTBaRU0yUjA1bVdVOHhkblJwTVFwRFVVMXBRV3BGUVc5UFdVNDRkblJET0V0NWIzQldSM0YxTWtVeGFISnVXRmxDVVhKVUsxSTRlRk41T0VaUk1ITlRRVmhHWXpVMGFHTTBTMlpQZW10aENsSklWWFpsVVVaU0NpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19","integratedTime":1686605136,"logIndex":23548006,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}}}
1 change: 1 addition & 0 deletions signing/testdata/invalid-cosign.bundle
@@ -0,0 +1 @@
{"base64Signature":"MEUCIQD4rAvIUYt0WgrXVL6whlkgJerX2jyRNDct3AwWSsGdJgIgP0DCR56AM9FQD/aEnZwnNT1s22V8PW/ud0YHREr2n0U=","cert":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMwakNDQWxlZ0F3SUJBZ0lVYzRvZkdaWUlxSEMvaW0xY0JPQ0FXbk9BQUQ4d0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpNd05qRXlNakV5TlRNMldoY05Nak13TmpFeU1qRXpOVE0yV2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVzUGd2b2k0b3ZyN3dLRWxtRkR0R2VqZHBwTXFEMkZtc2tHQ2EKUFNLNlVSRUlhQ3h2Q1NrRlNwQnE1bmNhd0lscWtnMVBnKy9sMHhhcDExd0hrOWplNEtPQ0FYWXdnZ0Z5TUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVBNkI1CmE4TXdjS0M4UFdMNjc4UGF3N0FTY3Rjd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d0lRWURWUjBSQVFIL0JCY3dGWUVUYzNOamFISnZZMnRBWjI5dloyeGxMbU52YlRBc0Jnb3JCZ0VFQVlPLwpNQUVCQkI1b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdmJHOW5hVzR2YjJGMWRHZ3dMZ1lLS3dZQkJBR0R2ekFCCkNBUWdEQjVvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2Ykc5bmFXNHZiMkYxZEdnd2dZa0dDaXNHQVFRQjFua0MKQkFJRWV3UjVBSGNBZFFEZFBUQnF4c2NSTW1NWkhoeVpaemNDb2twZXVONDhyZitIaW5LQUx5bnVqZ0FBQVlpeApnQUl3QUFBRUF3QkdNRVFDSUJTN3lEOERVUTN2b3RnRXFCZzhXekFqbmFkNjJGRVgvZXZCUkNnZTdmeWpBaUJECkZseG8vOC9OVWNvN3VRSkNSazgrbDUvQXN5dG1jNU5vL3l0OW9tYkg5ekFLQmdncWhrak9QUVFEQXdOcEFEQm0KQWpFQWhjT1hBSmNyWGovWnlTYi9DYUY4aldSckE4bkthRWllRkREVFI0dFhKakk2bVE0ZEM2R05mWU8xdnRpMQpDUU1pQWpFQW9PWU44dnRDOEt5b3BWR3F1MkUxaHJuWFlCUXJUK1I4eFN5OEZRMHNTQVhGYzU0aGM0S2ZPemthClJIVXZlUUZSCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"}

0 comments on commit 33bb591

Please sign in to comment.