github.com/instill-ai/component@v0.16.0-beta/pkg/connector/redis/v0/client.go (about) 1 package redis 2 3 import ( 4 "crypto/tls" 5 "crypto/x509" 6 "fmt" 7 8 "github.com/instill-ai/component/pkg/base" 9 goredis "github.com/redis/go-redis/v9" 10 "google.golang.org/protobuf/types/known/structpb" 11 ) 12 13 // SSLMode is the type for SSL mode 14 type SSLMode string 15 16 const ( 17 DisableSSLMode SSLMode = "disable" 18 VerifyFullSSLMode SSLMode = "verify-full" 19 ) 20 21 // SSLConfig is the interface for SSL configuration 22 type SSLModeConfig interface { 23 GetConfig() (*tls.Config, error) 24 } 25 26 // DisableSSL is the struct for disable SSL 27 type DisableSSL struct { 28 Mode SSLMode `json:"mode"` 29 } 30 31 func (d *DisableSSL) GetConfig() (*tls.Config, error) { 32 return nil, nil 33 } 34 35 // VerifyFullSSL is the struct for verify-full SSL. It always requires encryption and verification of the identify of the server. 36 type VerifyFullSSL struct { 37 Mode SSLMode `json:"mode"` 38 CaCert string `json:"ca_cert"` 39 ClientCert string `json:"client_cert"` 40 ClientKey string `json:"client_key"` 41 } 42 43 func (e *VerifyFullSSL) GetConfig() (*tls.Config, error) { 44 caCert := []byte(e.CaCert) 45 caCertPool := x509.NewCertPool() 46 caCertPool.AppendCertsFromPEM(caCert) 47 48 // TODO: Add support for password protected client key 49 50 // Load client's certificate and private key 51 clientCert, err := tls.X509KeyPair([]byte(e.ClientCert), []byte(e.ClientKey)) 52 if err != nil { 53 return nil, fmt.Errorf("failed to load client certificate and key: %v", err) 54 } 55 56 // Setup TLS config 57 tlsConfig := &tls.Config{ 58 RootCAs: caCertPool, 59 Certificates: []tls.Certificate{clientCert}, 60 // In a production setting, you might want to set MinVersion to tls.VersionTLS12 61 MinVersion: tls.VersionTLS12, 62 // Setting InsecureSkipVerify to true is not recommended in a production environment 63 InsecureSkipVerify: true, 64 } 65 return tlsConfig, nil 66 } 67 68 func getHost(config *structpb.Struct) string { 69 return config.GetFields()["host"].GetStringValue() 70 } 71 func getPort(config *structpb.Struct) int { 72 return int(config.GetFields()["port"].GetNumberValue()) 73 } 74 func getPassword(config *structpb.Struct) string { 75 val, ok := config.GetFields()["password"] 76 if !ok { 77 return "" 78 } 79 return val.GetStringValue() 80 } 81 func getUsername(config *structpb.Struct) string { 82 val, ok := config.GetFields()["username"] 83 if !ok { 84 return "" 85 } 86 return val.GetStringValue() 87 } 88 89 func getSSL(config *structpb.Struct) bool { 90 val, ok := config.GetFields()["ssl"] 91 if !ok { 92 return false 93 } 94 return val.GetBoolValue() 95 } 96 97 func getSSLMode(config *structpb.Struct) (SSLModeConfig, error) { 98 sslMode := config.GetFields()["ssl_mode"].GetStructValue() 99 mode := sslMode.GetFields()["mode"].GetStringValue() 100 101 var sslModeConfig SSLModeConfig 102 switch mode { 103 case string(DisableSSLMode): 104 sslModeConfig = &DisableSSL{} 105 case string(VerifyFullSSLMode): 106 sslModeConfig = &VerifyFullSSL{} 107 default: 108 return nil, fmt.Errorf("invalid SSL mode: %s", mode) 109 } 110 111 err := base.ConvertFromStructpb(sslMode, sslModeConfig) 112 if err != nil { 113 return nil, err 114 } 115 return sslModeConfig, nil 116 } 117 118 // NewClient creates a new redis client 119 func NewClient(config *structpb.Struct) (*goredis.Client, error) { 120 op := &goredis.Options{ 121 Addr: fmt.Sprintf("%s:%d", getHost(config), getPort(config)), 122 Password: getPassword(config), 123 DB: 0, 124 } 125 if getUsername(config) != "" { 126 op.Username = getUsername(config) 127 } 128 129 if getSSL(config) { 130 sslConfig, err := getSSLMode(config) 131 if err != nil { 132 return nil, err 133 } 134 if sslConfig != nil { 135 tlsConfig, err := sslConfig.GetConfig() 136 if err != nil { 137 return nil, err 138 } 139 op.TLSConfig = tlsConfig 140 } 141 } 142 143 // TODO - add SSH support 144 145 return goredis.NewClient(op), nil 146 }