Skip to content

Add SASL mechanism ANONYMOUS (backport #11999) #12018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 15, 2024

Conversation

mergify[bot]
Copy link

@mergify mergify bot commented Aug 15, 2024

This PR is a breaking change for AMQP 1.0 and MQTT users, scheduled to ship in RabbitMQ 4.0.

Note that this PR also changes nothing around the intentional default connectivity restrictions for the default (anonymous connection) user. So the default security profile is not affected.

1. Introduce new SASL mechanism ANONYMOUS

What?

Introduce a new rabbit_auth_mechanism implementation for SASL
mechanism ANONYMOUS called rabbit_auth_mechanism_anonymous.

Why?

As described in AMQP section 5.3.3.1, ANONYMOUS should be used when the
client doesn't need to authenticate.

Introducing a new rabbit_auth_mechanism consolidates and simplifies how anonymous
logins work across all RabbitMQ protocols that support SASL. This commit
therefore allows AMQP 0.9.1, AMQP 1.0, stream clients to connect out of
the box to RabbitMQ without providing any username or password.

Today's AMQP 0.9.1 and stream protocol client libs hard code RabbitMQ default credentials
guest:guest for example done in:

Hard coding RabbitMQ specific default credentials in dozens of different
client libraries is an anti-pattern in my opinion.
Furthermore, there are various AMQP 1.0 and MQTT client libraries which
we do not control or maintain and which still should work out of the box
when a user is getting started with RabbitMQ (that is without
providing guest:guest credentials).

How?

The old RabbitMQ 3.13 AMQP 1.0 plugin default_user
configuration
is replaced with the following two new rabbit configurations:

{anonymous_login_user, <<"guest">>},
{anonymous_login_pass, <<"guest">>},

We call it anonymous_login_user because this user will be used for
anonymous logins. The subsequent commit uses the same setting for
anonymous logins in MQTT. Hence, this user is orthogonal to the protocol
used when the client connects.

Setting anonymous_login_pass could have been left out.
This commit decides to include it because our documentation has so far
recommended:

It is highly recommended to pre-configure a new user with a generated username and password or delete the guest user
or at least change its password to reasonably secure generated value that won't be known to the public.

By having the new module rabbit_auth_mechanism_anonymous internally
authenticate with anonymous_login_pass instead of blindly allowing
access without any password, we protect operators that relied on the
sentence:

or at least change its password to reasonably secure generated value that won't be known to the public

To ease the getting started experience, since RabbitMQ already deploys a
guest user with full access to the default virtual host /, this commit
also allows SASL mechanism ANONYMOUS in rabbit setting auth_mechanisms.

In production, operators should disable SASL mechanism ANONYMOUS by
setting anonymous_login_user to none (or by removing ANONYMOUS from
the auth_mechanisms setting). This is documented in rabbitmq/rabbitmq-website#2017.
Even if operators forget or don't read the docs, this new ANONYMOUS
mechanism won't do any harm because it relies on the default user name
guest and password guest, which is recommended against in
production, and who by default can only connect from the local host.

2. Require SASL security layer in AMQP 1.0

What?

An AMQP 1.0 client must use the SASL security layer.

Why?

This is in line with the mandatory usage of SASL in AMQP 0.9.1 and
RabbitMQ stream protocol.
Since (presumably) any AMQP 1.0 client knows how to authenticate with a
username and password using SASL mechanism PLAIN, any AMQP 1.0 client
also (presumably) implements the trivial SASL mechanism ANONYMOUS.

Skipping SASL is not recommended in production anyway.
By requiring SASL, configuration for operators becomes easier.
Following the principle of least surprise, when an an operator
configures auth_mechanisms to exclude ANONYMOUS, anonymous logins
will be prohibited in SASL and also by disallowing skipping the SASL
layer.

How?

This commit implements AMQP 1.0 figure 2.13.

A follow-up commit needs to be pushed to v3.13.x which will use SASL
mechanism anon instead of none in the Erlang AMQP 1.0 client
such that AMQP 1.0 shovels running on 3.13 can connect to 4.0 RabbitMQ nodes.

3. Remove mqtt.default_user and mqtt.default_pass

What?

Remove mqtt.default_user and mqtt.default_pass
Instead, rabbit.anonymous_login_user and rabbit.anonymous_login_pass should be used.

Why?

RabbitMQ 4.0 simplifies anonymous logins.
There is now a single configuration place

rabbit.anonymous_login_user
rabbit.anonymous_login_pass

that is used for anonymous logins for any protocol.

Anonymous login is orthogonal to the protocol the client uses.
Hence, there should be a single configuration place which can then be
used for MQTT, AMQP 1.0, AMQP 0.9.1, and RabbitMQ Stream protocol.

This will also simplify switching to SASL for MQTT 5.0 in the future.


This is an automatic backport of pull request #11999 done by Mergify.

ansd and others added 5 commits August 15, 2024 17:14
 ## 1. Introduce new SASL mechanism ANONYMOUS

 ### What?
Introduce a new `rabbit_auth_mechanism` implementation for SASL
mechanism ANONYMOUS called `rabbit_auth_mechanism_anonymous`.

 ### Why?
As described in AMQP section 5.3.3.1, ANONYMOUS should be used when the
client doesn't need to authenticate.

Introducing a new `rabbit_auth_mechanism` consolidates and simplifies how anonymous
logins work across all RabbitMQ protocols that support SASL. This commit
therefore allows AMQP 0.9.1, AMQP 1.0, stream clients to connect out of
the box to RabbitMQ without providing any username or password.

Today's AMQP 0.9.1 and stream protocol client libs hard code RabbitMQ default credentials
`guest:guest` for example done in:
* https://github.com/rabbitmq/rabbitmq-java-client/blob/0215e85643a9ae0800822869be0200024e2ab569/src/main/java/com/rabbitmq/client/ConnectionFactory.java#L58-L61
* https://github.com/rabbitmq/amqp091-go/blob/ddb7a2f0685689063e6d709b8e417dbf9d09469c/uri.go#L31-L32

Hard coding RabbitMQ specific default credentials in dozens of different
client libraries is an anti-pattern in my opinion.
Furthermore, there are various AMQP 1.0 and MQTT client libraries which
we do not control or maintain and which still should work out of the box
when a user is getting started with RabbitMQ (that is without
providing `guest:guest` credentials).

 ### How?
The old RabbitMQ 3.13 AMQP 1.0 plugin `default_user`
[configuration](https://github.com/rabbitmq/rabbitmq-server/blob/146b4862d8e570b344c99c37d91246760e218b18/deps/rabbitmq_amqp1_0/Makefile#L6)
is replaced with the following two new `rabbit` configurations:
```
{anonymous_login_user, <<"guest">>},
{anonymous_login_pass, <<"guest">>},
```
We call it `anonymous_login_user` because this user will be used for
anonymous logins. The subsequent commit uses the same setting for
anonymous logins in MQTT. Hence, this user is orthogonal to the protocol
used when the client connects.

Setting `anonymous_login_pass` could have been left out.
This commit decides to include it because our documentation has so far
recommended:
> It is highly recommended to pre-configure a new user with a generated username and password or delete the guest user
> or at least change its password to reasonably secure generated value that won't be known to the public.

By having the new module `rabbit_auth_mechanism_anonymous` internally
authenticate with `anonymous_login_pass` instead of blindly allowing
access without any password, we protect operators that relied on the
sentence:
> or at least change its password to reasonably secure generated value that won't be known to the public

To ease the getting started experience, since RabbitMQ already deploys a
guest user with full access to the default virtual host `/`, this commit
also allows SASL mechanism ANONYMOUS in `rabbit` setting `auth_mechanisms`.

In production, operators should disable SASL mechanism ANONYMOUS by
setting `anonymous_login_user` to `none` (or by removing ANONYMOUS from
the `auth_mechanisms` setting. This will be documented separately.
Even if operators forget or don't read the docs, this new ANONYMOUS
mechanism won't do any harm because it relies on the default user name
`guest` and password `guest`, which is recommended against in
production, and who by default can only connect from the local host.

 ## 2. Require SASL security layer in AMQP 1.0

 ### What?
An AMQP 1.0 client must use the SASL security layer.

 ### Why?
This is in line with the mandatory usage of SASL in AMQP 0.9.1 and
RabbitMQ stream protocol.
Since (presumably) any AMQP 1.0 client knows how to authenticate with a
username and password using SASL mechanism PLAIN, any AMQP 1.0 client
also (presumably) implements the trivial SASL mechanism ANONYMOUS.

Skipping SASL is not recommended in production anyway.
By requiring SASL, configuration for operators becomes easier.
Following the principle of least surprise, when an an operator
configures `auth_mechanisms` to exclude `ANONYMOUS`, anonymous logins
will be prohibited in SASL and also by disallowing skipping the SASL
layer.

 ### How?
This commit implements AMQP 1.0 figure 2.13.

A follow-up commit needs to be pushed to `v3.13.x` which will use SASL
mechanism `anon` instead of `none` in the Erlang AMQP 1.0 client
such that AMQP 1.0 shovels running on 3.13 can connect to 4.0 RabbitMQ nodes.

(cherry picked from commit d46f07c)
This commit is a breaking change in RabbitMQ 4.0.

 ## What?
Remove mqtt.default_user and mqtt.default_pass
Instead, rabbit.anonymous_login_user and rabbit.anonymous_login_pass
should be used.

 ## Why?
RabbitMQ 4.0 simplifies anonymous logins.
There should be a single configuration place
```
rabbit.anonymous_login_user
rabbit.anonymous_login_pass
```
that is used for anonymous logins for any protocol.

Anonymous login is orthogonal to the protocol the client uses.
Hence, there should be a single configuration place which can then be
used for MQTT, AMQP 1.0, AMQP 0.9.1, and RabbitMQ Stream protocol.

This will also simplify switching to SASL for MQTT 5.0 in the future.

(cherry picked from commit ba14b15)
(cherry picked from commit b09f2d4)
(cherry picked from commit e21a3bd)
@mergify mergify bot assigned ansd Aug 15, 2024
@michaelklishin michaelklishin merged commit 7b64132 into v4.0.x Aug 15, 2024
197 checks passed
@michaelklishin michaelklishin deleted the mergify/bp/v4.0.x/pr-11999 branch August 15, 2024 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants