Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio
- **Loki Scaler**: Limit HTTP error response logging ([#7469](https://github.com/kedacore/keda/pull/7469))
- **Prometheus Scaler**: Handle NaN results in the same manner as Inf ([#7475](https://github.com/kedacore/keda/issues/7475))
- **Prometheus Scaler**: Limit HTTP error response logging ([#7469](https://github.com/kedacore/keda/pull/7469))
- **RabbitMQ Scaler**: Use SASL EXTERNAL for RabbitMQ AMQP TLS without credentials ([#6840](https://github.com/kedacore/keda/issues/6840))
- **Solr Scaler**: Use net/url to safely encode query parameters ([#7467](https://github.com/kedacore/keda/pull/7467))

### Deprecations
Expand Down
44 changes: 31 additions & 13 deletions pkg/scalers/rabbitmq_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,19 +357,9 @@ func parseRabbitMQMetadata(config *scalersconfig.ScalerConfig) (*rabbitMQMetadat
// the given ceClient cert, ceClient key,and CA certificate. If clientKeyPassword is not empty the provided password will be used to
// decrypt the given key. If enableTLS is disabled then amqp connection will be created without tls.
func getConnectionAndChannel(host string, meta *rabbitMQMetadata) (*amqp.Connection, *amqp.Channel, error) {
amqpConfig := amqp.Config{
Properties: amqp.Table{
"connection_name": meta.connectionName,
},
}

if meta.EnableTLS == rmqTLSEnable {
tlsConfig, err := kedautil.NewTLSConfigWithPassword(meta.Cert, meta.Key, meta.KeyPassword, meta.Ca, meta.UnsafeSsl)
if err != nil {
return nil, nil, err
}

amqpConfig.TLSClientConfig = tlsConfig
amqpConfig, err := buildAMQPConfig(meta)
if err != nil {
return nil, nil, err
}

conn, err := amqp.DialConfig(host, amqpConfig)
Expand All @@ -385,6 +375,34 @@ func getConnectionAndChannel(host string, meta *rabbitMQMetadata) (*amqp.Connect
return conn, channel, nil
}

func buildAMQPConfig(meta *rabbitMQMetadata) (amqp.Config, error) {
Comment thread
rickbrouwer marked this conversation as resolved.
config := amqp.Config{
Properties: amqp.Table{
"connection_name": meta.connectionName,
},
}

if meta.EnableTLS == rmqTLSEnable {
tlsConfig, err := kedautil.NewTLSConfigWithPassword(meta.Cert, meta.Key, meta.KeyPassword, meta.Ca, meta.UnsafeSsl)
if err != nil {
return amqp.Config{}, err
}
config.TLSClientConfig = tlsConfig

if meta.Username == "" && meta.Password == "" {
useExternal := true
if u, err := url.Parse(meta.Host); err == nil && u.User != nil && u.User.Username() != "" {
useExternal = false
}
if useExternal {
config.SASL = []amqp.Authentication{&amqp.ExternalAuth{}}
Comment thread
wozniakjan marked this conversation as resolved.
}
Comment thread
rickbrouwer marked this conversation as resolved.
Outdated
}
Comment thread
rickbrouwer marked this conversation as resolved.
}

return config, nil
}

// Close disposes of RabbitMQ connections
func (s *rabbitMQScaler) Close(context.Context) error {
if s.connection != nil {
Expand Down
72 changes: 72 additions & 0 deletions pkg/scalers/rabbitmq_scaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -830,3 +830,75 @@ func TestConnectionName(t *testing.T) {
t.Error("Expected connection name to be keda-test-namespace-test-name but got", connectionName)
}
}

func TestRabbitMQBuildAMQPConfig(t *testing.T) {
tests := []struct {
name string
meta *rabbitMQMetadata
wantSASLMechanism string
wantSASLNil bool
}{
{
name: "TLS enabled without credentials uses EXTERNAL SASL",
meta: &rabbitMQMetadata{
EnableTLS: rmqTLSEnable,
Username: "",
Password: "",
},
wantSASLMechanism: "EXTERNAL",
},
{
name: "TLS enabled with credentials does not set SASL",
meta: &rabbitMQMetadata{
EnableTLS: rmqTLSEnable,
Username: "user",
Password: "pass",
},
wantSASLNil: true,
},
{
name: "TLS disabled does not set SASL",
meta: &rabbitMQMetadata{
EnableTLS: rmqTLSDisable,
Username: "",
Password: "",
},
wantSASLNil: true,
},
{
name: "TLS enabled with credentials in host URI does not set EXTERNAL",
meta: &rabbitMQMetadata{
EnableTLS: rmqTLSEnable,
Host: "amqps://user:pass@rabbit:5671/",
Username: "",
Password: "",
},
wantSASLNil: true,
},
{
Comment thread
rickbrouwer marked this conversation as resolved.
name: "TLS enabled, no credentials in host URI, uses EXTERNAL",
meta: &rabbitMQMetadata{
EnableTLS: rmqTLSEnable,
Host: "amqps://rabbit.namespace.svc:5671/",
Username: "",
Password: "",
},
wantSASLMechanism: "EXTERNAL",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config, err := buildAMQPConfig(tt.meta)
assert.NoError(t, err)

if tt.wantSASLNil {
assert.Nil(t, config.SASL)
return
}

assert.Len(t, config.SASL, 1)
assert.Equal(t, tt.wantSASLMechanism, config.SASL[0].Mechanism())
})
}
}
Loading