Skip to content

Commit

Permalink
refactor verifier workflow
Browse files Browse the repository at this point in the history
Signed-off-by: linus-sun <[email protected]>
  • Loading branch information
linus-sun committed Nov 1, 2024
1 parent c8635a5 commit 15d9ce3
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/reusable_monitoring.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
run: cat ${{ env.LOG_FILE }}
# Skip on first run
continue-on-error: true
- run: go run ./cmd/verifier --file ${{ env.LOG_FILE }} --once --monitored-values "${{ inputs.identities }}" --user-agent "${{ format('{0}/{1}/{2}', needs.detect-workflow.outputs.repository, needs.detect-workflow.outputs.ref, github.run_id) }}"
- run: go run ./cmd/rekor_consistency --file ${{ env.LOG_FILE }} --once --monitored-values "${{ inputs.identities }}" --user-agent "${{ format('{0}/{1}/{2}', needs.detect-workflow.outputs.repository, needs.detect-workflow.outputs.ref, github.run_id) }}"
- name: Upload checkpoint
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
Expand Down
43 changes: 30 additions & 13 deletions cmd/verifier/main.go → cmd/rekor_consistency/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"flag"
"fmt"
"log"
"os"
"runtime"
"strings"
"time"
Expand Down Expand Up @@ -55,6 +56,16 @@ func main() {
userAgentString := flag.String("user-agent", "", "details to include in the user agent string")
flag.Parse()

rekorClient, err := client.GetRekorClient(*serverURL, client.WithUserAgent(strings.TrimSpace(fmt.Sprintf("rekor-monitor/%s (%s; %s) %s", version.GetVersionInfo().GitVersion, runtime.GOOS, runtime.GOARCH, *userAgentString))))
if err != nil {
log.Fatalf("getting Rekor client: %v", err)
}

verifier, err := rekor.GetLogVerifier(context.Background(), rekorClient)
if err != nil {
log.Fatal(err)
}

var monitoredVals identity.MonitoredValues
if err := yaml.Unmarshal([]byte(*monitoredValsInput), &monitoredVals); err != nil {
log.Fatalf("error parsing identities: %v", err)
Expand All @@ -73,23 +84,29 @@ func main() {
fmt.Printf("Monitoring subject %s\n", sub)
}

rekorClient, err := client.GetRekorClient(*serverURL, client.WithUserAgent(strings.TrimSpace(fmt.Sprintf("rekor-monitor/%s (%s; %s) %s", version.GetVersionInfo().GitVersion, runtime.GOOS, runtime.GOARCH, *userAgentString))))
if err != nil {
log.Fatalf("getting Rekor client: %v", err)
}

verifier, err := rekor.GetLogVerifier(context.Background(), rekorClient)
if err != nil {
log.Fatal(err)
}

err = rekor.VerifyConsistencyCheckInputs(interval, logInfoFile, outputIdentitiesFile, once)
if err != nil {
log.Fatal(err)
}

err = rekor.RunConsistencyCheck(*interval, rekorClient, verifier, *logInfoFile, monitoredVals, *outputIdentitiesFile, *once)
if err != nil {
log.Fatalf("%v", err)
ticker := time.NewTicker(*interval)
defer ticker.Stop()

// Loop will:
// 1. Fetch latest checkpoint and verify
// 2. If old checkpoint is present, verify consistency proof
// 3. Write latest checkpoint to file

// To get an immediate first tick
for ; ; <-ticker.C {
err = rekor.RunConsistencyCheck(rekorClient, verifier, *logInfoFile, monitoredVals, *outputIdentitiesFile)
if err != nil {
fmt.Fprintf(os.Stderr, "error running consistency check: %v", err)
return
}

if *once {
return
}
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/sigstore/sigstore v1.8.10
github.com/wneessen/go-mail v0.5.1
golang.org/x/mod v0.21.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
sigs.k8s.io/release-utils v0.8.5
)
Expand Down Expand Up @@ -108,6 +109,5 @@ require (
golang.org/x/time v0.5.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
83 changes: 35 additions & 48 deletions pkg/rekor/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,62 +111,49 @@ func VerifyConsistencyCheckInputs(interval *time.Duration, logInfoFile *string,
}

// RunConsistencyCheck periodically verifies the root hash consistency of a Rekor log.
func RunConsistencyCheck(interval time.Duration, rekorClient *client.Rekor, verifier signature.Verifier, logInfoFile string, mvs identity.MonitoredValues, outputIdentitiesFile string, once bool) error {
ticker := time.NewTicker(interval)
defer ticker.Stop()

// Loop will:
// 1. Fetch latest checkpoint and verify
// 2. If old checkpoint is present, verify consistency proof
// 3. Write latest checkpoint to file
func RunConsistencyCheck(rekorClient *client.Rekor, verifier signature.Verifier, logInfoFile string, mvs identity.MonitoredValues, outputIdentitiesFile string) error {
logInfo, err := GetLogInfo(context.Background(), rekorClient)
if err != nil {
return fmt.Errorf("failed to get log info: %v", err)
}
checkpoint, err := verifyLatestCheckpointSignature(logInfo, verifier)
if err != nil {
return fmt.Errorf("failed to verify signature of latest checkpoint: %v", err)
}

// To get an immediate first tick
for ; ; <-ticker.C {
logInfo, err := GetLogInfo(context.Background(), rekorClient)
if err != nil {
return fmt.Errorf("failed to get log info: %v", err)
}
checkpoint, err := verifyLatestCheckpointSignature(logInfo, verifier)
fi, err := os.Stat(logInfoFile)
// File containing previous checkpoints exists
var prevCheckpoint *util.SignedCheckpoint
if err == nil && fi.Size() != 0 {
prevCheckpoint, err = verifyCheckpointConsistency(logInfoFile, checkpoint, *logInfo.TreeID, rekorClient, verifier)
if err != nil {
return fmt.Errorf("failed to verify signature of latest checkpoint: %v", err)
return fmt.Errorf("failed to verify previous checkpoint: %v", err)
}

fi, err := os.Stat(logInfoFile)
// File containing previous checkpoints exists
var prevCheckpoint *util.SignedCheckpoint
if err == nil && fi.Size() != 0 {
prevCheckpoint, err = verifyCheckpointConsistency(logInfoFile, checkpoint, *logInfo.TreeID, rekorClient, verifier)
if err != nil {
return fmt.Errorf("failed to verify previous checkpoint: %v", err)
}

}

// Write if there was no stored checkpoint or the sizes differ
if prevCheckpoint == nil || prevCheckpoint.Size != checkpoint.Size {
if err := file.WriteCheckpoint(checkpoint, logInfoFile); err != nil {
// TODO: Once the consistency check and identity search are split into separate tasks, this should hard fail.
// Temporarily skipping this to allow this job to succeed, remediating the issue noted here: https://github.com/sigstore/rekor-monitor/issues/271
fmt.Fprintf(os.Stderr, "failed to write checkpoint: %v", err)
}
}
}

if prevCheckpoint != nil && prevCheckpoint.Size != checkpoint.Size {
err = writeIdentitiesBetweenCheckpoints(logInfo, prevCheckpoint, checkpoint, mvs, rekorClient, outputIdentitiesFile)
if err != nil {
return fmt.Errorf("failed to monitor identities: %v", err)
}
// Write if there was no stored checkpoint or the sizes differ
if prevCheckpoint == nil || prevCheckpoint.Size != checkpoint.Size {
if err := file.WriteCheckpoint(checkpoint, logInfoFile); err != nil {
// TODO: Once the consistency check and identity search are split into separate tasks, this should hard fail.
// Temporarily skipping this to allow this job to succeed, remediating the issue noted here: https://github.com/sigstore/rekor-monitor/issues/271
fmt.Fprintf(os.Stderr, "failed to write checkpoint: %v", err)
}
}

// TODO: Switch to writing checkpoints to GitHub so that the history is preserved. Then we only need
// to persist the last checkpoint.
// Delete old checkpoints to avoid the log growing indefinitely
if err := file.DeleteOldCheckpoints(logInfoFile); err != nil {
return fmt.Errorf("failed to delete old checkpoints: %v", err)
if prevCheckpoint != nil && prevCheckpoint.Size != checkpoint.Size {
err = writeIdentitiesBetweenCheckpoints(logInfo, prevCheckpoint, checkpoint, mvs, rekorClient, outputIdentitiesFile)
if err != nil {
return fmt.Errorf("failed to monitor identities: %v", err)
}
}

if once {
return nil
}
// TODO: Switch to writing checkpoints to GitHub so that the history is preserved. Then we only need
// to persist the last checkpoint.
// Delete old checkpoints to avoid the log growing indefinitely
if err := file.DeleteOldCheckpoints(logInfoFile); err != nil {
return fmt.Errorf("failed to delete old checkpoints: %v", err)
}

return nil
}
8 changes: 2 additions & 6 deletions pkg/test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"runtime"
"strings"
"testing"
"time"

"github.com/sigstore/rekor-monitor/pkg/fulcio/extensions"
"github.com/sigstore/rekor-monitor/pkg/identity"
Expand Down Expand Up @@ -148,8 +147,6 @@ func TestRunConsistencyCheck(t *testing.T) {
tempOutputIdentitiesFileName := tempOutputIdentitiesFile.Name()
defer os.Remove(tempOutputIdentitiesFileName)

interval := time.Minute

monitoredVals := identity.MonitoredValues{
Subjects: []string{subject},
CertificateIdentities: []identity.CertificateIdentity{
Expand All @@ -168,9 +165,8 @@ func TestRunConsistencyCheck(t *testing.T) {
certFingerprint,
},
}
once := true

err = rekor.RunConsistencyCheck(interval, rekorClient, verifier, tempLogInfoFileName, monitoredVals, tempOutputIdentitiesFileName, once)
err = rekor.RunConsistencyCheck(rekorClient, verifier, tempLogInfoFileName, monitoredVals, tempOutputIdentitiesFileName)
if err != nil {
t.Errorf("first consistency check failed: %v", err)
}
Expand Down Expand Up @@ -210,7 +206,7 @@ func TestRunConsistencyCheck(t *testing.T) {
t.Errorf("expected checkpoint size of 2, received size %d", checkpoint.Size)
}

err = rekor.RunConsistencyCheck(interval, rekorClient, verifier, tempLogInfoFileName, monitoredVals, tempOutputIdentitiesFileName, once)
err = rekor.RunConsistencyCheck(rekorClient, verifier, tempLogInfoFileName, monitoredVals, tempOutputIdentitiesFileName)
if err != nil {
t.Errorf("second consistency check failed: %v", err)
}
Expand Down

0 comments on commit 15d9ce3

Please sign in to comment.