From 9f5c5d13c4d8dc9590ef7c317d442e09b7ed7b72 Mon Sep 17 00:00:00 2001 From: linus-sun Date: Tue, 8 Oct 2024 21:53:24 +0000 Subject: [PATCH 1/4] refactor helper verification methods out, move consistency check into verification pkg Signed-off-by: linus-sun --- cmd/verifier/main.go | 106 +----------------- pkg/rekor/verifier.go | 124 +++++++++++++++++++++ {cmd/verifier => pkg/test/e2e}/e2e_test.go | 4 +- {cmd/verifier => pkg/test/e2e}/e2e_test.sh | 2 +- 4 files changed, 128 insertions(+), 108 deletions(-) rename {cmd/verifier => pkg/test/e2e}/e2e_test.go (96%) rename {cmd/verifier => pkg/test/e2e}/e2e_test.sh (97%) diff --git a/cmd/verifier/main.go b/cmd/verifier/main.go index 6c128d3d..f9ddcaf2 100644 --- a/cmd/verifier/main.go +++ b/cmd/verifier/main.go @@ -17,23 +17,16 @@ package main import ( "context" - "encoding/hex" "flag" "fmt" "log" - "os" "runtime" "strings" "time" "github.com/sigstore/rekor-monitor/pkg/identity" "github.com/sigstore/rekor-monitor/pkg/rekor" - "github.com/sigstore/rekor-monitor/pkg/util/file" "github.com/sigstore/rekor/pkg/client" - gclient "github.com/sigstore/rekor/pkg/generated/client" - "github.com/sigstore/rekor/pkg/util" - "github.com/sigstore/rekor/pkg/verify" - "github.com/sigstore/sigstore/pkg/signature" "gopkg.in/yaml.v3" "sigs.k8s.io/release-utils/version" @@ -46,103 +39,6 @@ const ( outputIdentitiesFileName = "identities.txt" ) -// runConsistencyCheck periodically verifies the root hash consistency of a Rekor log. -func RunConsistencyCheck(interval *time.Duration, rekorClient *gclient.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 - - // To get an immediate first tick - for ; ; <-ticker.C { - logInfo, err := rekor.GetLogInfo(context.Background(), rekorClient) - if err != nil { - return fmt.Errorf("getting log info: %v", err) - } - checkpoint := &util.SignedCheckpoint{} - if err := checkpoint.UnmarshalText([]byte(*logInfo.SignedTreeHead)); err != nil { - return fmt.Errorf("unmarshalling logInfo.SignedTreeHead to Checkpoint: %v", err) - } - if !checkpoint.Verify(verifier) { - return fmt.Errorf("verifying checkpoint (size %d, hash %s) failed", checkpoint.Size, hex.EncodeToString(checkpoint.Hash)) - } - - fi, err := os.Stat(*logInfoFile) - var prevCheckpoint *util.SignedCheckpoint - if err == nil && fi.Size() != 0 { - // File containing previous checkpoints exists - prevCheckpoint, err = file.ReadLatestCheckpoint(*logInfoFile) - if err != nil { - return fmt.Errorf("reading checkpoint log: %v", err) - } - if !prevCheckpoint.Verify(verifier) { - return fmt.Errorf("verifying checkpoint (size %d, hash %s) failed", checkpoint.Size, hex.EncodeToString(checkpoint.Hash)) - } - } - if prevCheckpoint != nil { - if err := verify.ProveConsistency(context.Background(), rekorClient, prevCheckpoint, checkpoint, *logInfo.TreeID); err != nil { - return fmt.Errorf("failed to verify log consistency: %v", err) - } - fmt.Fprintf(os.Stderr, "Root hash consistency verified - Current Size: %d Root Hash: %s - Previous Size: %d Root Hash %s\n", - checkpoint.Size, hex.EncodeToString(checkpoint.Hash), prevCheckpoint.Size, hex.EncodeToString(prevCheckpoint.Hash)) - } - - // 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 { - return fmt.Errorf("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) - } - - // Look for identities if there was a previous, different checkpoint - if prevCheckpoint != nil && prevCheckpoint.Size != checkpoint.Size { - // Get log size of inactive shards - totalSize := 0 - for _, s := range logInfo.InactiveShards { - totalSize += int(*s.TreeSize) - } - startIndex := int(prevCheckpoint.Size) + totalSize - 1 //nolint: gosec // G115, log will never be large enough to overflow - endIndex := int(checkpoint.Size) + totalSize - 1 //nolint: gosec // G115 - - // Search for identities in the log range - if len(mvs.CertificateIdentities) > 0 || len(mvs.Fingerprints) > 0 || len(mvs.Subjects) > 0 { - entries, err := rekor.GetEntriesByIndexRange(context.Background(), rekorClient, startIndex, endIndex) - if err != nil { - return fmt.Errorf("error getting entries by index range: %v", err) - } - idEntries, err := rekor.MatchedIndices(entries, mvs) - if err != nil { - return fmt.Errorf("error finding log indices: %v", err) - } - - if len(idEntries) > 0 { - for _, idEntry := range idEntries { - fmt.Fprintf(os.Stderr, "Found %s\n", idEntry.String()) - - if err := file.WriteIdentity(*outputIdentitiesFile, idEntry); err != nil { - return fmt.Errorf("failed to write entry: %v", err) - } - } - } - } - } - - if *once { - return nil - } - } -} - // This main function performs a periodic root hash consistency check. // Upon starting, any existing latest snapshot data is loaded and the function runs // indefinitely to perform consistency check for every time interval that was specified. @@ -187,7 +83,7 @@ func main() { log.Fatal(err) } - err = RunConsistencyCheck(interval, rekorClient, verifier, logInfoFile, monitoredVals, outputIdentitiesFile, once) + err = rekor.RunConsistencyCheck(interval, rekorClient, verifier, logInfoFile, monitoredVals, outputIdentitiesFile, once) if err != nil { log.Fatalf("%v", err) } diff --git a/pkg/rekor/verifier.go b/pkg/rekor/verifier.go index 2ab014f3..69f25aad 100644 --- a/pkg/rekor/verifier.go +++ b/pkg/rekor/verifier.go @@ -17,8 +17,17 @@ package rekor import ( "context" "crypto" + "encoding/hex" + "fmt" + "os" + "time" + "github.com/sigstore/rekor-monitor/pkg/identity" + "github.com/sigstore/rekor-monitor/pkg/util/file" "github.com/sigstore/rekor/pkg/generated/client" + "github.com/sigstore/rekor/pkg/generated/models" + "github.com/sigstore/rekor/pkg/util" + "github.com/sigstore/rekor/pkg/verify" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" ) @@ -40,3 +49,118 @@ func GetLogVerifier(ctx context.Context, rekorClient *client.Rekor) (signature.V } return verifier, nil } + +// verifyLatestCheckpoint fetches and verifies the signature of the latest checkpoint from log info fetched from Rekor. +// If it successfully verifies the checkpoint's signature, it returns the checkpoint; otherwise, it returns an error. +func verifyLatestCheckpointSignature(logInfo *models.LogInfo, verifier signature.Verifier) (*util.SignedCheckpoint, error) { + checkpoint := &util.SignedCheckpoint{} + if err := checkpoint.UnmarshalText([]byte(*logInfo.SignedTreeHead)); err != nil { + return nil, fmt.Errorf("unmarshalling logInfo.SignedTreeHead to Checkpoint: %v", err) + } + if !checkpoint.Verify(verifier) { + return nil, fmt.Errorf("verifying checkpoint (size %d, hash %s) failed", checkpoint.Size, hex.EncodeToString(checkpoint.Hash)) + } + return checkpoint, nil +} + +// verifyCheckpointConsistency reads and verifies the consistency of the previous latest checkpoint from a log info file against the current up-to-date checkpoint. +// If it successfully fetches and verifies the consistency between these two checkpoints, it returns the previous checkpoint; otherwise, it returns an error. +func verifyCheckpointConsistency(logInfoFile *string, checkpoint *util.SignedCheckpoint, treeID string, rekorClient *client.Rekor, verifier signature.Verifier) (*util.SignedCheckpoint, error) { + var prevCheckpoint *util.SignedCheckpoint + prevCheckpoint, err := file.ReadLatestCheckpoint(*logInfoFile) + if err != nil { + return nil, fmt.Errorf("reading checkpoint log: %v", err) + } + if !prevCheckpoint.Verify(verifier) { + return nil, fmt.Errorf("verifying checkpoint (size %d, hash %s) failed", checkpoint.Size, hex.EncodeToString(checkpoint.Hash)) + } + if err := verify.ProveConsistency(context.Background(), rekorClient, prevCheckpoint, checkpoint, treeID); err != nil { + return nil, fmt.Errorf("failed to verify log consistency: %v", err) + } + fmt.Fprintf(os.Stderr, "Root hash consistency verified - Current Size: %d Root Hash: %s - Previous Size: %d Root Hash %s\n", + checkpoint.Size, hex.EncodeToString(checkpoint.Hash), prevCheckpoint.Size, hex.EncodeToString(prevCheckpoint.Hash)) + return prevCheckpoint, nil +} + +// 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 + + // 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) + if err != nil { + return fmt.Errorf("failed to verify signature of latest 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 { + return fmt.Errorf("failed to write checkpoint: %v", err) + } + } + + if prevCheckpoint != nil && prevCheckpoint.Size != checkpoint.Size { + // Get log size of inactive shards + totalSize := 0 + for _, s := range logInfo.InactiveShards { + totalSize += int(*s.TreeSize) + } + startIndex := int(prevCheckpoint.Size) + totalSize - 1 //nolint: gosec // G115, log will never be large enough to overflow + endIndex := int(checkpoint.Size) + totalSize - 1 //nolint: gosec // G115 + + // Search for identities in the log range + if len(mvs.CertificateIdentities) > 0 || len(mvs.Fingerprints) > 0 || len(mvs.Subjects) > 0 { + entries, err := GetEntriesByIndexRange(context.Background(), rekorClient, startIndex, endIndex) + if err != nil { + return fmt.Errorf("error getting entries by index range: %v", err) + } + idEntries, err := MatchedIndices(entries, mvs) + if err != nil { + return fmt.Errorf("error finding log indices: %v", err) + } + + if len(idEntries) > 0 { + for _, idEntry := range idEntries { + fmt.Fprintf(os.Stderr, "Found %s\n", idEntry.String()) + + if err := file.WriteIdentity(*outputIdentitiesFile, idEntry); err != nil { + return fmt.Errorf("failed to write entry: %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 *once { + return nil + } + } +} diff --git a/cmd/verifier/e2e_test.go b/pkg/test/e2e/e2e_test.go similarity index 96% rename from cmd/verifier/e2e_test.go rename to pkg/test/e2e/e2e_test.go index dbe327a7..7e83d4d6 100755 --- a/cmd/verifier/e2e_test.go +++ b/pkg/test/e2e/e2e_test.go @@ -168,7 +168,7 @@ func TestRunConsistencyCheck(t *testing.T) { } once := true - err = RunConsistencyCheck(&interval, rekorClient, verifier, &tempLogInfoFileName, monitoredVals, &tempOutputIdentitiesFileName, &once) + err = rekor.RunConsistencyCheck(&interval, rekorClient, verifier, &tempLogInfoFileName, monitoredVals, &tempOutputIdentitiesFileName, &once) if err != nil { t.Errorf("first consistency check failed: %v", err) } @@ -208,7 +208,7 @@ func TestRunConsistencyCheck(t *testing.T) { t.Errorf("expected checkpoint size of 2, received size %d", checkpoint.Size) } - err = RunConsistencyCheck(&interval, rekorClient, verifier, &tempLogInfoFileName, monitoredVals, &tempOutputIdentitiesFileName, &once) + err = rekor.RunConsistencyCheck(&interval, rekorClient, verifier, &tempLogInfoFileName, monitoredVals, &tempOutputIdentitiesFileName, &once) if err != nil { t.Errorf("second consistency check failed: %v", err) } diff --git a/cmd/verifier/e2e_test.sh b/pkg/test/e2e/e2e_test.sh similarity index 97% rename from cmd/verifier/e2e_test.sh rename to pkg/test/e2e/e2e_test.sh index d4879d14..46e86b13 100755 --- a/cmd/verifier/e2e_test.sh +++ b/pkg/test/e2e/e2e_test.sh @@ -66,4 +66,4 @@ echo echo "running tests" popd -go test -tags=e2e -v -race ./cmd/verifier/... \ No newline at end of file +go test -tags=e2e -v -race ./pkg/test/e2e/... \ No newline at end of file From 21f7300b53841054684ece3bb6876f2ee4321827 Mon Sep 17 00:00:00 2001 From: linus-sun Date: Thu, 10 Oct 2024 20:06:02 +0000 Subject: [PATCH 2/4] add e2e test to ci Signed-off-by: linus-sun --- .github/workflows/main.yml | 27 +++++++++++++++++++++++++++ pkg/test/e2e/e2e_test.go | 6 ++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 053f35fb..145bcd1e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,3 +63,30 @@ jobs: - name: Run Go tests w/ `-race` if: ${{ runner.os == 'Linux' }} run: go test -race $(go list ./... | grep -v third_party/) + e2e-tests: + name: Run end-to-end tests + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + # https://github.com/mvdan/github-actions-golang#how-do-i-set-up-caching-between-builds + - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + with: + # In order: + # * Module download cache + # * Build cache (Linux) + path: | + ~/go/pkg/mod + ~/.cache/go-build + ~/Library/Caches/go-build + %LocalAppData%\go-build + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 + with: + go-version-file: './go.mod' + check-latest: true + - name: run e2e test + run: ./pkg/test/e2e/e2e_test.sh + diff --git a/pkg/test/e2e/e2e_test.go b/pkg/test/e2e/e2e_test.go index 7e83d4d6..78d0a5c8 100755 --- a/pkg/test/e2e/e2e_test.go +++ b/pkg/test/e2e/e2e_test.go @@ -12,7 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package main +//go:build e2e +// +build e2e + +package e2e import ( "bytes" @@ -56,7 +59,6 @@ const ( // Check that Rekor-monitor reusable monitoring workflow successfully verifies consistency of the log checkpoint // and is able to find a monitored identity within the checkpoint indices and write it to file. func TestRunConsistencyCheck(t *testing.T) { - t.Skip("skipping test outside of being run from e2e_test.sh") rekorClient, err := client.GetRekorClient(rekorURL, client.WithUserAgent(strings.TrimSpace(fmt.Sprintf("rekor-monitor/%s (%s; %s)", version.GetVersionInfo().GitVersion, runtime.GOOS, runtime.GOARCH)))) if err != nil { log.Fatalf("getting Rekor client: %v", err) From 913bd375f848a6b3b72d3af64748fc671f2d67a0 Mon Sep 17 00:00:00 2001 From: linus-sun Date: Mon, 14 Oct 2024 18:58:35 +0000 Subject: [PATCH 3/4] add TODO to string/flag consistency check Signed-off-by: linus-sun --- .github/workflows/main.yml | 1 + pkg/rekor/verifier.go | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 145bcd1e..8acc7150 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,6 +63,7 @@ jobs: - name: Run Go tests w/ `-race` if: ${{ runner.os == 'Linux' }} run: go test -race $(go list ./... | grep -v third_party/) + e2e-tests: name: Run end-to-end tests runs-on: ubuntu-latest diff --git a/pkg/rekor/verifier.go b/pkg/rekor/verifier.go index 69f25aad..222a3a47 100644 --- a/pkg/rekor/verifier.go +++ b/pkg/rekor/verifier.go @@ -83,6 +83,7 @@ func verifyCheckpointConsistency(logInfoFile *string, checkpoint *util.SignedChe } // RunConsistencyCheck periodically verifies the root hash consistency of a Rekor log. +// TODO: RunConsistencyCheck should take in string/bool flags directly instead of pointers and check that flags are being set correctly. 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() @@ -102,6 +103,7 @@ func RunConsistencyCheck(interval *time.Duration, rekorClient *client.Rekor, ver if err != nil { return fmt.Errorf("failed to verify signature of latest checkpoint: %v", err) } + fi, err := os.Stat(*logInfoFile) // File containing previous checkpoints exists var prevCheckpoint *util.SignedCheckpoint From 1a3652ae2015d2778a65959e6c7489f50e83d93e Mon Sep 17 00:00:00 2001 From: linus-sun Date: Thu, 10 Oct 2024 22:12:25 +0000 Subject: [PATCH 4/4] refactor out identity search into separate func Signed-off-by: linus-sun --- pkg/rekor/identity.go | 39 +++++++++++++++++++++++++++++++++++++++ pkg/rekor/verifier.go | 35 ++++++----------------------------- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/pkg/rekor/identity.go b/pkg/rekor/identity.go index 4f09b550..3b443205 100644 --- a/pkg/rekor/identity.go +++ b/pkg/rekor/identity.go @@ -16,19 +16,24 @@ package rekor import ( "bytes" + "context" "crypto/x509" "encoding/asn1" "encoding/base64" "errors" "fmt" + "os" "regexp" "github.com/go-openapi/runtime" "github.com/sigstore/rekor-monitor/pkg/fulcio/extensions" "github.com/sigstore/rekor-monitor/pkg/identity" + "github.com/sigstore/rekor-monitor/pkg/util/file" + "github.com/sigstore/rekor/pkg/generated/client" "github.com/sigstore/rekor/pkg/generated/models" "github.com/sigstore/rekor/pkg/pki" "github.com/sigstore/rekor/pkg/types" + "github.com/sigstore/rekor/pkg/util" "github.com/sigstore/sigstore/pkg/cryptoutils" // required imports to call init methods @@ -335,3 +340,37 @@ func oidMatchesPolicy(cert *x509.Certificate, oid asn1.ObjectIdentifier, extensi return false, nil, "", nil } + +// writeIdentitiesBetweenCheckpoints monitors for given identities between two checkpoints and writes any found identities to file. +func writeIdentitiesBetweenCheckpoints(logInfo *models.LogInfo, prevCheckpoint *util.SignedCheckpoint, checkpoint *util.SignedCheckpoint, monitoredValues identity.MonitoredValues, rekorClient *client.Rekor, outputIdentitiesFile *string) error { + // Get log size of inactive shards + totalSize := 0 + for _, s := range logInfo.InactiveShards { + totalSize += int(*s.TreeSize) + } + startIndex := int(prevCheckpoint.Size) + totalSize - 1 //nolint: gosec // G115, log will never be large enough to overflow + endIndex := int(checkpoint.Size) + totalSize - 1 //nolint: gosec // G115 + + // Search for identities in the log range + if len(monitoredValues.CertificateIdentities) > 0 || len(monitoredValues.Fingerprints) > 0 || len(monitoredValues.Subjects) > 0 || len(monitoredValues.OIDMatchers) > 0 { + entries, err := GetEntriesByIndexRange(context.Background(), rekorClient, startIndex, endIndex) + if err != nil { + return fmt.Errorf("error getting entries by index range: %v", err) + } + idEntries, err := MatchedIndices(entries, monitoredValues) + if err != nil { + return fmt.Errorf("error finding log indices: %v", err) + } + + if len(idEntries) > 0 { + for _, idEntry := range idEntries { + fmt.Fprintf(os.Stderr, "Found %s\n", idEntry.String()) + + if err := file.WriteIdentity(*outputIdentitiesFile, idEntry); err != nil { + return fmt.Errorf("failed to write entry: %v", err) + } + } + } + } + return nil +} diff --git a/pkg/rekor/verifier.go b/pkg/rekor/verifier.go index 222a3a47..4d5cb26c 100644 --- a/pkg/rekor/verifier.go +++ b/pkg/rekor/verifier.go @@ -118,39 +118,16 @@ func RunConsistencyCheck(interval *time.Duration, rekorClient *client.Rekor, ver // 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 { - return fmt.Errorf("failed to write checkpoint: %v", err) + // 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 { - // Get log size of inactive shards - totalSize := 0 - for _, s := range logInfo.InactiveShards { - totalSize += int(*s.TreeSize) - } - startIndex := int(prevCheckpoint.Size) + totalSize - 1 //nolint: gosec // G115, log will never be large enough to overflow - endIndex := int(checkpoint.Size) + totalSize - 1 //nolint: gosec // G115 - - // Search for identities in the log range - if len(mvs.CertificateIdentities) > 0 || len(mvs.Fingerprints) > 0 || len(mvs.Subjects) > 0 { - entries, err := GetEntriesByIndexRange(context.Background(), rekorClient, startIndex, endIndex) - if err != nil { - return fmt.Errorf("error getting entries by index range: %v", err) - } - idEntries, err := MatchedIndices(entries, mvs) - if err != nil { - return fmt.Errorf("error finding log indices: %v", err) - } - - if len(idEntries) > 0 { - for _, idEntry := range idEntries { - fmt.Fprintf(os.Stderr, "Found %s\n", idEntry.String()) - - if err := file.WriteIdentity(*outputIdentitiesFile, idEntry); err != nil { - return fmt.Errorf("failed to write entry: %v", err) - } - } - } + err = writeIdentitiesBetweenCheckpoints(logInfo, prevCheckpoint, checkpoint, mvs, rekorClient, outputIdentitiesFile) + if err != nil { + return fmt.Errorf("failed to monitor identities: %v", err) } }