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  }