Skip to content

Commit 014cfb1

Browse files
bobcallawaycpanato
authored andcommitted
add mysql indexstorage backend
Signed-off-by: Bob Callaway <[email protected]>
1 parent 0394bf7 commit 014cfb1

File tree

15 files changed

+363
-39
lines changed

15 files changed

+363
-39
lines changed

cmd/rekor-server/app/root.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ Memory and file-based signers should only be used for testing.`)
110110
rootCmd.PersistentFlags().Bool("enable_retrieve_api", true, "enables Redis-based index API endpoint")
111111
_ = rootCmd.PersistentFlags().MarkDeprecated("enable_retrieve_api", "this flag is deprecated in favor of enabled_api_endpoints (searchIndex)")
112112
rootCmd.PersistentFlags().String("search_index.storage_provider", "redis",
113-
`Index Storage provider to use. Valid options are: [redis].`)
113+
`Index Storage provider to use. Valid options are: [redis, mysql].`)
114114
rootCmd.PersistentFlags().String("redis_server.address", "127.0.0.1", "Redis server address")
115115
rootCmd.PersistentFlags().Uint16("redis_server.port", 6379, "Redis server port")
116116
rootCmd.PersistentFlags().String("redis_server.password", "", "Redis server password")
@@ -125,6 +125,12 @@ Memory and file-based signers should only be used for testing.`)
125125
rootCmd.PersistentFlags().Uint64("max_jar_metadata_size", 1048576, "maximum permitted size for jar META-INF/ files, in bytes; set to 0 for unlimited")
126126
rootCmd.PersistentFlags().Uint64("max_apk_metadata_size", 1048576, "maximum permitted size for apk .SIGN and .PKGINFO files, in bytes; set to 0 for unlimited")
127127

128+
rootCmd.PersistentFlags().String("search_index.mysql.dsn", "", "DSN for index storage using MySQL")
129+
rootCmd.PersistentFlags().Duration("search_index.mysql.conn_max_idletime", 0*time.Second, "maximum connection idle time")
130+
rootCmd.PersistentFlags().Duration("search_index.mysql.conn_max_lifetime", 0*time.Second, "maximum connection lifetime")
131+
rootCmd.PersistentFlags().Int("search_index.mysql.max_open_connections", 0, "maximum open connections")
132+
rootCmd.PersistentFlags().Int("search_index.mysql.max_idle_connections", 0, "maximum idle connections")
133+
128134
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
129135
log.Logger.Fatal(err)
130136
}

docker-compose.test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@ services:
3838
"--max_request_body_size=32792576",
3939
"--rekor_server.new_entry_publisher=gcppubsub://projects/test-project/topics/new-entry",
4040
"--rekor_server.publish_events_json=true",
41+
"--search_index.storage_provider=mysql",
42+
"--search_index.mysql.dsn=test:zaphod@tcp(mysql:3306)/test",
4143
]
4244
ports:
4345
- "3000:3000"
4446
- "2112:2112"
4547
depends_on:
4648
- gcp-pubsub-emulator
49+
- mysql
4750
gcp-pubsub-emulator:
4851
image: gcp-pubsub-emulator
4952
ports:

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ services:
100100
"--enable_attestation_storage",
101101
"--attestation_storage_bucket=file:///var/run/attestations",
102102
"--enable_stable_checkpoint",
103+
"--search_index.storage_provider=mysql",
104+
"--search_index.mysql.dsn=test:zaphod@tcp(mysql:3306)/test",
103105
# Uncomment this for production logging
104106
# "--log_type=prod",
105107
]

e2e-test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ set -e
1818
testdir=$(dirname "$0")
1919

2020
docker_compose="docker compose -f docker-compose.yml -f docker-compose.test.yml"
21-
if ! ${docker_compose} version 2&>1 >/dev/null; then
21+
if ! ${docker_compose} version >/dev/null 2>&1; then
2222
docker_compose="docker-compose -f docker-compose.yml -f docker-compose.test.yml"
2323
fi
2424

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,14 @@ require (
5353
cloud.google.com/go/profiler v0.4.0
5454
cloud.google.com/go/pubsub v1.33.0
5555
github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230618160516-e936619f9f18
56+
github.com/DATA-DOG/go-sqlmock v1.5.0
5657
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7
5758
github.com/go-redis/redismock/v9 v9.2.0
59+
github.com/go-sql-driver/mysql v1.7.1
5860
github.com/golang/mock v1.6.0
5961
github.com/hashicorp/go-cleanhttp v0.5.2
6062
github.com/hashicorp/go-retryablehttp v0.7.5
63+
github.com/jmoiron/sqlx v1.3.5
6164
github.com/redis/go-redis/v9 v9.3.0
6265
github.com/sassoftware/relic/v7 v7.6.1
6366
github.com/sigstore/protobuf-specs v0.2.1

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw
7070
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
7171
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
7272
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
73+
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
74+
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
7375
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
7476
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
7577
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
@@ -244,6 +246,7 @@ github.com/go-openapi/validate v0.22.2 h1:Lda8nadL/5kIvS5mdXCAIuZ7IVXvKFIppLnw+E
244246
github.com/go-openapi/validate v0.22.2/go.mod h1:kVxh31KbfsxU8ZyoHaDbLBWU5CnMdqBUEtadQ2G4d5M=
245247
github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw=
246248
github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0=
249+
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
247250
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
248251
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
249252
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
@@ -400,6 +403,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
400403
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
401404
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4=
402405
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo=
406+
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
407+
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
403408
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
404409
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
405410
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -423,6 +428,7 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
423428
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
424429
github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf h1:ndns1qx/5dL43g16EQkPV/i8+b3l5bYQwLeoSBe7tS8=
425430
github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf/go.mod h1:aGkAgvWY/IUcVFfuly53REpfv5edu25oij+qHRFaraA=
431+
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
426432
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
427433
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
428434
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
@@ -438,6 +444,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
438444
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
439445
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
440446
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
447+
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
448+
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
441449
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
442450
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
443451
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=

pkg/api/api.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,10 @@ func StopAPI() {
197197
if api.newEntryPublisher != nil {
198198
api.newEntryPublisher.Close()
199199
}
200+
201+
if indexStorageClient != nil {
202+
if err := indexStorageClient.Shutdown(); err != nil {
203+
log.Logger.Errorf("shutting down indexStorageClient: %v", err)
204+
}
205+
}
200206
}

pkg/api/entries.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,8 @@ func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middl
251251
log.ContextLogger(ctx).Errorf("getting entry index keys: %v", err)
252252
return
253253
}
254-
for _, key := range keys {
255-
if err := addToIndex(context.Background(), key, entryID); err != nil {
256-
log.ContextLogger(ctx).Errorf("adding keys to index: %v", err)
257-
}
254+
if err := addToIndex(context.Background(), keys, entryID); err != nil {
255+
log.ContextLogger(ctx).Errorf("adding keys to index: %v", err)
258256
}
259257
}()
260258
}

pkg/api/index.go

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,20 @@ func SearchIndexHandler(params index.SearchIndexParams) middleware.Responder {
4242
}
4343
var result = NewCollection(queryOperator)
4444

45+
var lookupKeys []string
46+
4547
if params.Query.Hash != "" {
4648
// This must be a valid hash
47-
sha := util.PrefixSHA(params.Query.Hash)
48-
resultUUIDs, err := indexStorageClient.LookupIndices(httpReqCtx, strings.ToLower(sha))
49-
if err != nil {
50-
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("index storage error: %w", err), indexStorageUnexpectedResult)
49+
sha := strings.ToLower(util.PrefixSHA(params.Query.Hash))
50+
if queryOperator == "or" {
51+
lookupKeys = append(lookupKeys, sha)
52+
} else {
53+
resultUUIDs, err := indexStorageClient.LookupIndices(httpReqCtx, []string{sha})
54+
if err != nil {
55+
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("index storage error: %w", err), indexStorageUnexpectedResult)
56+
}
57+
result.Add(resultUUIDs)
5158
}
52-
result.Add(resultUUIDs)
5359
}
5460
if params.Query.PublicKey != nil {
5561
af, err := pki.NewArtifactFactory(pki.Format(swag.StringValue(params.Query.PublicKey.Format)))
@@ -72,14 +78,31 @@ func SearchIndexHandler(params index.SearchIndexParams) middleware.Responder {
7278
}
7379

7480
keyHash := sha256.Sum256(canonicalKey)
75-
resultUUIDs, err := indexStorageClient.LookupIndices(httpReqCtx, strings.ToLower(hex.EncodeToString(keyHash[:])))
76-
if err != nil {
77-
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("index storage error: %w", err), indexStorageUnexpectedResult)
81+
keyHashStr := strings.ToLower(hex.EncodeToString(keyHash[:]))
82+
if queryOperator == "or" {
83+
lookupKeys = append(lookupKeys, keyHashStr)
84+
} else {
85+
resultUUIDs, err := indexStorageClient.LookupIndices(httpReqCtx, []string{keyHashStr})
86+
if err != nil {
87+
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("index storage error: %w", err), indexStorageUnexpectedResult)
88+
}
89+
result.Add(resultUUIDs)
7890
}
79-
result.Add(resultUUIDs)
8091
}
8192
if params.Query.Email != "" {
82-
resultUUIDs, err := indexStorageClient.LookupIndices(httpReqCtx, strings.ToLower(params.Query.Email.String()))
93+
emailStr := strings.ToLower(params.Query.Email.String())
94+
if queryOperator == "or" {
95+
lookupKeys = append(lookupKeys, emailStr)
96+
} else {
97+
resultUUIDs, err := indexStorageClient.LookupIndices(httpReqCtx, []string{emailStr})
98+
if err != nil {
99+
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("index storage error: %w", err), indexStorageUnexpectedResult)
100+
}
101+
result.Add(resultUUIDs)
102+
}
103+
}
104+
if len(lookupKeys) > 0 {
105+
resultUUIDs, err := indexStorageClient.LookupIndices(httpReqCtx, lookupKeys)
83106
if err != nil {
84107
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("index storage error: %w", err), indexStorageUnexpectedResult)
85108
}
@@ -99,8 +122,8 @@ func SearchIndexNotImplementedHandler(_ index.SearchIndexParams) middleware.Resp
99122

100123
}
101124

102-
func addToIndex(ctx context.Context, key, value string) error {
103-
err := indexStorageClient.WriteIndex(ctx, key, value)
125+
func addToIndex(ctx context.Context, keys []string, value string) error {
126+
err := indexStorageClient.WriteIndex(ctx, keys, value)
104127
if err != nil {
105128
return fmt.Errorf("redis client: %w", err)
106129
}

pkg/indexstorage/indexstorage.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,24 @@ import (
1818
"context"
1919
"fmt"
2020

21+
"github.com/sigstore/rekor/pkg/indexstorage/mysql"
2122
"github.com/sigstore/rekor/pkg/indexstorage/redis"
2223
"github.com/spf13/viper"
2324
)
2425

2526
type IndexStorage interface {
26-
LookupIndices(context.Context, string) ([]string, error) // Returns indices for specified key
27-
WriteIndex(context.Context, string, string) error // Writes index for specified key
27+
LookupIndices(context.Context, []string) ([]string, error) // Returns indices for specified keys
28+
WriteIndex(context.Context, []string, string) error // Writes index for specified keys
29+
Shutdown() error // Method to run on shutdown
2830
}
2931

3032
// NewIndexStorage instantiates a new IndexStorage provider based on the requested type
3133
func NewIndexStorage(providerType string) (IndexStorage, error) {
3234
switch providerType {
3335
case redis.ProviderType:
3436
return redis.NewProvider(viper.GetString("redis_server.address"), viper.GetString("redis_server.port"), viper.GetString("redis_server.password"))
37+
case mysql.ProviderType:
38+
return mysql.NewProvider(viper.GetString("search_index.mysql.dsn"))
3539
default:
3640
return nil, fmt.Errorf("invalid index storage provider type: %v", providerType)
3741
}

0 commit comments

Comments
 (0)