NATS TLS specify CA and client TLS authentication (#8389)

- added ability to specify CA for self-signed certificates
- added option to authenticate using client certificates
- added unit tests for nats connections
This commit is contained in:
svistoi
2019-11-15 12:13:23 -05:00
committed by Harshavardhana
parent 13e2b97ad9
commit c9be601988
13 changed files with 411 additions and 58 deletions

View File

@@ -32,15 +32,18 @@ import (
// NATS related constants
const (
NATSAddress = "address"
NATSSubject = "subject"
NATSUsername = "username"
NATSPassword = "password"
NATSToken = "token"
NATSSecure = "secure"
NATSPingInterval = "ping_interval"
NATSQueueDir = "queue_dir"
NATSQueueLimit = "queue_limit"
NATSAddress = "address"
NATSSubject = "subject"
NATSUsername = "username"
NATSPassword = "password"
NATSToken = "token"
NATSSecure = "secure"
NATSPingInterval = "ping_interval"
NATSQueueDir = "queue_dir"
NATSQueueLimit = "queue_limit"
NATSCertAuthority = "cert_authority"
NATSClientCert = "client_cert"
NATSClientKey = "client_key"
// Streaming constants
NATSStreaming = "streaming"
@@ -48,16 +51,19 @@ const (
NATSStreamingAsync = "streaming_async"
NATSStreamingMaxPubAcksInFlight = "streaming_max_pub_acks_in_flight"
EnvNATSState = "MINIO_NOTIFY_NATS_STATE"
EnvNATSAddress = "MINIO_NOTIFY_NATS_ADDRESS"
EnvNATSSubject = "MINIO_NOTIFY_NATS_SUBJECT"
EnvNATSUsername = "MINIO_NOTIFY_NATS_USERNAME"
EnvNATSPassword = "MINIO_NOTIFY_NATS_PASSWORD"
EnvNATSToken = "MINIO_NOTIFY_NATS_TOKEN"
EnvNATSSecure = "MINIO_NOTIFY_NATS_SECURE"
EnvNATSPingInterval = "MINIO_NOTIFY_NATS_PING_INTERVAL"
EnvNATSQueueDir = "MINIO_NOTIFY_NATS_QUEUE_DIR"
EnvNATSQueueLimit = "MINIO_NOTIFY_NATS_QUEUE_LIMIT"
EnvNATSState = "MINIO_NOTIFY_NATS_STATE"
EnvNATSAddress = "MINIO_NOTIFY_NATS_ADDRESS"
EnvNATSSubject = "MINIO_NOTIFY_NATS_SUBJECT"
EnvNATSUsername = "MINIO_NOTIFY_NATS_USERNAME"
EnvNATSPassword = "MINIO_NOTIFY_NATS_PASSWORD"
EnvNATSToken = "MINIO_NOTIFY_NATS_TOKEN"
EnvNATSSecure = "MINIO_NOTIFY_NATS_SECURE"
EnvNATSPingInterval = "MINIO_NOTIFY_NATS_PING_INTERVAL"
EnvNATSQueueDir = "MINIO_NOTIFY_NATS_QUEUE_DIR"
EnvNATSQueueLimit = "MINIO_NOTIFY_NATS_QUEUE_LIMIT"
EnvNATSCertAuthority = "MINIO_NOTIFY_NATS_CERT_AUTHORITY"
EnvNATSClientCert = "MINIO_NOTIFY_NATS_CLIENT_CERT"
EnvNATSClientKey = "MINIO_NOTIFY_NATS_CLIENT_KEY"
// Streaming constants
EnvNATSStreaming = "MINIO_NOTIFY_NATS_STREAMING"
@@ -68,17 +74,20 @@ const (
// NATSArgs - NATS target arguments.
type NATSArgs struct {
Enable bool `json:"enable"`
Address xnet.Host `json:"address"`
Subject string `json:"subject"`
Username string `json:"username"`
Password string `json:"password"`
Token string `json:"token"`
Secure bool `json:"secure"`
PingInterval int64 `json:"pingInterval"`
QueueDir string `json:"queueDir"`
QueueLimit uint64 `json:"queueLimit"`
Streaming struct {
Enable bool `json:"enable"`
Address xnet.Host `json:"address"`
Subject string `json:"subject"`
Username string `json:"username"`
Password string `json:"password"`
Token string `json:"token"`
Secure bool `json:"secure"`
CertAuthority string `json:"certAuthority"`
ClientCert string `json:"clientCert"`
ClientKey string `json:"clientKey"`
PingInterval int64 `json:"pingInterval"`
QueueDir string `json:"queueDir"`
QueueLimit uint64 `json:"queueLimit"`
Streaming struct {
Enable bool `json:"enable"`
ClusterID string `json:"clusterID"`
Async bool `json:"async"`
@@ -100,6 +109,10 @@ func (n NATSArgs) Validate() error {
return errors.New("empty subject")
}
if n.ClientCert != "" && n.ClientKey == "" || n.ClientCert == "" && n.ClientKey != "" {
return errors.New("cert and key must be specified as a pair")
}
if n.Streaming.Enable {
if n.Streaming.ClusterID == "" {
return errors.New("empty cluster id")
@@ -120,13 +133,23 @@ func (n NATSArgs) Validate() error {
// To obtain a nats connection from args.
func (n NATSArgs) connectNats() (*nats.Conn, error) {
options := nats.DefaultOptions
options.Url = "nats://" + n.Address.String()
options.User = n.Username
options.Password = n.Password
options.Token = n.Token
options.Secure = n.Secure
return options.Connect()
connOpts := []nats.Option{nats.Name("Minio Notification")}
if n.Username != "" && n.Password != "" {
connOpts = append(connOpts, nats.UserInfo(n.Username, n.Password))
}
if n.Token != "" {
connOpts = append(connOpts, nats.Token(n.Token))
}
if n.Secure {
connOpts = append(connOpts, nats.Secure(nil))
}
if n.CertAuthority != "" {
connOpts = append(connOpts, nats.RootCAs(n.CertAuthority))
}
if n.ClientCert != "" && n.ClientKey != "" {
connOpts = append(connOpts, nats.ClientCert(n.ClientCert, n.ClientKey))
}
return nats.Connect(n.Address.String(), connOpts...)
}
// To obtain a streaming connection from args.