From 4c702ce0ec6e3f45fafd6276fd1eff61493c9b7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Kraszewski?=
Date: Thu, 16 Oct 2014 18:35:35 +0200
Subject: [PATCH 1/4] Added support for cert-only login without user and
password
---
auth.go | 13 +++++++++++++
connection.go | 19 +++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/auth.go b/auth.go
index 435c94b1..e9083bf2 100644
--- a/auth.go
+++ b/auth.go
@@ -48,8 +48,21 @@ func (auth *AMQPlainAuth) Response() string {
return fmt.Sprintf("LOGIN:%sPASSWORD:%s", auth.Username, auth.Password)
}
+// CertAuth for RabbitMQ-auth-mechanism-ssl.
+type CertAuth struct {
+}
+
+func (me *CertAuth) Mechanism() string {
+ return "EXTERNAL"
+}
+
+func (me *CertAuth) Response() string {
+ return fmt.Sprintf("\000*\000*")
+}
+
// Finds the first mechanism preferred by the client that the server supports.
func pickSASLMechanism(client []Authentication, serverMechanisms []string) (auth Authentication, ok bool) {
+
for _, auth = range client {
for _, mech := range serverMechanisms {
if auth.Mechanism() == mech {
diff --git a/connection.go b/connection.go
index 252852e8..506bcaed 100644
--- a/connection.go
+++ b/connection.go
@@ -155,6 +155,25 @@ func DialTLS(url string, amqps *tls.Config) (*Connection, error) {
TLSClientConfig: amqps,
Locale: defaultLocale,
})
+
+}
+
+// DialTLS_CertAuth accepts a string in the AMQP URI format and returns a new
+// Connection over TCP using EXTERNAL auth. Defaults to a server heartbeat
+// interval of 10 seconds and sets the initial read deadline to 30 seconds.
+//
+// This mechanism is used, when RabbitMQ is configured for EXTERNAL auth with
+// ssl_cert_login plugin for userless/passwordless logons
+//
+// DialTLS_CertAuth uses the provided tls.Config when encountering an amqps://
+// scheme.
+func DialTLS_CertAuth(url string, amqps *tls.Config) (*Connection, error) {
+
+ return DialConfig(url, Config{
+ Heartbeat: defaultHeartbeat,
+ TLSClientConfig: amqps,
+ SASL: []Authentication{&CertAuth{}},
+ })
}
// DialConfig accepts a string in the AMQP URI format and a configuration for
From 61673124ae180e0f84d5f4857c3863aeeabd3bc1 Mon Sep 17 00:00:00 2001
From: Ugurcan Ergun
Date: Fri, 26 Feb 2021 17:12:10 +0900
Subject: [PATCH 2/4] Made changes requested inside PR #121
---
auth.go | 12 ++++++------
connection.go | 41 +++++++++++++++++++++++++++++++++++------
examples_test.go | 30 ++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+), 12 deletions(-)
diff --git a/auth.go b/auth.go
index e9083bf2..266218ca 100644
--- a/auth.go
+++ b/auth.go
@@ -48,21 +48,21 @@ func (auth *AMQPlainAuth) Response() string {
return fmt.Sprintf("LOGIN:%sPASSWORD:%s", auth.Username, auth.Password)
}
-// CertAuth for RabbitMQ-auth-mechanism-ssl.
-type CertAuth struct {
+// ExternalAuth for RabbitMQ-auth-mechanism-ssl.
+type ExternalAuth struct {
}
-func (me *CertAuth) Mechanism() string {
+// Mechanism returns "EXTERNAL"
+func (me *ExternalAuth) Mechanism() string {
return "EXTERNAL"
}
-func (me *CertAuth) Response() string {
- return fmt.Sprintf("\000*\000*")
+func (me *ExternalAuth) Response() string {
+ return "\000*\000*"
}
// Finds the first mechanism preferred by the client that the server supports.
func pickSASLMechanism(client []Authentication, serverMechanisms []string) (auth Authentication, ok bool) {
-
for _, auth = range client {
for _, mech := range serverMechanisms {
if auth.Mechanism() == mech {
diff --git a/connection.go b/connection.go
index 506bcaed..df6959b6 100644
--- a/connection.go
+++ b/connection.go
@@ -130,6 +130,33 @@ func DefaultDial(connectionTimeout time.Duration) func(network, addr string) (ne
}
}
+type Option func(*Config) error
+
+// SetOptions set amqp connection options
+func (a *Config) SetOptions(opts ...Option) error {
+ for _, opt := range opts {
+ if err := opt(a); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func TLS(val *tls.Config) Option {
+ return func(t *Config) error {
+ t.TLSClientConfig = val
+ return nil
+ }
+}
+
+func Auth(val []Authentication) Option {
+ return func(t *Config) error {
+ t.SASL = val
+ return nil
+ }
+}
+
// Dial accepts a string in the AMQP URI format and returns a new Connection
// over TCP using PlainAuth. Defaults to a server heartbeat interval of 10
// seconds and sets the handshake deadline to 30 seconds. After handshake,
@@ -137,11 +164,13 @@ func DefaultDial(connectionTimeout time.Duration) func(network, addr string) (ne
//
// Dial uses the zero value of tls.Config when it encounters an amqps://
// scheme. It is equivalent to calling DialTLS(amqp, nil).
-func Dial(url string) (*Connection, error) {
- return DialConfig(url, Config{
+func Dial(url string, opts ...Option) (*Connection, error) {
+ config := Config{
Heartbeat: defaultHeartbeat,
Locale: defaultLocale,
- })
+ }
+ config.SetOptions(opts...)
+ return DialConfig(url, config)
}
// DialTLS accepts a string in the AMQP URI format and returns a new Connection
@@ -158,7 +187,7 @@ func DialTLS(url string, amqps *tls.Config) (*Connection, error) {
}
-// DialTLS_CertAuth accepts a string in the AMQP URI format and returns a new
+// DialTLSExternalAuth accepts a string in the AMQP URI format and returns a new
// Connection over TCP using EXTERNAL auth. Defaults to a server heartbeat
// interval of 10 seconds and sets the initial read deadline to 30 seconds.
//
@@ -167,12 +196,12 @@ func DialTLS(url string, amqps *tls.Config) (*Connection, error) {
//
// DialTLS_CertAuth uses the provided tls.Config when encountering an amqps://
// scheme.
-func DialTLS_CertAuth(url string, amqps *tls.Config) (*Connection, error) {
+func DialTLSExternalAuth(url string, amqps *tls.Config) (*Connection, error) {
return DialConfig(url, Config{
Heartbeat: defaultHeartbeat,
TLSClientConfig: amqps,
- SASL: []Authentication{&CertAuth{}},
+ SASL: []Authentication{&ExternalAuth{}},
})
}
diff --git a/examples_test.go b/examples_test.go
index 278a6dd1..4567228d 100644
--- a/examples_test.go
+++ b/examples_test.go
@@ -104,6 +104,36 @@ func ExampleDialTLS() {
log.Printf("conn: %v, err: %v", conn, err)
}
+func ExampleDialwithTLSandExternalAuth() {
+ // This example assumes you enabled the rabbitmq-auth-mechanism-ssl plugin
+ // and your RabbitMQ server has TLS enabled
+
+ // The username will be read from the DN or CN fields of the certificate
+ // you provide, you can see the more detailed information provided here
+ // https://github.com/rabbitmq/rabbitmq-auth-mechanism-ssl#username-extraction-from-certificate
+
+ cfg := new(tls.Config)
+
+ // see at the top
+ cfg.RootCAs = x509.NewCertPool()
+
+ if ca, err := ioutil.ReadFile("testca/cacert.pem"); err == nil {
+ cfg.RootCAs.AppendCertsFromPEM(ca)
+ }
+
+ // Move the client cert and key to a location specific to your application
+ // and load them here.
+
+ if cert, err := tls.LoadX509KeyPair("client/cert.pem", "client/key.pem"); err == nil {
+ cfg.Certificates = append(cfg.Certificates, cert)
+ }
+
+ // If you don't supply the Auth method as EXTERNAL, connection wouldn't fail and you will be logged in as the guest user.
+ conn, err := amqp.Dial("amqps://server-name-from-certificate/", amqp.TLS(cfg), amqp.Auth([]amqp.Authentication{&amqp.ExternalAuth{}}))
+
+ log.Printf("conn: %v, err: %v", conn, err)
+}
+
func ExampleChannel_Confirm_bridge() {
// This example acts as a bridge, shoveling all messages sent from the source
// exchange "log" to destination exchange "log".
From 990b989cab71111a39906b832ec62f2d432e10ac Mon Sep 17 00:00:00 2001
From: Ugurcan Ergun
Date: Fri, 26 Feb 2021 17:43:15 +0900
Subject: [PATCH 3/4] Corrected lint errors
---
auth.go | 1 +
connection.go | 3 +++
2 files changed, 4 insertions(+)
diff --git a/auth.go b/auth.go
index 266218ca..45f77e62 100644
--- a/auth.go
+++ b/auth.go
@@ -57,6 +57,7 @@ func (me *ExternalAuth) Mechanism() string {
return "EXTERNAL"
}
+// Response returns zero ?
func (me *ExternalAuth) Response() string {
return "\000*\000*"
}
diff --git a/connection.go b/connection.go
index df6959b6..38e3ab0f 100644
--- a/connection.go
+++ b/connection.go
@@ -130,6 +130,7 @@ func DefaultDial(connectionTimeout time.Duration) func(network, addr string) (ne
}
}
+// Option type for Dial
type Option func(*Config) error
// SetOptions set amqp connection options
@@ -143,6 +144,7 @@ func (a *Config) SetOptions(opts ...Option) error {
return nil
}
+// TLS is a wrapper for tls.Config to send as a Dial Option
func TLS(val *tls.Config) Option {
return func(t *Config) error {
t.TLSClientConfig = val
@@ -150,6 +152,7 @@ func TLS(val *tls.Config) Option {
}
}
+// Auth is a wrapper for SASL to send as a Dial Option
func Auth(val []Authentication) Option {
return func(t *Config) error {
t.SASL = val
From fbbcdd77a321bb26a29821813b5d0b7a37ec15f1 Mon Sep 17 00:00:00 2001
From: Ugurcan Ergun
Date: Fri, 26 Feb 2021 17:53:09 +0900
Subject: [PATCH 4/4] Changed test name
---
examples_test.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples_test.go b/examples_test.go
index 4567228d..4983816a 100644
--- a/examples_test.go
+++ b/examples_test.go
@@ -104,7 +104,7 @@ func ExampleDialTLS() {
log.Printf("conn: %v, err: %v", conn, err)
}
-func ExampleDialwithTLSandExternalAuth() {
+func ExampleDial_withTLSandExternalAuth() {
// This example assumes you enabled the rabbitmq-auth-mechanism-ssl plugin
// and your RabbitMQ server has TLS enabled