This repository was archived by the owner on Jan 26, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Add Redis Auth and mTLS support #14
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
1915620
Staging my Work in Progress
beautifulentropy d2786b1
Still piping through the new RedisConfig, Updated example files
beautifulentropy e1c882f
Still piping through to attache-check
beautifulentropy 650be06
Need to generate new certs
beautifulentropy e615fac
New certs generated
beautifulentropy 52a1e86
Auth is making it through, but still getting WRONGPASS when go-redis …
beautifulentropy 9df948a
Small cleanup
beautifulentropy 1a6ac88
Everything is working except for scaling
beautifulentropy 38f3a82
Scaling replicas bug fixed
beautifulentropy b8156cc
Final bits of code cleanup
beautifulentropy 0c7ada8
Fix fatalf call without arg
beautifulentropy 140c1ce
Fix README checkboxes
beautifulentropy f60d0c3
Comment fix
beautifulentropy 26f033b
Remove .DS_Store
beautifulentropy 4c89f35
Fix comment copypasta
beautifulentropy a79e811
Fix comment copypasta part 2
beautifulentropy 651fcb3
Addressing comments
beautifulentropy f84b6cc
Updating README
beautifulentropy 1c70917
Adding masterauth and masteruser back
beautifulentropy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,3 +46,5 @@ attache-control | |
| !attache-control/ | ||
| !attache-check/ | ||
|
|
||
| # Mac | ||
| *.DS_Store | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,141 +1,83 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "errors" | ||
| "flag" | ||
| "fmt" | ||
| "net/http" | ||
| "time" | ||
|
|
||
| consul "github.com/hashicorp/consul/api" | ||
| logger "github.com/sirupsen/logrus" | ||
| c "github.com/letsencrypt/attache/src/consul/config" | ||
| r "github.com/letsencrypt/attache/src/redis/config" | ||
| ) | ||
|
|
||
| // CLIOpts is exported for use with flag.Parse(). | ||
| type CLIOpts struct { | ||
| // Exported for use with flag.Parse() | ||
| RedisNodeAddr string | ||
| // Exported for use with flag.Parse() | ||
| RedisOpts r.RedisOpts | ||
| RedisPrimaryCount int | ||
| // Exported for use with flag.Parse() | ||
| RedisReplicaCount int | ||
| // Exported for use with flag.Parse() | ||
| LockPath string | ||
| // Exported for use with flag.Parse() | ||
| AttemptInterval time.Duration | ||
| // Exported for use with flag.Parse() | ||
| AttemptLimit int | ||
| // Exported for use with flag.Parse() | ||
| AwaitServiceName string | ||
| // Exported for use with flag.Parse() | ||
| DestServiceName string | ||
| // Exported for use with flag.Parse() | ||
| LogLevel string | ||
| // Exported for use with flag.Parse() | ||
| ConsulOpts ConsulOpts | ||
| LockPath string | ||
| AttemptInterval time.Duration | ||
| AttemptLimit int | ||
| AwaitServiceName string | ||
| DestServiceName string | ||
| LogLevel string | ||
| ConsulOpts c.ConsulOpts | ||
| } | ||
|
|
||
| type ConsulOpts struct { | ||
| // Exported for use with flag.Parse() | ||
| DC string | ||
| // Exported for use with flag.Parse() | ||
| Address string | ||
| // Exported for use with flag.Parse() | ||
| ACLToken string | ||
| // Exported for use with flag.Parse() | ||
| TLSEnable bool | ||
| // Exported for use with flag.Parse() | ||
| TLSCACert string | ||
| // Exported for use with flag.Parse() | ||
| TLSCert string | ||
| // Exported for use with flag.Parse() | ||
| TLSKey string | ||
| } | ||
| func (c CLIOpts) Validate() error { | ||
| if c.RedisPrimaryCount == 0 { | ||
| return errors.New("missing required opt: 'redis-primary-count'") | ||
|
beautifulentropy marked this conversation as resolved.
|
||
| } | ||
|
|
||
| if c.DestServiceName == "" { | ||
| return errors.New("missing required opt: 'dest-service-name'") | ||
| } | ||
|
|
||
| func (c *ConsulOpts) MakeConsulClient() (*consul.Client, error) { | ||
| config := consul.DefaultConfig() | ||
| config.Datacenter = c.DC | ||
| config.Address = c.Address | ||
| config.Token = c.ACLToken | ||
| if c.TLSEnable { | ||
| config.Scheme = "https" | ||
| tlsConfig := consul.TLSConfig{ | ||
| Address: c.Address, | ||
| CAFile: c.TLSCACert, | ||
| CertFile: c.TLSCert, | ||
| KeyFile: c.TLSKey, | ||
| } | ||
| tlsClientConf, err := consul.SetupTLSConfig(&tlsConfig) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("error creating TLS client config for consul: %w", err) | ||
| } | ||
| config.HttpClient.Transport = &http.Transport{ | ||
| TLSClientConfig: tlsClientConf, | ||
| } | ||
| if c.AwaitServiceName == "" { | ||
| return errors.New("missing required opt: 'await-service-name'") | ||
| } | ||
|
|
||
| client, err := consul.NewClient(config) | ||
| err := c.ConsulOpts.Validate() | ||
| if err != nil { | ||
| return nil, err | ||
| return err | ||
| } | ||
|
|
||
| return client, nil | ||
| err = c.RedisOpts.Validate() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func ParseFlags() CLIOpts { | ||
| var conf CLIOpts | ||
|
|
||
| // CLI | ||
| flag.StringVar(&conf.RedisNodeAddr, "redis-node-addr", "", "redis-server listening address") | ||
| flag.IntVar(&conf.RedisPrimaryCount, "redis-primary-count", 0, "Total number of expected Redis shard primary nodes") | ||
| flag.IntVar(&conf.RedisPrimaryCount, "redis-primary-count", 0, "Total number of expected Redis shard primary nodes, (required)") | ||
| flag.IntVar(&conf.RedisReplicaCount, "redis-replica-count", 0, "Total number of expected Redis shard replica nodes") | ||
| flag.StringVar(&conf.LockPath, "lock-kv-path", "service/attache/leader", "Consul KV path used as a distributed lock for operations") | ||
| flag.DurationVar(&conf.AttemptInterval, "attempt-interval", 3*time.Second, "Duration to wait between attempts to join or create a cluster") | ||
| flag.IntVar(&conf.AttemptLimit, "attempt-limit", 20, "Number of times to attempt joining or creating a cluster before exiting") | ||
| flag.StringVar(&conf.AwaitServiceName, "await-service-name", "", "Consul Service for any newly created Redis Cluster Nodes") | ||
| flag.StringVar(&conf.AwaitServiceName, "await-service-name", "", "Consul Service for newly created Redis Cluster Nodes, (required)") | ||
| flag.StringVar(&conf.DestServiceName, "dest-service-name", "", "Consul Service for healthy Redis Cluster Nodes, (required)") | ||
| flag.StringVar(&conf.LogLevel, "log-level", "info", "Set the log level") | ||
|
|
||
| // Redis | ||
| flag.StringVar(&conf.RedisOpts.NodeAddr, "redis-node-addr", "", "redis-server listening address, (required)") | ||
| flag.StringVar(&conf.RedisOpts.Username, "redis-auth-username", "", "Redis username, (required)") | ||
| flag.StringVar(&conf.RedisOpts.PasswordFile, "redis-auth-password-file", "", "Redis password file path, (required)") | ||
| flag.StringVar(&conf.RedisOpts.CACertFile, "redis-tls-ca-cert", "", "Redis client CA certificate file, (required)") | ||
| flag.StringVar(&conf.RedisOpts.CertFile, "redis-tls-cert-file", "", "Redis client certificate file, (required)") | ||
| flag.StringVar(&conf.RedisOpts.KeyFile, "redis-tls-key-file", "", "Redis client key file, (required)") | ||
|
|
||
| // Consul | ||
| flag.StringVar(&conf.DestServiceName, "dest-service-name", "", "Consul Service for any existing Redis Cluster Nodes") | ||
| flag.StringVar(&conf.ConsulOpts.DC, "consul-dc", "dev-general", "Consul client datacenter") | ||
| flag.StringVar(&conf.ConsulOpts.Address, "consul-addr", "127.0.0.1:8500", "Consul client address") | ||
| flag.StringVar(&conf.ConsulOpts.ACLToken, "consul-acl-token", "", "Consul client ACL token") | ||
| flag.BoolVar(&conf.ConsulOpts.TLSEnable, "consul-tls-enable", false, "Enable TLS for the Consul client") | ||
| flag.BoolVar(&conf.ConsulOpts.EnableTLS, "consul-tls-enable", false, "Enable mTLS for the Consul client") | ||
| flag.StringVar(&conf.ConsulOpts.TLSCACert, "consul-tls-ca-cert", "", "Consul client CA certificate file") | ||
| flag.StringVar(&conf.ConsulOpts.TLSCert, "consul-tls-cert", "", "Consul client certificate file") | ||
| flag.StringVar(&conf.ConsulOpts.TLSKey, "consul-tls-key", "", "Consul client key file") | ||
|
|
||
| flag.Parse() | ||
|
|
||
| return conf | ||
| } | ||
|
|
||
| func ValidateConfig(conf CLIOpts) { | ||
| if conf.ConsulOpts.TLSEnable { | ||
| if conf.ConsulOpts.TLSCACert == "" { | ||
| logger.Fatal("Missing required opt: 'consul-tls-ca-cert") | ||
| } | ||
|
|
||
| if conf.ConsulOpts.TLSCert == "" { | ||
| logger.Fatal("Missing required opt: 'consul-tls-cert") | ||
| } | ||
|
|
||
| if conf.ConsulOpts.TLSKey == "" { | ||
| logger.Fatal("Missing required opt: 'consul-tls-key") | ||
| } | ||
| } | ||
|
|
||
| if conf.RedisNodeAddr == "" { | ||
| logger.Fatal("Missing required opt: 'redis-node-addr'") | ||
| } | ||
|
|
||
| if conf.RedisPrimaryCount == 0 { | ||
| logger.Fatal("Missing required opt: 'redis-primary-count'") | ||
| } | ||
|
|
||
| if conf.DestServiceName == "" { | ||
| logger.Fatal("Missing required opt: 'dest-service-name'") | ||
| } | ||
|
|
||
| if conf.AwaitServiceName == "" { | ||
| logger.Fatal("Missing required opt: 'await-service-name'") | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.