From 07b1a9f42942c6c35eb6f796cb0bc4fce3064b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihkel=20P=C3=A4rna?= <35686820+mihkelparna1@users.noreply.github.com> Date: Thu, 15 Feb 2024 23:35:41 +0200 Subject: [PATCH] Add TLS support for Redis Client implementation (#1998) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add TLS support for Redis Client implementation Signed-off-by: Mihkel Pärna * Define 'redis_server.insecure-skip-verify' flag in 'rekor-server' to allow skipping TLS verification Signed-off-by: Mihkel Pärna * Change flag comment to reference that this only applies to the redis endpoint Signed-off-by: Mihkel Pärna * Add '#nosec G402' annotation to suppress known warning Signed-off-by: Mihkel Pärna * Wrap redis client creation to a separate function to return different implementations based on 'enable-tls' flag Signed-off-by: Mihkel Pärna * Fix flag name from 'enableTls' -> 'enableTLS'. Make bool comparisons conform to go best practices. Signed-off-by: Mihkel Pärna * Reduce duplicate code. Signed-off-by: Mihkel Pärna * Add TLS option for Redis for the search index client Signed-off-by: Mihkel Pärna --------- Signed-off-by: Mihkel Pärna --- cmd/backfill-redis/main.go | 47 ++++++++++++++++++++++---------- cmd/rekor-server/app/root.go | 2 ++ pkg/api/api.go | 27 ++++++++++++++---- pkg/indexstorage/indexstorage.go | 2 +- pkg/indexstorage/redis/redis.go | 10 ++++++- 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/cmd/backfill-redis/main.go b/cmd/backfill-redis/main.go index 718d6c5c7..ea8921592 100644 --- a/cmd/backfill-redis/main.go +++ b/cmd/backfill-redis/main.go @@ -29,6 +29,7 @@ package main import ( "bytes" "context" + "crypto/tls" "encoding/base64" "errors" "flag" @@ -64,15 +65,17 @@ import ( ) var ( - redisHostname = flag.String("hostname", "", "Hostname for Redis application") - redisPort = flag.String("port", "", "Port to Redis application") - redisPassword = flag.String("password", "", "Password for Redis authentication") - startIndex = flag.Int("start", -1, "First index to backfill") - endIndex = flag.Int("end", -1, "Last index to backfill") - rekorAddress = flag.String("rekor-address", "", "Address for Rekor, e.g. https://rekor.sigstore.dev") - versionFlag = flag.Bool("version", false, "Print the current version of Backfill Redis") - concurrency = flag.Int("concurrency", 1, "Number of workers to use for backfill") - dryRun = flag.Bool("dry-run", false, "Dry run - don't actually insert into Redis") + redisHostname = flag.String("hostname", "", "Hostname for Redis application") + redisPort = flag.String("port", "", "Port to Redis application") + redisPassword = flag.String("password", "", "Password for Redis authentication") + startIndex = flag.Int("start", -1, "First index to backfill") + endIndex = flag.Int("end", -1, "Last index to backfill") + enableTLS = flag.Bool("enable-tls", false, "Enable TLS for Redis client") + insecureSkipVerify = flag.Bool("insecure-skip-verify", false, "Whether to skip TLS verification for Redis client or not") + rekorAddress = flag.String("rekor-address", "", "Address for Rekor, e.g. https://rekor.sigstore.dev") + versionFlag = flag.Bool("version", false, "Print the current version of Backfill Redis") + concurrency = flag.Int("concurrency", 1, "Number of workers to use for backfill") + dryRun = flag.Bool("dry-run", false, "Dry run - don't actually insert into Redis") ) func main() { @@ -102,12 +105,7 @@ func main() { log.Printf("running backfill redis Version: %s GitCommit: %s BuildDate: %s", versionInfo.GitVersion, versionInfo.GitCommit, versionInfo.BuildDate) - redisClient := redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("%s:%s", *redisHostname, *redisPort), - Password: *redisPassword, - Network: "tcp", - DB: 0, // default DB - }) + redisClient := redisClient() rekorClient, err := client.GetRekorClient(*rekorAddress) if err != nil { @@ -210,6 +208,25 @@ func main() { } } +func redisClient() *redis.Client { + + opts := &redis.Options{ + Addr: fmt.Sprintf("%s:%s", *redisHostname, *redisPort), + Password: *redisPassword, + Network: "tcp", + DB: 0, // default DB + } + + // #nosec G402 + if *enableTLS { + opts.TLSConfig = &tls.Config{ + InsecureSkipVerify: *insecureSkipVerify, + } + } + + return redis.NewClient(opts) +} + // unmarshalEntryImpl decodes the base64-encoded entry to a specific entry type (types.EntryImpl). // Taken from Cosign func unmarshalEntryImpl(e string) (types.EntryImpl, string, string, error) { diff --git a/cmd/rekor-server/app/root.go b/cmd/rekor-server/app/root.go index 23a0c70db..a17054ff9 100644 --- a/cmd/rekor-server/app/root.go +++ b/cmd/rekor-server/app/root.go @@ -115,6 +115,8 @@ Memory and file-based signers should only be used for testing.`) rootCmd.PersistentFlags().String("redis_server.address", "127.0.0.1", "Redis server address") rootCmd.PersistentFlags().Uint16("redis_server.port", 6379, "Redis server port") rootCmd.PersistentFlags().String("redis_server.password", "", "Redis server password") + rootCmd.PersistentFlags().Bool("redis_server.enable-tls", false, "Whether to enable TLS verification when connecting to Redis endpoint") + rootCmd.PersistentFlags().Bool("redis_server.insecure-skip-verify", false, "Whether to skip TLS verification when connecting to Redis endpoint, only applicable when 'redis_server.enable-tls' is set to 'true'") rootCmd.PersistentFlags().Bool("enable_attestation_storage", false, "enables rich attestation storage") rootCmd.PersistentFlags().String("attestation_storage_bucket", "", "url for attestation storage bucket") diff --git a/pkg/api/api.go b/pkg/api/api.go index 9eabb747c..47b112afa 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -18,6 +18,7 @@ package api import ( "context" "crypto/sha256" + "crypto/tls" "crypto/x509" "encoding/hex" "fmt" @@ -175,12 +176,7 @@ func ConfigureAPI(treeID uint) { } if viper.GetBool("enable_stable_checkpoint") { - redisClient = redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("%v:%v", viper.GetString("redis_server.address"), viper.GetUint64("redis_server.port")), - Password: viper.GetString("redis_server.password"), - Network: "tcp", - DB: 0, // default DB - }) + redisClient = NewRedisClient() checkpointPublisher := witness.NewCheckpointPublisher(context.Background(), api.logClient, api.logRanges.ActiveTreeID(), viper.GetString("rekor_server.hostname"), api.signer, redisClient, viper.GetUint("publish_frequency"), CheckpointPublishCount) @@ -191,6 +187,25 @@ func ConfigureAPI(treeID uint) { } } +func NewRedisClient() *redis.Client { + + opts := &redis.Options{ + Addr: fmt.Sprintf("%v:%v", viper.GetString("redis_server.address"), viper.GetUint64("redis_server.port")), + Password: viper.GetString("redis_server.password"), + Network: "tcp", + DB: 0, // default DB + } + + // #nosec G402 + if viper.GetBool("redis_server.enable-tls") { + opts.TLSConfig = &tls.Config{ + InsecureSkipVerify: viper.GetBool("redis_server.insecure-skip-verify"), + } + } + + return redis.NewClient(opts) +} + func StopAPI() { api.checkpointPublishCancel() diff --git a/pkg/indexstorage/indexstorage.go b/pkg/indexstorage/indexstorage.go index 53f38c3d1..009d0d178 100644 --- a/pkg/indexstorage/indexstorage.go +++ b/pkg/indexstorage/indexstorage.go @@ -33,7 +33,7 @@ type IndexStorage interface { func NewIndexStorage(providerType string) (IndexStorage, error) { switch providerType { case redis.ProviderType: - return redis.NewProvider(viper.GetString("redis_server.address"), viper.GetString("redis_server.port"), viper.GetString("redis_server.password")) + return redis.NewProvider(viper.GetString("redis_server.address"), viper.GetString("redis_server.port"), viper.GetString("redis_server.password"), viper.GetBool("redis_server.enable-tls"), viper.GetBool("redis_server.insecure-skip-verify")) case mysql.ProviderType: return mysql.NewProvider(viper.GetString("search_index.mysql.dsn"), mysql.WithConnMaxIdleTime(viper.GetDuration("search_index.mysql.conn_max_idletime")), diff --git a/pkg/indexstorage/redis/redis.go b/pkg/indexstorage/redis/redis.go index 4c3819e09..65d741c7c 100644 --- a/pkg/indexstorage/redis/redis.go +++ b/pkg/indexstorage/redis/redis.go @@ -16,6 +16,7 @@ package redis import ( "context" + "crypto/tls" "errors" "fmt" "strings" @@ -30,7 +31,7 @@ type IndexStorageProvider struct { client *redis.Client } -func NewProvider(address, port, password string) (*IndexStorageProvider, error) { +func NewProvider(address, port, password string, enableTLS bool, insecureSkipVerify bool) (*IndexStorageProvider, error) { provider := &IndexStorageProvider{} provider.client = redis.NewClient(&redis.Options{ Addr: fmt.Sprintf("%v:%v", address, port), @@ -38,6 +39,13 @@ func NewProvider(address, port, password string) (*IndexStorageProvider, error) Password: password, DB: 0, // default DB }) + + // #nosec G402 + if enableTLS { + provider.client.Options().TLSConfig = &tls.Config{ + InsecureSkipVerify: insecureSkipVerify, + } + } return provider, nil }