github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/client/mq/kafka/auth/options.go (about)

     1  package auth
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"io/ioutil"
     7  
     8  	"github.com/weedge/lib/container/slice"
     9  	"github.com/weedge/lib/log"
    10  
    11  	"github.com/Shopify/sarama"
    12  )
    13  
    14  type AuthOptions struct {
    15  	// security-protocol: SSL (broker service config default PLAINTEXT, need security.inter.broker.protocol=SSL)
    16  	enableSSL bool
    17  	certFile  string // the optional certificate file for client authentication
    18  	keyFile   string // the optional key file for client authentication
    19  	caFile    string // the optional certificate authority file for TLS client authentication
    20  	verifySSL bool   // the optional verify ssl certificates chain
    21  
    22  	//SASL: PLAINTEXT(Kafka 0.10.0.0+), SCRAM(kafka 0.10.2.0+ dynamic add user), OAUTHBEARER(Kafka2.0.0+,JWT)
    23  	enableSASL     bool
    24  	authentication string // PLAINTEXT,SCRAM,OAUTHBEARER,if enableSASL true,default SCRAM
    25  	saslUser       string // The SASL username
    26  	saslPassword   string // The SASL password
    27  	scramAlgorithm string // The SASL SCRAM SHA algorithm sha256 or sha512 as mechanism
    28  }
    29  
    30  type Option interface {
    31  	apply(o *AuthOptions)
    32  }
    33  
    34  type funcServerOption struct {
    35  	f func(o *AuthOptions)
    36  }
    37  
    38  func (fdo *funcServerOption) apply(o *AuthOptions) {
    39  	fdo.f(o)
    40  }
    41  
    42  func newFuncServerOption(f func(o *AuthOptions)) *funcServerOption {
    43  	return &funcServerOption{
    44  		f: f,
    45  	}
    46  }
    47  
    48  func WithEnableSSL(enableSSL bool) Option {
    49  	return newFuncServerOption(func(o *AuthOptions) {
    50  		o.enableSSL = enableSSL
    51  	})
    52  }
    53  
    54  func WithSSLCertFile(certFile string) Option {
    55  	return newFuncServerOption(func(o *AuthOptions) {
    56  		o.certFile = certFile
    57  	})
    58  }
    59  
    60  func WithSSLKeyFile(keyFile string) Option {
    61  	return newFuncServerOption(func(o *AuthOptions) {
    62  		o.keyFile = keyFile
    63  	})
    64  }
    65  
    66  func WithSSLCaFile(caFile string) Option {
    67  	return newFuncServerOption(func(o *AuthOptions) {
    68  		o.caFile = caFile
    69  	})
    70  }
    71  
    72  func (opts *AuthOptions) InitSSL(config *sarama.Config) {
    73  	if opts.enableSSL == false {
    74  		return
    75  	}
    76  
    77  	tlsConfig := opts.CreateTlsConfiguration()
    78  	if tlsConfig != nil {
    79  		config.Net.TLS.Config = tlsConfig
    80  		config.Net.TLS.Enable = true
    81  	}
    82  }
    83  
    84  func (opts *AuthOptions) CreateTlsConfiguration() (t *tls.Config) {
    85  	if opts.certFile == "" || opts.keyFile == "" || opts.caFile == "" {
    86  		return
    87  	}
    88  
    89  	cert, err := tls.LoadX509KeyPair(opts.certFile, opts.keyFile)
    90  	if err != nil {
    91  		log.Error("tls.LoadX509KeyPair err", err)
    92  		return
    93  	}
    94  
    95  	caCert, err := ioutil.ReadFile(opts.caFile)
    96  	if err != nil {
    97  		log.Error("ioutil.ReadFile err", err)
    98  		return
    99  	}
   100  
   101  	caCertPool := x509.NewCertPool()
   102  	caCertPool.AppendCertsFromPEM(caCert)
   103  
   104  	t = &tls.Config{
   105  		Certificates:       []tls.Certificate{cert},
   106  		RootCAs:            caCertPool,
   107  		InsecureSkipVerify: opts.verifySSL,
   108  	}
   109  
   110  	return
   111  }
   112  
   113  func WithEnableSASL(enableSASL bool) Option {
   114  	return newFuncServerOption(func(o *AuthOptions) {
   115  		o.enableSASL = enableSASL
   116  	})
   117  }
   118  
   119  func WithAuthentication(authentication string) Option {
   120  	return newFuncServerOption(func(o *AuthOptions) {
   121  		o.authentication = "SCRAM"
   122  		if slice.Contains([]string{"PLAINTEXT", "SCRAM", "OAUTHBEARER"}, authentication) {
   123  			o.authentication = authentication
   124  		}
   125  	})
   126  }
   127  
   128  func WithScramAlgorithm(scramAlgorithm string) Option {
   129  	return newFuncServerOption(func(o *AuthOptions) {
   130  		o.scramAlgorithm = "sha256"
   131  		if slice.Contains([]string{"sha256", "sha512"}, scramAlgorithm) {
   132  			o.scramAlgorithm = scramAlgorithm
   133  		}
   134  	})
   135  }
   136  
   137  func WithSASLUser(saslUser string) Option {
   138  	return newFuncServerOption(func(o *AuthOptions) {
   139  		o.saslUser = saslUser
   140  	})
   141  }
   142  
   143  func WithSASLPassword(saslPassword string) Option {
   144  	return newFuncServerOption(func(o *AuthOptions) {
   145  		o.saslPassword = saslPassword
   146  	})
   147  }
   148  
   149  func (opts *AuthOptions) InitSASLSCRAM(conf *sarama.Config) {
   150  	if !opts.enableSASL {
   151  		return
   152  	}
   153  	if opts.authentication != "SCRAM" {
   154  		return
   155  	}
   156  	conf.Net.SASL.Enable = opts.enableSASL
   157  	conf.Net.SASL.User = opts.saslUser
   158  	conf.Net.SASL.Password = opts.saslPassword
   159  	conf.Net.SASL.Handshake = true
   160  	switch opts.scramAlgorithm {
   161  	case "sha512":
   162  		conf.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &XDGSCRAMClient{HashGeneratorFcn: SHA512} }
   163  		conf.Net.SASL.Mechanism = sarama.SASLTypeSCRAMSHA512
   164  	case "sha256":
   165  		fallthrough
   166  	default:
   167  		conf.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &XDGSCRAMClient{HashGeneratorFcn: SHA256} }
   168  		conf.Net.SASL.Mechanism = sarama.SASLTypeSCRAMSHA256
   169  	}
   170  }
   171  
   172  func GetAuthOptions(opts ...Option) *AuthOptions {
   173  	authOptions := &AuthOptions{
   174  		enableSSL:      false,
   175  		certFile:       "",
   176  		keyFile:        "",
   177  		caFile:         "",
   178  		verifySSL:      false,
   179  
   180  		enableSASL:     false,
   181  		authentication: "SCRAM",
   182  		saslUser:       "",
   183  		saslPassword:   "",
   184  		scramAlgorithm: "sha256",
   185  	}
   186  
   187  	for _, o := range opts {
   188  		o.apply(authOptions)
   189  	}
   190  
   191  	return authOptions
   192  }