Merge branch 'main' into local-shovel
Peer Discovery AWS Integration Test / Integration Test (push) Has been cancelled
Details
Peer Discovery AWS Integration Test / Integration Test (push) Has been cancelled
Details
This commit is contained in:
commit
ce8fa317cf
|
@ -21,7 +21,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: CHECKOUT REPOSITORY
|
- name: CHECKOUT REPOSITORY
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
|
|
|
@ -14,7 +14,7 @@ env:
|
||||||
REGISTRY_IMAGE: pivotalrabbitmq/ibm-mqadvanced-server-dev
|
REGISTRY_IMAGE: pivotalrabbitmq/ibm-mqadvanced-server-dev
|
||||||
IBM_MQ_REPOSITORY: ibm-messaging/mq-container
|
IBM_MQ_REPOSITORY: ibm-messaging/mq-container
|
||||||
IBM_MQ_BRANCH_NAME: 9.4.0
|
IBM_MQ_BRANCH_NAME: 9.4.0
|
||||||
IMAGE_TAG: 9.4.0.5-amd64
|
IMAGE_TAG: 9.4.0.12-amd64
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -34,7 +34,7 @@ jobs:
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Checkout ibm-mqadvanced-server-dev
|
- name: Checkout ibm-mqadvanced-server-dev
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
repository: ${{ env.IBM_MQ_REPOSITORY }}
|
repository: ${{ env.IBM_MQ_REPOSITORY }}
|
||||||
ref: ${{ env.IBM_MQ_BRANCH_NAME }}
|
ref: ${{ env.IBM_MQ_BRANCH_NAME }}
|
||||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
ref: ${{ matrix.branch }}
|
ref: ${{ matrix.branch }}
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
@ -76,7 +76,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
ref: ${{ matrix.branch }}
|
ref: ${{ matrix.branch }}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ jobs:
|
||||||
fi
|
fi
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
if: steps.authorized.outputs.authorized == 'true'
|
if: steps.authorized.outputs.authorized == 'true'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
- name: Configure Erlang
|
- name: Configure Erlang
|
||||||
if: steps.authorized.outputs.authorized == 'true'
|
if: steps.authorized.outputs.authorized == 'true'
|
||||||
uses: erlef/setup-beam@v1
|
uses: erlef/setup-beam@v1
|
||||||
|
@ -82,7 +82,7 @@ jobs:
|
||||||
if: ${{ needs.build-package-generic-unix.outputs.authorized }} == 'true'
|
if: ${{ needs.build-package-generic-unix.outputs.authorized }} == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
- name: Download package-generic-unix
|
- name: Download package-generic-unix
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -30,7 +30,7 @@ jobs:
|
||||||
fi
|
fi
|
||||||
- name: CHECKOUT REPOSITORY
|
- name: CHECKOUT REPOSITORY
|
||||||
if: steps.authorized.outputs.authorized == 'true'
|
if: steps.authorized.outputs.authorized == 'true'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
- uses: docker/metadata-action@v5
|
- uses: docker/metadata-action@v5
|
||||||
if: steps.authorized.outputs.authorized == 'true'
|
if: steps.authorized.outputs.authorized == 'true'
|
||||||
id: metadata
|
id: metadata
|
||||||
|
|
|
@ -41,7 +41,7 @@ jobs:
|
||||||
DOCKER_NETWORK: rabbitmq_net
|
DOCKER_NETWORK: rabbitmq_net
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Configure OTP & Elixir
|
- name: Configure OTP & Elixir
|
||||||
uses: erlef/setup-beam@v1
|
uses: erlef/setup-beam@v1
|
||||||
|
|
|
@ -32,7 +32,7 @@ jobs:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: CHECKOUT REPOSITORY
|
- name: CHECKOUT REPOSITORY
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: FETCH TAGS
|
- name: FETCH TAGS
|
||||||
run: git fetch --tags
|
run: git fetch --tags
|
||||||
|
|
|
@ -31,7 +31,7 @@ jobs:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: CHECKOUT REPOSITORY
|
- name: CHECKOUT REPOSITORY
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: FETCH TAGS
|
- name: FETCH TAGS
|
||||||
run: git fetch --tags
|
run: git fetch --tags
|
||||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
||||||
DOCKER_NETWORK: rabbitmq_net
|
DOCKER_NETWORK: rabbitmq_net
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Configure OTP & Elixir
|
- name: Configure OTP & Elixir
|
||||||
uses: erlef/setup-beam@v1
|
uses: erlef/setup-beam@v1
|
||||||
|
|
|
@ -33,7 +33,7 @@ jobs:
|
||||||
DOCKER_NETWORK: rabbitmq_net
|
DOCKER_NETWORK: rabbitmq_net
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Configure OTP & Elixir
|
- name: Configure OTP & Elixir
|
||||||
uses: erlef/setup-beam@v1
|
uses: erlef/setup-beam@v1
|
||||||
|
|
59
PKG_LINUX.md
59
PKG_LINUX.md
|
@ -1,60 +1,3 @@
|
||||||
# Build RabbitMQ Packages using Linux
|
# Build RabbitMQ Packages using Linux
|
||||||
|
|
||||||
|
See [`rabbitmq/build-env-images`](https://github.com/rabbitmq/build-env-images) and [`rabbitmq/server-packages`](https://github.com/rabbitmq/server-packages?tab=readme-ov-file).
|
||||||
## Environment
|
|
||||||
|
|
||||||
Debian Jesse using this `Vagrantfile`:
|
|
||||||
|
|
||||||
```
|
|
||||||
$script = <<SCRIPT
|
|
||||||
export LANG='C.UTF-8'
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
echo 'deb http://cdn-fastly.deb.debian.org/debian jessie-backports main' >> /etc/apt/sources.list.d/backports.list
|
|
||||||
|
|
||||||
wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
|
|
||||||
dpkg -i erlang-solutions_1.0_all.deb
|
|
||||||
|
|
||||||
apt-get clean
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y --fix-missing --no-install-recommends \
|
|
||||||
build-essential \
|
|
||||||
ca-certificates \
|
|
||||||
debhelper \
|
|
||||||
dh-systemd \
|
|
||||||
elinks \
|
|
||||||
esl-erlang \
|
|
||||||
elixir \
|
|
||||||
fakeroot \
|
|
||||||
git \
|
|
||||||
libfile-fcntllock-perl \
|
|
||||||
mandoc \
|
|
||||||
nsis \
|
|
||||||
python-lxml \
|
|
||||||
python-markdown \
|
|
||||||
python-simplejson \
|
|
||||||
rpm \
|
|
||||||
rsync \
|
|
||||||
tofrodos \
|
|
||||||
unzip \
|
|
||||||
xmlto \
|
|
||||||
xsltproc \
|
|
||||||
zip \
|
|
||||||
curl
|
|
||||||
date > /etc/vagrant_provisioned_at
|
|
||||||
SCRIPT
|
|
||||||
|
|
||||||
Vagrant.configure('2') do |config|
|
|
||||||
config.vm.box = "debian/jessie64"
|
|
||||||
config.vm.hostname = 'DEBIAN-JESSIE64'
|
|
||||||
config.vm.provision 'shell', inline: $script
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
## Instructions
|
|
||||||
|
|
||||||
Bring up a Debian Jesse instance using Vagrant, or, use the provisioning script
|
|
||||||
on a Debian Jesse server of your own. When it is done running, all necessary
|
|
||||||
package build requirements for either `apt`-based or `rpm`-based distros will
|
|
||||||
be present. See the [`README.md`](README.md#tldr) document for instructions on
|
|
||||||
building packages.
|
|
||||||
|
|
123
PKG_WINDOWS.md
123
PKG_WINDOWS.md
|
@ -1,121 +1,6 @@
|
||||||
# Build RabbitMQ Windows Package using Windows
|
# Build RabbitMQ Windows Package
|
||||||
|
|
||||||
## Environment
|
The RabbitMQ Windows installer is produced on Linux, together
|
||||||
|
with the rest of the packages.
|
||||||
|
|
||||||
Windows 8.1 using this `Vagrantfile`:
|
See [`rabbitmq/build-env-images`](https://github.com/rabbitmq/build-env-images) and [`rabbitmq/server-packages`](https://github.com/rabbitmq/server-packages?tab=readme-ov-file).
|
||||||
|
|
||||||
```
|
|
||||||
Vagrant.configure("2") do |config|
|
|
||||||
config.vm.box = "inclusivedesign/windows81-eval-x64"
|
|
||||||
config.vm.provider "virtualbox" do |v|
|
|
||||||
v.gui = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that these steps should work on more recent versions of Windows as well.
|
|
||||||
If you have issues using a newer version of Windows, please provide full
|
|
||||||
details in a message to the
|
|
||||||
[`rabbitmq-users`](https://groups.google.com/forum/#!forum/rabbitmq-users)
|
|
||||||
mailing list.
|
|
||||||
|
|
||||||
## Initial Steps
|
|
||||||
|
|
||||||
Bring up the VM and go through the process of updating Windows and (optionall)
|
|
||||||
VirtualBox tools. You'll notice that the evaluation license is expired. Re-arm
|
|
||||||
it by running this command via an administrative prompt:
|
|
||||||
|
|
||||||
```
|
|
||||||
slmgr -rearm
|
|
||||||
```
|
|
||||||
|
|
||||||
This part of the process will take a while as Windows is updated. Go make some
|
|
||||||
coffee and check your email.
|
|
||||||
|
|
||||||
## Install Erlang and Elixir
|
|
||||||
|
|
||||||
Using Chocolatey is the easiest method to install the most recent version of
|
|
||||||
Erlang and Elixir. Install Chocolatey [using these
|
|
||||||
instructions](https://chocolatey.org/install#installing-chocolatey)
|
|
||||||
([link](https://chocolatey.org/install#installing-chocolatey)), then install
|
|
||||||
both Erlang and Elixir using this command from an *administrative* `cmd.exe` or
|
|
||||||
Powershell terminal:
|
|
||||||
|
|
||||||
```
|
|
||||||
choco install elixir which
|
|
||||||
```
|
|
||||||
|
|
||||||
To confirm installation, open a new command prompt and run the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
erl -version
|
|
||||||
elixir -v
|
|
||||||
which erl
|
|
||||||
which elixir
|
|
||||||
```
|
|
||||||
|
|
||||||
## Install MSYS2 and NSIS
|
|
||||||
|
|
||||||
Chocolatey is also an easy way to install `msys2` and the NSIS install script
|
|
||||||
builder. Run the following from an *administrative* command prompt:
|
|
||||||
|
|
||||||
```
|
|
||||||
choco install msys2 nsis
|
|
||||||
```
|
|
||||||
|
|
||||||
As a bonus, it will update your `msys2` installation for you during the initial
|
|
||||||
install process.
|
|
||||||
|
|
||||||
## Install MSYS2 packages
|
|
||||||
|
|
||||||
Start up an `msys2` shell by running the following command (does not have to be
|
|
||||||
admin):
|
|
||||||
|
|
||||||
```
|
|
||||||
C:\tools\msys64\msys2_shell.cmd
|
|
||||||
```
|
|
||||||
|
|
||||||
In that shell, install all of these dependencies. If you are prompted for
|
|
||||||
input, just hit ENTER to choose the default:
|
|
||||||
|
|
||||||
```
|
|
||||||
pacman -S --needed git make tar rsync python zip unzip dos2unix man
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build RabbitMQ
|
|
||||||
|
|
||||||
### Clone this repository
|
|
||||||
|
|
||||||
From within your MSYS2 shell:
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/rabbitmq/rabbitmq-server-release.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set `PATH`
|
|
||||||
|
|
||||||
```
|
|
||||||
export PATH="$PATH:/c/ProgramData/Chocolatey/bin:/c/ProgramData/Chocolatey/lib/Elixir/bin:/c/Program Files (x86)/NSIS/bin"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fetch and build deps
|
|
||||||
|
|
||||||
*Note:* as of this writing, RabbitMQ `3.7.8` is the latest version. Be sure to check out the tag appropriate for your use:
|
|
||||||
|
|
||||||
```
|
|
||||||
cd rabbitmq-server-release
|
|
||||||
|
|
||||||
# the following checks out the "next to be released" branch
|
|
||||||
# this branch and version 3.7.9 have a necessary fix for building
|
|
||||||
# on windows, see this: https://github.com/rabbitmq/rabbitmq-server-release/pull/89
|
|
||||||
|
|
||||||
git checkout v3.7.x
|
|
||||||
|
|
||||||
make deps
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build Windows package
|
|
||||||
|
|
||||||
```
|
|
||||||
make UNIX_TO_DOS=unix2dos package-windows
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# RabbitMQ Server Releases
|
# RabbitMQ Server Releases
|
||||||
|
|
||||||
See [`rabbitmq/server-packages`](https://github.com/rabbitmq/server-packages/).
|
See [`rabbitmq/build-env-images`](https://github.com/rabbitmq/build-env-images) and [`rabbitmq/server-packages`](https://github.com/rabbitmq/server-packages?tab=readme-ov-file).
|
||||||
|
|
|
@ -4,3 +4,6 @@
|
||||||
|
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
|
||||||
|
src/rabbit_amqp_sql_lexer.erl
|
||||||
|
src/rabbit_amqp_sql_parser.erl
|
||||||
|
|
|
@ -363,7 +363,7 @@ RMQ_ERLC_OPTS += -DTRACE_SUPERVISOR2=true
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# https://www.erlang.org/doc/apps/parsetools/leex.html#file/2
|
# https://www.erlang.org/doc/apps/parsetools/leex.html#file/2
|
||||||
export ERL_COMPILER_OPTIONS := deterministic
|
YRL_ERLC_OPTS ?= +deterministic
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Documentation.
|
# Documentation.
|
||||||
|
|
|
@ -52,6 +52,14 @@
|
||||||
{requires, pre_boot},
|
{requires, pre_boot},
|
||||||
{enables, external_infrastructure}]}).
|
{enables, external_infrastructure}]}).
|
||||||
|
|
||||||
|
-rabbit_boot_step({auth_backend_plugins_check,
|
||||||
|
[{description, "check configured auth plugins are enabled"},
|
||||||
|
{mfa, {rabbit_access_control,
|
||||||
|
ensure_auth_backends_are_enabled,
|
||||||
|
[]}},
|
||||||
|
{requires, pre_boot},
|
||||||
|
{enables, external_infrastructure}]}).
|
||||||
|
|
||||||
%% rabbit_alarm currently starts memory and disk space monitors
|
%% rabbit_alarm currently starts memory and disk space monitors
|
||||||
-rabbit_boot_step({rabbit_alarm,
|
-rabbit_boot_step({rabbit_alarm,
|
||||||
[{description, "alarm handler"},
|
[{description, "alarm handler"},
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||||
-include_lib("kernel/include/logger.hrl").
|
-include_lib("kernel/include/logger.hrl").
|
||||||
|
|
||||||
|
-export([ensure_auth_backends_are_enabled/0]).
|
||||||
-export([check_user_pass_login/2, check_user_login/2, check_user_login/3, check_user_loopback/2,
|
-export([check_user_pass_login/2, check_user_login/2, check_user_login/3, check_user_loopback/2,
|
||||||
check_vhost_access/4, check_resource_access/4, check_topic_access/4,
|
check_vhost_access/4, check_resource_access/4, check_topic_access/4,
|
||||||
check_user_id/2]).
|
check_user_id/2]).
|
||||||
|
@ -18,6 +19,141 @@
|
||||||
|
|
||||||
%%----------------------------------------------------------------------------
|
%%----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec ensure_auth_backends_are_enabled() -> Ret when
|
||||||
|
Ret :: ok | {error, Reason},
|
||||||
|
Reason :: string().
|
||||||
|
|
||||||
|
ensure_auth_backends_are_enabled() ->
|
||||||
|
{ok, AuthBackends} = application:get_env(rabbit, auth_backends),
|
||||||
|
ValidAuthBackends = filter_valid_auth_backend_configuration(
|
||||||
|
AuthBackends, []),
|
||||||
|
case ValidAuthBackends of
|
||||||
|
AuthBackends ->
|
||||||
|
ok;
|
||||||
|
[_ | _] ->
|
||||||
|
%% Some auth backend modules were filtered out because their
|
||||||
|
%% corresponding plugin is either unavailable or disabled. We
|
||||||
|
%% update the application environment variable so that
|
||||||
|
%% authentication and authorization do not try to use them.
|
||||||
|
?LOG_WARNING(
|
||||||
|
"Some configured backends were dropped because their "
|
||||||
|
"corresponding plugins are disabled. Please look at the "
|
||||||
|
"info messages above to learn which plugin(s) should be "
|
||||||
|
"enabled. Here is the list of auth backends kept after "
|
||||||
|
"filering:~n~p", [ValidAuthBackends]),
|
||||||
|
ok = application:set_env(rabbit, auth_backends, ValidAuthBackends),
|
||||||
|
ok;
|
||||||
|
[] ->
|
||||||
|
%% None of the auth backend modules are usable. Log an error and
|
||||||
|
%% abort the boot of RabbitMQ.
|
||||||
|
?LOG_ERROR(
|
||||||
|
"None of the configured auth backends are usable because "
|
||||||
|
"their corresponding plugins were not enabled. Please look "
|
||||||
|
"at the info messages above to learn which plugin(s) should "
|
||||||
|
"be enabled."),
|
||||||
|
{error,
|
||||||
|
"Authentication/authorization backends require plugins to be "
|
||||||
|
"enabled; see logs for details"}
|
||||||
|
end.
|
||||||
|
|
||||||
|
filter_valid_auth_backend_configuration(
|
||||||
|
[Mod | Rest], ValidAuthBackends)
|
||||||
|
when is_atom(Mod) ->
|
||||||
|
case is_auth_backend_module_enabled(Mod) of
|
||||||
|
true ->
|
||||||
|
ValidAuthBackends1 = [Mod | ValidAuthBackends],
|
||||||
|
filter_valid_auth_backend_configuration(Rest, ValidAuthBackends1);
|
||||||
|
false ->
|
||||||
|
filter_valid_auth_backend_configuration(Rest, ValidAuthBackends)
|
||||||
|
end;
|
||||||
|
filter_valid_auth_backend_configuration(
|
||||||
|
[{ModN, ModZ} = Mod | Rest], ValidAuthBackends)
|
||||||
|
when is_atom(ModN) andalso is_atom(ModZ) ->
|
||||||
|
%% Both auth backend modules must be usable to keep the entire pair.
|
||||||
|
IsModNEnabled = is_auth_backend_module_enabled(ModN),
|
||||||
|
IsModZEnabled = is_auth_backend_module_enabled(ModZ),
|
||||||
|
case IsModNEnabled andalso IsModZEnabled of
|
||||||
|
true ->
|
||||||
|
ValidAuthBackends1 = [Mod | ValidAuthBackends],
|
||||||
|
filter_valid_auth_backend_configuration(Rest, ValidAuthBackends1);
|
||||||
|
false ->
|
||||||
|
filter_valid_auth_backend_configuration(Rest, ValidAuthBackends)
|
||||||
|
end;
|
||||||
|
filter_valid_auth_backend_configuration(
|
||||||
|
[{ModN, ModZs} | Rest], ValidAuthBackends)
|
||||||
|
when is_atom(ModN) andalso is_list(ModZs) ->
|
||||||
|
%% The authentication backend module and at least on of the authorization
|
||||||
|
%% backend module must be usable to keep the entire pair.
|
||||||
|
%%
|
||||||
|
%% The list of authorization backend modules may be shorter than the
|
||||||
|
%% configured one after the filtering.
|
||||||
|
IsModNEnabled = is_auth_backend_module_enabled(ModN),
|
||||||
|
EnabledModZs = lists:filter(fun is_auth_backend_module_enabled/1, ModZs),
|
||||||
|
case IsModNEnabled andalso EnabledModZs =/= [] of
|
||||||
|
true ->
|
||||||
|
Mod1 = {ModN, EnabledModZs},
|
||||||
|
ValidAuthBackends1 = [Mod1 | ValidAuthBackends],
|
||||||
|
filter_valid_auth_backend_configuration(Rest, ValidAuthBackends1);
|
||||||
|
false ->
|
||||||
|
filter_valid_auth_backend_configuration(Rest, ValidAuthBackends)
|
||||||
|
end;
|
||||||
|
filter_valid_auth_backend_configuration([], ValidAuthBackends) ->
|
||||||
|
lists:reverse(ValidAuthBackends).
|
||||||
|
|
||||||
|
is_auth_backend_module_enabled(Mod) when is_atom(Mod) ->
|
||||||
|
%% We check if the module is provided by the core of RabbitMQ or a plugin,
|
||||||
|
%% and if that plugin is enabled.
|
||||||
|
{ok, Modules} = application:get_key(rabbit, modules),
|
||||||
|
case lists:member(Mod, Modules) of
|
||||||
|
true ->
|
||||||
|
true;
|
||||||
|
false ->
|
||||||
|
%% The module is not provided by RabbitMQ core. Let's query
|
||||||
|
%% plugins then.
|
||||||
|
case rabbit_plugins:which_plugin(Mod) of
|
||||||
|
{ok, PluginName} ->
|
||||||
|
%% FIXME: The definition of an "enabled plugin" in
|
||||||
|
%% `rabbit_plugins' varies from funtion to function.
|
||||||
|
%% Sometimes, it means the "rabbitmq-plugin enable
|
||||||
|
%% <plugin>" was executed, sometimes it means the plugin
|
||||||
|
%% is running.
|
||||||
|
%%
|
||||||
|
%% This function is a boot step and is executed before
|
||||||
|
%% plugin are started. Therefore, we can't rely on
|
||||||
|
%% `rabbit_plugins:is_enabled/1' because it uses the
|
||||||
|
%% latter definition of "the plugin is running, regardless
|
||||||
|
%% of if it is enabled or not".
|
||||||
|
%%
|
||||||
|
%% Therefore, we use `rabbit_plugins:enabled_plugins/0'
|
||||||
|
%% which lists explicitly enabled plugins. Unfortunately,
|
||||||
|
%% it won't include the implicitly enabled plugins (i.e,
|
||||||
|
%% plugins that are dependencies of explicitly enabled
|
||||||
|
%% plugins).
|
||||||
|
EnabledPlugins = rabbit_plugins:enabled_plugins(),
|
||||||
|
case lists:member(PluginName, EnabledPlugins) of
|
||||||
|
true ->
|
||||||
|
true;
|
||||||
|
false ->
|
||||||
|
?LOG_INFO(
|
||||||
|
"The `~ts` auth backend module is configured. "
|
||||||
|
"However, the `~ts` plugin must be enabled in "
|
||||||
|
"order to use this auth backend. Until then "
|
||||||
|
"it will be skipped during "
|
||||||
|
"authentication/authorization",
|
||||||
|
[Mod, PluginName]),
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
{error, no_provider} ->
|
||||||
|
?LOG_INFO(
|
||||||
|
"The `~ts` auth backend module is configured. "
|
||||||
|
"However, no plugins available provide this "
|
||||||
|
"module. Until then it will be skipped during "
|
||||||
|
"authentication/authorization",
|
||||||
|
[Mod]),
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
-spec check_user_pass_login
|
-spec check_user_pass_login
|
||||||
(rabbit_types:username(), rabbit_types:password()) ->
|
(rabbit_types:username(), rabbit_types:password()) ->
|
||||||
{'ok', rabbit_types:user()} |
|
{'ok', rabbit_types:user()} |
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -782,12 +782,15 @@ get_stable_feature_flags(#{feature_flags := FeatureFlags}) ->
|
||||||
%% There are two ways to specify that list:
|
%% There are two ways to specify that list:
|
||||||
%% <ol>
|
%% <ol>
|
||||||
%% <li>Using the `$RABBITMQ_FEATURE_FLAGS' environment variable; for
|
%% <li>Using the `$RABBITMQ_FEATURE_FLAGS' environment variable; for
|
||||||
%% instance `RABBITMQ_FEATURE_FLAGS=quorum_queue,mnevis'.</li>
|
%% instance `RABBITMQ_FEATURE_FLAGS=rabbitmq_4.0.0,khepri_db'.</li>
|
||||||
%% <li>Using the `forced_feature_flags_on_init' configuration parameter;
|
%% <li>Using the `forced_feature_flags_on_init' configuration parameter;
|
||||||
%% for instance
|
%% for instance
|
||||||
%% `{rabbit, [{forced_feature_flags_on_init, [quorum_queue, mnevis]}]}'.</li>
|
%% `{rabbit, [{forced_feature_flags_on_init, [rabbitmq_4.0.0, khepri_db]}]}'.</li>
|
||||||
%% </ol>
|
%% </ol>
|
||||||
%%
|
%%
|
||||||
|
%% There's also a way to enable specific flags and skip others:
|
||||||
|
%% `{rabbit, [{forced_feature_flags_on_init, {rel, ListToEnable, ListToSkip}}]}'.
|
||||||
|
%%
|
||||||
%% The environment variable has precedence over the configuration parameter.
|
%% The environment variable has precedence over the configuration parameter.
|
||||||
%%
|
%%
|
||||||
%% @private
|
%% @private
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
-module(rabbit_plugins).
|
-module(rabbit_plugins).
|
||||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||||
-include_lib("kernel/include/logger.hrl").
|
-include_lib("kernel/include/logger.hrl").
|
||||||
-export([setup/0, active/0, read_enabled/1, list/1, list/2, dependencies/3, running_plugins/0]).
|
-export([setup/0, active/0, read_enabled/1, list/0, list/1, list/2, dependencies/3, running_plugins/0]).
|
||||||
-export([ensure/1]).
|
-export([ensure/1]).
|
||||||
-export([validate_plugins/1, format_invalid_plugins/1]).
|
-export([validate_plugins/1, format_invalid_plugins/1]).
|
||||||
-export([is_strictly_plugin/1, strictly_plugins/2, strictly_plugins/1]).
|
-export([is_strictly_plugin/1, strictly_plugins/2, strictly_plugins/1]).
|
||||||
-export([plugins_dir/0, plugin_names/1, plugins_expand_dir/0, enabled_plugins_file/0]).
|
-export([plugins_dir/0, plugin_names/1, plugins_expand_dir/0, enabled_plugins_file/0]).
|
||||||
-export([is_enabled/1, is_enabled_on_node/2]).
|
-export([is_enabled/1, is_enabled_on_node/2, enabled_plugins/0]).
|
||||||
|
-export([which_plugin/1]).
|
||||||
|
|
||||||
% Export for testing purpose.
|
% Export for testing purpose.
|
||||||
-export([is_version_supported/2, validate_plugins/2]).
|
-export([is_version_supported/2, validate_plugins/2]).
|
||||||
|
@ -130,7 +131,7 @@ setup() ->
|
||||||
-spec active() -> [plugin_name()].
|
-spec active() -> [plugin_name()].
|
||||||
|
|
||||||
active() ->
|
active() ->
|
||||||
InstalledPlugins = plugin_names(list(plugins_dir())),
|
InstalledPlugins = plugin_names(list()),
|
||||||
[App || {App, _, _} <- rabbit_misc:which_applications(),
|
[App || {App, _, _} <- rabbit_misc:which_applications(),
|
||||||
lists:member(App, InstalledPlugins)].
|
lists:member(App, InstalledPlugins)].
|
||||||
|
|
||||||
|
@ -157,6 +158,13 @@ is_enabled_on_node(Name, Node) ->
|
||||||
_Class:_Reason:_Stacktrace -> false
|
_Class:_Reason:_Stacktrace -> false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec list() -> [#plugin{}].
|
||||||
|
%% @doc Get the list of plugins from the configured plugin path.
|
||||||
|
|
||||||
|
list() ->
|
||||||
|
PluginsPath = plugins_dir(),
|
||||||
|
list(PluginsPath).
|
||||||
|
|
||||||
%% @doc Get the list of plugins which are ready to be enabled.
|
%% @doc Get the list of plugins which are ready to be enabled.
|
||||||
|
|
||||||
-spec list(string()) -> [#plugin{}].
|
-spec list(string()) -> [#plugin{}].
|
||||||
|
@ -228,7 +236,7 @@ strictly_plugins(Plugins, AllPlugins) ->
|
||||||
-spec strictly_plugins([plugin_name()]) -> [plugin_name()].
|
-spec strictly_plugins([plugin_name()]) -> [plugin_name()].
|
||||||
|
|
||||||
strictly_plugins(Plugins) ->
|
strictly_plugins(Plugins) ->
|
||||||
AllPlugins = list(plugins_dir()),
|
AllPlugins = list(),
|
||||||
lists:filter(
|
lists:filter(
|
||||||
fun(Name) ->
|
fun(Name) ->
|
||||||
is_strictly_plugin(lists:keyfind(Name, #plugin.name, AllPlugins))
|
is_strictly_plugin(lists:keyfind(Name, #plugin.name, AllPlugins))
|
||||||
|
@ -279,11 +287,61 @@ running_plugins() ->
|
||||||
ActivePlugins = active(),
|
ActivePlugins = active(),
|
||||||
{ok, [{App, Vsn} || {App, _ , Vsn} <- rabbit_misc:which_applications(), lists:member(App, ActivePlugins)]}.
|
{ok, [{App, Vsn} || {App, _ , Vsn} <- rabbit_misc:which_applications(), lists:member(App, ActivePlugins)]}.
|
||||||
|
|
||||||
|
-spec which_plugin(Module) -> Ret when
|
||||||
|
Module :: module(),
|
||||||
|
Ret :: {ok, PluginName} | {error, Reason},
|
||||||
|
PluginName :: atom(),
|
||||||
|
Reason :: no_provider.
|
||||||
|
%% @doc Returns the name of the plugin that provides the given module.
|
||||||
|
%%
|
||||||
|
%% If no plugin provides the module, `{error, no_provider}' is returned.
|
||||||
|
%%
|
||||||
|
%% The returned plugin might not be enabled, thus using the given module might
|
||||||
|
%% not work until the plugin is enabled.
|
||||||
|
%%
|
||||||
|
%% @returns An `{ok, PluginName}' tuple with the name of the plugin providing
|
||||||
|
%% the module, or `{error, no_provider}'.
|
||||||
|
|
||||||
|
which_plugin(Module) ->
|
||||||
|
Plugins = list(),
|
||||||
|
which_plugin(Plugins, Module).
|
||||||
|
|
||||||
|
which_plugin([#plugin{name = Name} | Rest], Module) ->
|
||||||
|
%% Get the list of modules belonging to this plugin.
|
||||||
|
ModulesKey = case application:get_key(Name, modules) of
|
||||||
|
{ok, _} = Ret ->
|
||||||
|
Ret;
|
||||||
|
undefined ->
|
||||||
|
%% The plugin application might not be loaded. Load
|
||||||
|
%% it temporarily and try again.
|
||||||
|
case application:load(Name) of
|
||||||
|
ok ->
|
||||||
|
Ret = application:get_key(Name, modules),
|
||||||
|
_ = application:unload(Name),
|
||||||
|
Ret;
|
||||||
|
{error, _Reason} ->
|
||||||
|
undefined
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
case ModulesKey of
|
||||||
|
{ok, Modules} ->
|
||||||
|
case lists:member(Module, Modules) of
|
||||||
|
true ->
|
||||||
|
{ok, Name};
|
||||||
|
false ->
|
||||||
|
which_plugin(Rest, Module)
|
||||||
|
end;
|
||||||
|
undefined ->
|
||||||
|
which_plugin(Rest, Module)
|
||||||
|
end;
|
||||||
|
which_plugin([], _Module) ->
|
||||||
|
{error, no_provider}.
|
||||||
|
|
||||||
%%----------------------------------------------------------------------------
|
%%----------------------------------------------------------------------------
|
||||||
|
|
||||||
prepare_plugins(Enabled) ->
|
prepare_plugins(Enabled) ->
|
||||||
ExpandDir = plugins_expand_dir(),
|
ExpandDir = plugins_expand_dir(),
|
||||||
AllPlugins = list(plugins_dir()),
|
AllPlugins = list(),
|
||||||
Wanted = dependencies(false, Enabled, AllPlugins),
|
Wanted = dependencies(false, Enabled, AllPlugins),
|
||||||
WantedPlugins = lookup_plugins(Wanted, AllPlugins),
|
WantedPlugins = lookup_plugins(Wanted, AllPlugins),
|
||||||
{ValidPlugins, Problems} = validate_plugins(WantedPlugins),
|
{ValidPlugins, Problems} = validate_plugins(WantedPlugins),
|
||||||
|
@ -695,20 +753,6 @@ remove_plugins(Plugins) ->
|
||||||
IsAPlugin =
|
IsAPlugin =
|
||||||
lists:member(Plugin, ActualPlugins) orelse
|
lists:member(Plugin, ActualPlugins) orelse
|
||||||
lists:member(Name, PluginDeps),
|
lists:member(Name, PluginDeps),
|
||||||
if
|
|
||||||
IsOTPApp ->
|
|
||||||
?LOG_DEBUG(
|
|
||||||
"Plugins discovery: "
|
|
||||||
"ignoring ~ts, Erlang/OTP application",
|
|
||||||
[Name]);
|
|
||||||
not IsAPlugin ->
|
|
||||||
?LOG_DEBUG(
|
|
||||||
"Plugins discovery: "
|
|
||||||
"ignoring ~ts, not a RabbitMQ plugin",
|
|
||||||
[Name]);
|
|
||||||
true ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
not (IsOTPApp orelse not IsAPlugin)
|
not (IsOTPApp orelse not IsAPlugin)
|
||||||
end, Plugins).
|
end, Plugins).
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
-include_lib("common_test/include/ct.hrl").
|
-include_lib("common_test/include/ct.hrl").
|
||||||
-include_lib("amqp_client/include/amqp_client.hrl").
|
-include_lib("amqp_client/include/amqp_client.hrl").
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
-include_lib("rabbitmq_ct_helpers/include/rabbit_assert.hrl").
|
||||||
|
|
||||||
-compile(nowarn_export_all).
|
-compile(nowarn_export_all).
|
||||||
-compile(export_all).
|
-compile(export_all).
|
||||||
|
@ -41,7 +42,8 @@ groups() ->
|
||||||
[{cluster_size_3, [], [
|
[{cluster_size_3, [], [
|
||||||
force_standalone_boot,
|
force_standalone_boot,
|
||||||
force_standalone_boot_and_restart,
|
force_standalone_boot_and_restart,
|
||||||
force_standalone_boot_and_restart_with_quorum_queues
|
force_standalone_boot_and_restart_with_quorum_queues,
|
||||||
|
recover_after_partition_with_leader
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{clustered_5_nodes, [],
|
{clustered_5_nodes, [],
|
||||||
|
@ -66,7 +68,9 @@ suite() ->
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
init_per_suite(Config) ->
|
||||||
rabbit_ct_helpers:log_environment(),
|
rabbit_ct_helpers:log_environment(),
|
||||||
rabbit_ct_helpers:run_setup_steps(Config).
|
rabbit_ct_helpers:run_setup_steps(
|
||||||
|
Config,
|
||||||
|
[fun rabbit_ct_broker_helpers:configure_dist_proxy/1]).
|
||||||
|
|
||||||
end_per_suite(Config) ->
|
end_per_suite(Config) ->
|
||||||
rabbit_ct_helpers:run_teardown_steps(Config).
|
rabbit_ct_helpers:run_teardown_steps(Config).
|
||||||
|
@ -249,6 +253,172 @@ force_standalone_boot_and_restart_with_quorum_queues(Config) ->
|
||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
recover_after_partition_with_leader(Config) ->
|
||||||
|
Nodes = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
|
||||||
|
|
||||||
|
%% We use intermediate Erlang nodes between the common_test control node
|
||||||
|
%% and the RabbitMQ nodes, using `peer' standard_io communication. The goal
|
||||||
|
%% is to make sure the common_test control node doesn't interfere with the
|
||||||
|
%% nodes the RabbitMQ nodes can see, despite the blocking of the Erlang
|
||||||
|
%% distribution connection.
|
||||||
|
Proxies0 = [begin
|
||||||
|
{ok, Proxy, PeerNode} = peer:start_link(
|
||||||
|
#{name => peer:random_name(),
|
||||||
|
connection => standard_io,
|
||||||
|
wait_boot => 120000}),
|
||||||
|
ct:pal("Proxy ~0p -> ~0p", [Proxy, PeerNode]),
|
||||||
|
Proxy
|
||||||
|
end || _ <- Nodes],
|
||||||
|
Proxies = maps:from_list(lists:zip(Nodes, Proxies0)),
|
||||||
|
ct:pal("Proxies: ~p", [Proxies]),
|
||||||
|
Config1 = [{proxies, Proxies} | Config],
|
||||||
|
|
||||||
|
NodeA = hd(Nodes),
|
||||||
|
|
||||||
|
ct:pal("Prevent automatic reconnection on the common_test node"),
|
||||||
|
application:set_env(kernel, dist_auto_connect, never),
|
||||||
|
ct:pal("Disconnect the common_test node from RabbitMQ nodes"),
|
||||||
|
lists:foreach(fun erlang:disconnect_node/1, Nodes),
|
||||||
|
ct:pal(
|
||||||
|
"Ensure RabbitMQ nodes only know about the RabbitMQ nodes "
|
||||||
|
"(and their proxy)"),
|
||||||
|
lists:foreach(
|
||||||
|
fun(Node) ->
|
||||||
|
?awaitMatch(
|
||||||
|
Nodes,
|
||||||
|
get_connected_nodes(Config1, Node),
|
||||||
|
30000)
|
||||||
|
end, Nodes),
|
||||||
|
|
||||||
|
ct:pal("Wait for a Khepri leader to be elected"),
|
||||||
|
?awaitMatch({ok, _}, get_leader_node(Config1, NodeA), 30000),
|
||||||
|
|
||||||
|
ct:pal("Query the Khepri leader nodename"),
|
||||||
|
{ok, Leader} = get_leader_node(Config1, NodeA),
|
||||||
|
Followers = Nodes -- [Leader],
|
||||||
|
ct:pal("Leader: ~0p~nFollowers: ~p", [Leader, Followers]),
|
||||||
|
|
||||||
|
lists:foreach(
|
||||||
|
fun(Follower) ->
|
||||||
|
ct:pal(
|
||||||
|
?LOW_IMPORTANCE,
|
||||||
|
"Blocking traffic between ~ts and ~ts",
|
||||||
|
[Leader, Follower]),
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
proxied_rpc(
|
||||||
|
Config1, Leader, inet_tcp_proxy_dist, block, [Follower])),
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
proxied_rpc(
|
||||||
|
Config1, Follower, inet_tcp_proxy_dist, block, [Leader]))
|
||||||
|
end, Followers),
|
||||||
|
|
||||||
|
ct:pal(
|
||||||
|
"Ensure the leader node is disconnected from other RabbitMQ nodes"),
|
||||||
|
?awaitMatch(
|
||||||
|
[Leader],
|
||||||
|
get_connected_nodes(Config1, Leader),
|
||||||
|
30000),
|
||||||
|
ct:pal(
|
||||||
|
"Ensure the follower nodes are disconnected from the leader node"),
|
||||||
|
lists:foreach(
|
||||||
|
fun(Follower) ->
|
||||||
|
?awaitMatch(
|
||||||
|
Followers,
|
||||||
|
get_connected_nodes(Config1, Follower),
|
||||||
|
30000)
|
||||||
|
end, Followers),
|
||||||
|
|
||||||
|
ct:pal("Wait for each side of the partition to have its own leader"),
|
||||||
|
Follower1 = hd(Followers),
|
||||||
|
?awaitMatch(
|
||||||
|
false,
|
||||||
|
begin
|
||||||
|
LeaderA = get_leader_node(Config1, Leader),
|
||||||
|
LeaderB = get_leader_node(Config1, Follower1),
|
||||||
|
ct:pal("LeaderA: ~0p~nLeaderB: ~0p", [LeaderA, LeaderB]),
|
||||||
|
LeaderA =:= LeaderB
|
||||||
|
end,
|
||||||
|
30000),
|
||||||
|
|
||||||
|
ct:pal("Waiting for 2 minutes"),
|
||||||
|
timer:sleep(120000),
|
||||||
|
|
||||||
|
ct:pal("Query Khepri status for each RabbitMQ node"),
|
||||||
|
PerNodeStatus1 = get_per_node_khepri_status(Config1),
|
||||||
|
ct:pal("Per-node Khepri status (during partition):~n~p", [PerNodeStatus1]),
|
||||||
|
|
||||||
|
lists:foreach(
|
||||||
|
fun(Follower) ->
|
||||||
|
ct:pal(
|
||||||
|
?LOW_IMPORTANCE,
|
||||||
|
"Unblocking traffic between ~ts and ~ts",
|
||||||
|
[Leader, Follower]),
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
proxied_rpc(
|
||||||
|
Config1, Leader, inet_tcp_proxy_dist, allow, [Follower])),
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
proxied_rpc(
|
||||||
|
Config1, Follower, inet_tcp_proxy_dist, allow, [Leader]))
|
||||||
|
end, Followers),
|
||||||
|
|
||||||
|
ct:pal("Wait for the whole cluster to agree on the same leader"),
|
||||||
|
?awaitMatch(
|
||||||
|
true,
|
||||||
|
begin
|
||||||
|
LeaderA = get_leader_node(Config1, Leader),
|
||||||
|
LeaderB = get_leader_node(Config1, Follower1),
|
||||||
|
ct:pal("LeaderA: ~0p~nLeaderB: ~0p", [LeaderA, LeaderB]),
|
||||||
|
LeaderA =:= LeaderB
|
||||||
|
end,
|
||||||
|
30000),
|
||||||
|
|
||||||
|
ct:pal("Query Khepri status for each RabbitMQ node"),
|
||||||
|
PerNodeStatus2 = get_per_node_khepri_status(Config1),
|
||||||
|
ct:pal("Per-node Khepri status (after recovery):~n~p", [PerNodeStatus2]),
|
||||||
|
|
||||||
|
ct:pal("Restore automatic reconnection on the common_test node"),
|
||||||
|
application:unset_env(kernel, dist_auto_connect),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
proxied_rpc(Config, Node, Module, Function, Args) ->
|
||||||
|
Proxies = ?config(proxies, Config),
|
||||||
|
Proxy = maps:get(Node, Proxies),
|
||||||
|
peer:call(
|
||||||
|
Proxy, rabbit_ct_broker_helpers, rpc,
|
||||||
|
[Config, Node, Module, Function, Args]).
|
||||||
|
|
||||||
|
get_leader_node(Config, Node) ->
|
||||||
|
StoreId = rabbit_khepri:get_store_id(),
|
||||||
|
Ret = proxied_rpc(
|
||||||
|
Config, Node,
|
||||||
|
ra_leaderboard, lookup_leader, [StoreId]),
|
||||||
|
case Ret of
|
||||||
|
{StoreId, LeaderNode} ->
|
||||||
|
{ok, LeaderNode};
|
||||||
|
undefined ->
|
||||||
|
{error, no_leader}
|
||||||
|
end.
|
||||||
|
|
||||||
|
get_connected_nodes(Config, Node) ->
|
||||||
|
Proxies = ?config(proxies, Config),
|
||||||
|
Proxy = maps:get(Node, Proxies),
|
||||||
|
Peer = peer:call(Proxy, erlang, node, []),
|
||||||
|
OtherNodes = proxied_rpc(Config, Node, erlang, nodes, []),
|
||||||
|
lists:sort([Node | OtherNodes -- [Peer]]).
|
||||||
|
|
||||||
|
get_per_node_khepri_status(Config) ->
|
||||||
|
Nodes = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
|
||||||
|
maps:from_list(
|
||||||
|
lists:map(
|
||||||
|
fun(Node) ->
|
||||||
|
Status = proxied_rpc(Config, Node, rabbit_khepri, status, []),
|
||||||
|
{Node, Status}
|
||||||
|
end, Nodes)).
|
||||||
|
|
||||||
rolling_restart(Config) ->
|
rolling_restart(Config) ->
|
||||||
Nodes = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
|
Nodes = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
|
||||||
|
|
||||||
|
|
|
@ -2,34 +2,54 @@
|
||||||
%% License, v. 2.0. If a copy of the MPL was not distributed with this
|
%% License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
%%
|
%%
|
||||||
%% Copyright (c) 2024 Broadcom. All Rights Reserved.
|
%% Copyright (c) 2024-2025 Broadcom. All Rights Reserved.
|
||||||
%% The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
|
%% The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
||||||
-module(rabbit_access_control_SUITE).
|
-module(rabbit_access_control_SUITE).
|
||||||
|
|
||||||
-compile(export_all).
|
|
||||||
|
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
-include_lib("common_test/include/ct.hrl").
|
||||||
|
-include_lib("rabbitmq_ct_helpers/include/rabbit_assert.hrl").
|
||||||
|
|
||||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||||
|
|
||||||
|
-export([all/0,
|
||||||
|
groups/0,
|
||||||
|
init_per_suite/1,
|
||||||
|
end_per_suite/1,
|
||||||
|
init_per_group/2,
|
||||||
|
end_per_group/2,
|
||||||
|
init_per_testcase/2,
|
||||||
|
end_per_testcase/2,
|
||||||
|
|
||||||
|
expiry_timestamp/1,
|
||||||
|
with_enabled_plugin/1,
|
||||||
|
with_enabled_plugin_plus_internal/1,
|
||||||
|
with_missing_plugin/1,
|
||||||
|
with_missing_plugin_plus_internal/1,
|
||||||
|
with_disabled_plugin/1,
|
||||||
|
with_disabled_plugin_plus_internal/1
|
||||||
|
]).
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Common Test callbacks
|
%%% Common Test callbacks
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
|
||||||
|
|
||||||
all() ->
|
all() ->
|
||||||
[{group, tests}].
|
[{group, unit_tests},
|
||||||
|
{group, integration_tests}].
|
||||||
%% replicate eunit like test resolution
|
|
||||||
all_tests() ->
|
|
||||||
[F
|
|
||||||
|| {F, _} <- ?MODULE:module_info(functions),
|
|
||||||
re:run(atom_to_list(F), "_test$") /= nomatch].
|
|
||||||
|
|
||||||
groups() ->
|
groups() ->
|
||||||
[{tests, [], all_tests()}].
|
[{unit_tests, [], [expiry_timestamp]},
|
||||||
|
{integration_tests, [], [with_enabled_plugin,
|
||||||
|
with_enabled_plugin_plus_internal,
|
||||||
|
with_missing_plugin,
|
||||||
|
with_missing_plugin_plus_internal,
|
||||||
|
with_disabled_plugin,
|
||||||
|
with_disabled_plugin_plus_internal]}].
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
init_per_suite(Config) ->
|
||||||
Config.
|
Config.
|
||||||
|
@ -37,20 +57,74 @@ init_per_suite(Config) ->
|
||||||
end_per_suite(_Config) ->
|
end_per_suite(_Config) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
init_per_group(integration_tests, Config) ->
|
||||||
|
rabbit_ct_helpers:log_environment(),
|
||||||
|
rabbit_ct_helpers:run_setup_steps(Config);
|
||||||
init_per_group(_Group, Config) ->
|
init_per_group(_Group, Config) ->
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
|
end_per_group(integration_tests, Config) ->
|
||||||
|
rabbit_ct_helpers:run_teardown_steps(Config);
|
||||||
end_per_group(_Group, _Config) ->
|
end_per_group(_Group, _Config) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
init_per_testcase(Testcase, Config)
|
||||||
|
when Testcase =:= with_missing_plugin orelse
|
||||||
|
Testcase =:= with_missing_plugin_plus_internal ->
|
||||||
|
rabbit_ct_helpers:testcase_started(Config, Testcase),
|
||||||
|
do_init_per_testcase(Testcase, Config, []);
|
||||||
|
init_per_testcase(Testcase, Config)
|
||||||
|
when Testcase =:= with_enabled_plugin orelse
|
||||||
|
Testcase =:= with_enabled_plugin_plus_internal orelse
|
||||||
|
Testcase =:= with_disabled_plugin orelse
|
||||||
|
Testcase =:= with_disabled_plugin_plus_internal ->
|
||||||
|
rabbit_ct_helpers:testcase_started(Config, Testcase),
|
||||||
|
do_init_per_testcase(Testcase, Config, [fun prepare_my_plugin/1]);
|
||||||
init_per_testcase(_TestCase, Config) ->
|
init_per_testcase(_TestCase, Config) ->
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
|
do_init_per_testcase(Testcase, Config, PrepSteps) ->
|
||||||
|
rabbit_ct_helpers:testcase_started(Config, Testcase),
|
||||||
|
TestNumber = rabbit_ct_helpers:testcase_number(Config, ?MODULE, Testcase),
|
||||||
|
ClusterSize = 1,
|
||||||
|
Config1 = rabbit_ct_helpers:set_config(
|
||||||
|
Config,
|
||||||
|
[{rmq_nodename_suffix, Testcase},
|
||||||
|
{rmq_nodes_count, ClusterSize},
|
||||||
|
{tcp_ports_base, {skip_n_nodes, TestNumber * ClusterSize}},
|
||||||
|
{start_rmq_with_plugins_disabled, true}]),
|
||||||
|
Config2 = rabbit_ct_helpers:merge_app_env(
|
||||||
|
Config1,
|
||||||
|
{rabbit,
|
||||||
|
[{log, [{file, [{level, debug}]}]}]}),
|
||||||
|
Config3 = rabbit_ct_helpers:run_steps(
|
||||||
|
Config2,
|
||||||
|
PrepSteps ++
|
||||||
|
rabbit_ct_broker_helpers:setup_steps() ++
|
||||||
|
rabbit_ct_client_helpers:setup_steps()),
|
||||||
|
Config3.
|
||||||
|
|
||||||
|
end_per_testcase(Testcase, Config)
|
||||||
|
when Testcase =:= with_enabled_plugin orelse
|
||||||
|
Testcase =:= with_enabled_plugin_plus_internal orelse
|
||||||
|
Testcase =:= with_missing_plugin orelse
|
||||||
|
Testcase =:= with_missing_plugin_plus_internal orelse
|
||||||
|
Testcase =:= with_disabled_plugin orelse
|
||||||
|
Testcase =:= with_disabled_plugin_plus_internal ->
|
||||||
|
Config1 = rabbit_ct_helpers:run_steps(
|
||||||
|
Config,
|
||||||
|
rabbit_ct_client_helpers:teardown_steps() ++
|
||||||
|
rabbit_ct_broker_helpers:teardown_steps()),
|
||||||
|
rabbit_ct_helpers:testcase_finished(Config1, Testcase);
|
||||||
end_per_testcase(_TestCase, _Config) ->
|
end_per_testcase(_TestCase, _Config) ->
|
||||||
meck:unload(),
|
meck:unload(),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
expiry_timestamp_test(_) ->
|
%% -------------------------------------------------------------------
|
||||||
|
%% Testcases.
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
|
||||||
|
expiry_timestamp(_) ->
|
||||||
%% test rabbit_access_control:expiry_timestamp/1 returns the earliest expiry time
|
%% test rabbit_access_control:expiry_timestamp/1 returns the earliest expiry time
|
||||||
Now = os:system_time(seconds),
|
Now = os:system_time(seconds),
|
||||||
BeforeNow = Now - 60,
|
BeforeNow = Now - 60,
|
||||||
|
@ -102,3 +176,265 @@ expiry_timestamp_test(_) ->
|
||||||
{rabbit_expiry_backend, unused}]},
|
{rabbit_expiry_backend, unused}]},
|
||||||
?assertEqual(Now, rabbit_access_control:expiry_timestamp(User7)),
|
?assertEqual(Now, rabbit_access_control:expiry_timestamp(User7)),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
with_enabled_plugin(Config) ->
|
||||||
|
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
|
||||||
|
ok = rabbit_ct_broker_helpers:enable_plugin(Config, Node, my_auth_plugin),
|
||||||
|
rabbit_ct_broker_helpers:stop_broker(Config, Node),
|
||||||
|
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, os, unsetenv, ["RABBITMQ_ENABLED_PLUGINS"]),
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, os, unsetenv, ["LEAVE_PLUGINS_DISABLED"]),
|
||||||
|
|
||||||
|
AuthBackends = [my_auth_plugin],
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, application, set_env,
|
||||||
|
[rabbit, auth_backends, AuthBackends, [{persistent, true}]]),
|
||||||
|
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
rabbit_ct_broker_helpers:start_broker(Config, Node)),
|
||||||
|
|
||||||
|
?assertMatch({error, {auth_failure, _}}, test_connection(Config, Node)),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
with_enabled_plugin_plus_internal(Config) ->
|
||||||
|
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
|
||||||
|
ok = rabbit_ct_broker_helpers:enable_plugin(Config, Node, my_auth_plugin),
|
||||||
|
rabbit_ct_broker_helpers:stop_broker(Config, Node),
|
||||||
|
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, os, unsetenv, ["RABBITMQ_ENABLED_PLUGINS"]),
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, os, unsetenv, ["LEAVE_PLUGINS_DISABLED"]),
|
||||||
|
|
||||||
|
AuthBackends = [my_auth_plugin, rabbit_auth_backend_internal],
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, application, set_env,
|
||||||
|
[rabbit, auth_backends, AuthBackends, [{persistent, true}]]),
|
||||||
|
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
rabbit_ct_broker_helpers:start_broker(Config, Node)),
|
||||||
|
|
||||||
|
?assertEqual(ok, test_connection(Config, Node)),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
with_missing_plugin(Config) ->
|
||||||
|
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
|
||||||
|
rabbit_ct_broker_helpers:stop_broker(Config, Node),
|
||||||
|
|
||||||
|
AuthBackends = [my_auth_plugin],
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, application, set_env,
|
||||||
|
[rabbit, auth_backends, AuthBackends, [{persistent, true}]]),
|
||||||
|
|
||||||
|
?assertThrow(
|
||||||
|
{error,
|
||||||
|
{rabbit,
|
||||||
|
{{error,
|
||||||
|
"Authentication/authorization backends require plugins to be "
|
||||||
|
"enabled; see logs for details"},
|
||||||
|
_}}},
|
||||||
|
rabbit_ct_broker_helpers:start_broker(Config, Node)),
|
||||||
|
|
||||||
|
?awaitMatch(
|
||||||
|
true,
|
||||||
|
check_log(Config, Node, "no plugins available provide this module"),
|
||||||
|
30000),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
with_missing_plugin_plus_internal(Config) ->
|
||||||
|
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
|
||||||
|
rabbit_ct_broker_helpers:stop_broker(Config, Node),
|
||||||
|
|
||||||
|
AuthBackends = [my_auth_plugin, rabbit_auth_backend_internal],
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, application, set_env,
|
||||||
|
[rabbit, auth_backends, AuthBackends, [{persistent, true}]]),
|
||||||
|
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
rabbit_ct_broker_helpers:start_broker(Config, Node)),
|
||||||
|
|
||||||
|
?awaitMatch(
|
||||||
|
true,
|
||||||
|
check_log(Config, Node, "no plugins available provide this module"),
|
||||||
|
30000),
|
||||||
|
|
||||||
|
?assertEqual(ok, test_connection(Config, Node)),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
with_disabled_plugin(Config) ->
|
||||||
|
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
|
||||||
|
rabbit_ct_broker_helpers:stop_broker(Config, Node),
|
||||||
|
|
||||||
|
AuthBackends = [my_auth_plugin],
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, application, set_env,
|
||||||
|
[rabbit, auth_backends, AuthBackends, [{persistent, true}]]),
|
||||||
|
|
||||||
|
?assertThrow(
|
||||||
|
{error,
|
||||||
|
{rabbit,
|
||||||
|
{{error,
|
||||||
|
"Authentication/authorization backends require plugins to be "
|
||||||
|
"enabled; see logs for details"},
|
||||||
|
_}}},
|
||||||
|
rabbit_ct_broker_helpers:start_broker(Config, Node)),
|
||||||
|
|
||||||
|
?awaitMatch(
|
||||||
|
true,
|
||||||
|
check_log(
|
||||||
|
Config, Node,
|
||||||
|
"the `my_auth_plugin` plugin must be enabled in order to use "
|
||||||
|
"this auth backend"),
|
||||||
|
30000),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
with_disabled_plugin_plus_internal(Config) ->
|
||||||
|
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
|
||||||
|
rabbit_ct_broker_helpers:stop_broker(Config, Node),
|
||||||
|
|
||||||
|
AuthBackends = [my_auth_plugin, rabbit_auth_backend_internal],
|
||||||
|
rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node, application, set_env,
|
||||||
|
[rabbit, auth_backends, AuthBackends, [{persistent, true}]]),
|
||||||
|
|
||||||
|
?assertEqual(
|
||||||
|
ok,
|
||||||
|
rabbit_ct_broker_helpers:start_broker(Config, Node)),
|
||||||
|
|
||||||
|
?awaitMatch(
|
||||||
|
true,
|
||||||
|
check_log(
|
||||||
|
Config, Node,
|
||||||
|
"the `my_auth_plugin` plugin must be enabled in order to use "
|
||||||
|
"this auth backend"),
|
||||||
|
30000),
|
||||||
|
|
||||||
|
?assertEqual(ok, test_connection(Config, Node)),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
%% Internal helpers.
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
|
||||||
|
prepare_my_plugin(Config) ->
|
||||||
|
case os:getenv("RABBITMQ_RUN") of
|
||||||
|
false ->
|
||||||
|
build_my_plugin(Config);
|
||||||
|
_ ->
|
||||||
|
MyPluginDir = filename:dirname(
|
||||||
|
filename:dirname(
|
||||||
|
code:where_is_file("my_auth_plugin.app"))),
|
||||||
|
PluginsDir = filename:dirname(MyPluginDir),
|
||||||
|
rabbit_ct_helpers:set_config(
|
||||||
|
Config, [{rmq_plugins_dir, PluginsDir}])
|
||||||
|
end.
|
||||||
|
|
||||||
|
build_my_plugin(Config) ->
|
||||||
|
DataDir = filename:join(
|
||||||
|
filename:dirname(filename:dirname(?config(data_dir, Config))),
|
||||||
|
?MODULE_STRING ++ "_data"),
|
||||||
|
PluginSrcDir = filename:join(DataDir, "my_auth_plugin"),
|
||||||
|
PluginsDir = filename:join(PluginSrcDir, "plugins"),
|
||||||
|
Config1 = rabbit_ct_helpers:set_config(Config,
|
||||||
|
[{rmq_plugins_dir, PluginsDir}]),
|
||||||
|
{MyPlugin, OtherPlugins} = list_my_plugin_plugins(PluginSrcDir),
|
||||||
|
case MyPlugin of
|
||||||
|
[] ->
|
||||||
|
DepsDir = ?config(erlang_mk_depsdir, Config),
|
||||||
|
Args = ["test-dist",
|
||||||
|
{"DEPS_DIR=~ts", [DepsDir]},
|
||||||
|
%% We clear ALL_DEPS_DIRS to make sure they are
|
||||||
|
%% not recompiled when the plugin is built. `rabbit`
|
||||||
|
%% was previously compiled with -DTEST and if it is
|
||||||
|
%% recompiled because of this plugin, it will be
|
||||||
|
%% recompiled without -DTEST: the testsuite depends
|
||||||
|
%% on test code so we can't allow that.
|
||||||
|
%%
|
||||||
|
%% Note that we do not clear the DEPS variable: we need
|
||||||
|
%% it to be correct because it is used to generate
|
||||||
|
%% `my_auth_plugin.app` (and a RabbitMQ plugin must
|
||||||
|
%% depend on `rabbit`).
|
||||||
|
"ALL_DEPS_DIRS="],
|
||||||
|
case rabbit_ct_helpers:make(Config1, PluginSrcDir, Args) of
|
||||||
|
{ok, _} ->
|
||||||
|
{_, OtherPlugins1} = list_my_plugin_plugins(PluginSrcDir),
|
||||||
|
remove_other_plugins(PluginSrcDir, OtherPlugins1),
|
||||||
|
update_cli_path(Config1, PluginSrcDir);
|
||||||
|
{error, _} ->
|
||||||
|
{skip,
|
||||||
|
"Failed to compile the `my_auth_plugin` test plugin"}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
remove_other_plugins(PluginSrcDir, OtherPlugins),
|
||||||
|
update_cli_path(Config1, PluginSrcDir)
|
||||||
|
end.
|
||||||
|
|
||||||
|
update_cli_path(Config, PluginSrcDir) ->
|
||||||
|
SbinDir = filename:join(PluginSrcDir, "sbin"),
|
||||||
|
Rabbitmqctl = filename:join(SbinDir, "rabbitmqctl"),
|
||||||
|
RabbitmqPlugins = filename:join(SbinDir, "rabbitmq-plugins"),
|
||||||
|
RabbitmqQueues = filename:join(SbinDir, "rabbitmq-queues"),
|
||||||
|
case filelib:is_regular(Rabbitmqctl) of
|
||||||
|
true ->
|
||||||
|
ct:pal(?LOW_IMPORTANCE,
|
||||||
|
"Switching to CLI in e.g. ~ts", [Rabbitmqctl]),
|
||||||
|
rabbit_ct_helpers:set_config(
|
||||||
|
Config,
|
||||||
|
[{rabbitmqctl_cmd, Rabbitmqctl},
|
||||||
|
{rabbitmq_plugins_cmd, RabbitmqPlugins},
|
||||||
|
{rabbitmq_queues_cmd, RabbitmqQueues}]);
|
||||||
|
false ->
|
||||||
|
Config
|
||||||
|
end.
|
||||||
|
|
||||||
|
list_my_plugin_plugins(PluginSrcDir) ->
|
||||||
|
Files = filelib:wildcard("plugins/*", PluginSrcDir),
|
||||||
|
lists:partition(
|
||||||
|
fun(Path) ->
|
||||||
|
Filename = filename:basename(Path),
|
||||||
|
re:run(Filename, "^my_auth_plugin-", [{capture, none}]) =:= match
|
||||||
|
end, Files).
|
||||||
|
|
||||||
|
remove_other_plugins(PluginSrcDir, OtherPlugins) ->
|
||||||
|
ok = rabbit_file:recursive_delete(
|
||||||
|
[filename:join(PluginSrcDir, OtherPlugin)
|
||||||
|
|| OtherPlugin <- OtherPlugins]).
|
||||||
|
|
||||||
|
check_log(Config, Node, Msg) ->
|
||||||
|
LogLocations = rabbit_ct_broker_helpers:rpc(
|
||||||
|
Config, Node,
|
||||||
|
rabbit, log_locations, []),
|
||||||
|
lists:any(
|
||||||
|
fun(LogLocation) ->
|
||||||
|
check_log1(LogLocation, Msg)
|
||||||
|
end, LogLocations).
|
||||||
|
|
||||||
|
check_log1(LogLocation, Msg) ->
|
||||||
|
case filelib:is_regular(LogLocation) of
|
||||||
|
true ->
|
||||||
|
{ok, Content} = file:read_file(LogLocation),
|
||||||
|
ReOpts = [{capture, none}, multiline, unicode],
|
||||||
|
match =:= re:run(Content, Msg, ReOpts);
|
||||||
|
false ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_connection(Config, Node) ->
|
||||||
|
case rabbit_ct_client_helpers:open_unmanaged_connection(Config, Node) of
|
||||||
|
Conn when is_pid(Conn) ->
|
||||||
|
ok = rabbit_ct_client_helpers:close_connection(Conn),
|
||||||
|
ok;
|
||||||
|
{error, _} = Error ->
|
||||||
|
Error
|
||||||
|
end.
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
PROJECT = my_auth_plugin
|
||||||
|
PROJECT_DESCRIPTION = Plugin to test access control
|
||||||
|
PROJECT_VERSION = 1.0.0
|
||||||
|
|
||||||
|
define PROJECT_APP_EXTRA_KEYS
|
||||||
|
{broker_version_requirements, []}
|
||||||
|
endef
|
||||||
|
|
||||||
|
DEPS = rabbit_common rabbit
|
||||||
|
|
||||||
|
DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk
|
||||||
|
DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk
|
||||||
|
|
||||||
|
include ../../../../../rabbitmq-components.mk
|
||||||
|
include ../../../../../erlang.mk
|
36
deps/rabbit/test/rabbit_access_control_SUITE_data/my_auth_plugin/src/my_auth_plugin.erl
vendored
Normal file
36
deps/rabbit/test/rabbit_access_control_SUITE_data/my_auth_plugin/src/my_auth_plugin.erl
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
%% This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
%% License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
%%
|
||||||
|
%% Copyright (c) 2025 Broadcom. All Rights Reserved. The term “Broadcom”
|
||||||
|
%% refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
|
||||||
|
%%
|
||||||
|
|
||||||
|
-module(my_auth_plugin).
|
||||||
|
|
||||||
|
-behaviour(rabbit_authn_backend).
|
||||||
|
-behaviour(rabbit_authz_backend).
|
||||||
|
|
||||||
|
-export([user_login_authentication/2, user_login_authorization/2,
|
||||||
|
check_vhost_access/3, check_resource_access/4, check_topic_access/4]).
|
||||||
|
-export([expiry_timestamp/1]).
|
||||||
|
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
%% Implementation of rabbit_authn_backend.
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
|
||||||
|
user_login_authentication(_, _) ->
|
||||||
|
{error, unknown_user}.
|
||||||
|
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
%% Implementation of rabbit_authz_backend.
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
|
||||||
|
user_login_authorization(_, _) ->
|
||||||
|
{error, unknown_user}.
|
||||||
|
|
||||||
|
check_vhost_access(_AuthUser, _VHostPath, _AuthzData) -> true.
|
||||||
|
check_resource_access(_AuthUser, _Resource, _Permission, _Context) -> true.
|
||||||
|
check_topic_access(_AuthUser, _Resource, _Permission, _Context) -> true.
|
||||||
|
|
||||||
|
expiry_timestamp(_AuthUser) -> never.
|
|
@ -23,7 +23,7 @@
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
<kotlin.version>2.2.0</kotlin.version>
|
<kotlin.version>2.2.10</kotlin.version>
|
||||||
<junit-jupiter.version>5.10.0</junit-jupiter.version>
|
<junit-jupiter.version>5.10.0</junit-jupiter.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -275,7 +275,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClusterStatusCommand do
|
||||||
cluster_tags: result |> Keyword.get(:cluster_tags, []),
|
cluster_tags: result |> Keyword.get(:cluster_tags, []),
|
||||||
disk_nodes: result |> Keyword.get(:nodes, []) |> Keyword.get(:disc, []),
|
disk_nodes: result |> Keyword.get(:nodes, []) |> Keyword.get(:disc, []),
|
||||||
ram_nodes: result |> Keyword.get(:nodes, []) |> Keyword.get(:ram, []),
|
ram_nodes: result |> Keyword.get(:nodes, []) |> Keyword.get(:ram, []),
|
||||||
running_nodes: result |> Keyword.get(:running_nodes, []) |> Enum.map(&to_string/1),
|
running_nodes: result |> Keyword.get(:running_nodes, []),
|
||||||
alarms: Keyword.get(result, :alarms) |> Keyword.values() |> Enum.concat() |> Enum.uniq(),
|
alarms: Keyword.get(result, :alarms) |> Keyword.values() |> Enum.concat() |> Enum.uniq(),
|
||||||
maintenance_status: Keyword.get(result, :maintenance_status, []) |> Enum.into(%{}),
|
maintenance_status: Keyword.get(result, :maintenance_status, []) |> Enum.into(%{}),
|
||||||
partitions: Keyword.get(result, :partitions, []) |> Enum.into(%{}),
|
partitions: Keyword.get(result, :partitions, []) |> Enum.into(%{}),
|
||||||
|
|
|
@ -1133,6 +1133,13 @@ configure_metadata_store(Config) ->
|
||||||
{rabbit,
|
{rabbit,
|
||||||
[{forced_feature_flags_on_init,
|
[{forced_feature_flags_on_init,
|
||||||
{rel, [khepri_db], []}}]});
|
{rel, [khepri_db], []}}]});
|
||||||
|
{rel, ListToEnable, ListToSkip} ->
|
||||||
|
Rel1 = {rel, [khepri_db | ListToEnable], ListToSkip},
|
||||||
|
rabbit_ct_helpers:merge_app_env(
|
||||||
|
Config1, {rabbit, [
|
||||||
|
{forced_feature_flags_on_init, Rel1}
|
||||||
|
]}
|
||||||
|
);
|
||||||
_ ->
|
_ ->
|
||||||
rabbit_ct_helpers:merge_app_env(
|
rabbit_ct_helpers:merge_app_env(
|
||||||
Config1,
|
Config1,
|
||||||
|
@ -1149,6 +1156,13 @@ configure_metadata_store(Config) ->
|
||||||
{rabbit,
|
{rabbit,
|
||||||
[{forced_feature_flags_on_init,
|
[{forced_feature_flags_on_init,
|
||||||
{rel, [], [khepri_db]}}]});
|
{rel, [], [khepri_db]}}]});
|
||||||
|
{rel, ListToEnable, ListToSkip} ->
|
||||||
|
Rel1 = {rel, ListToEnable, [khepri_db | ListToSkip]},
|
||||||
|
rabbit_ct_helpers:merge_app_env(
|
||||||
|
Config1, {rabbit, [
|
||||||
|
{forced_feature_flags_on_init, Rel1}
|
||||||
|
]}
|
||||||
|
);
|
||||||
_ ->
|
_ ->
|
||||||
rabbit_ct_helpers:merge_app_env(
|
rabbit_ct_helpers:merge_app_env(
|
||||||
Config1,
|
Config1,
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
|
|
||||||
-compile([export_all, nowarn_export_all]).
|
-compile([export_all, nowarn_export_all]).
|
||||||
|
|
||||||
|
-import(rabbit_ct_helpers, [eventually/1]).
|
||||||
|
-import(rabbit_ct_broker_helpers, [rpc/4]).
|
||||||
|
|
||||||
all() ->
|
all() ->
|
||||||
[
|
[
|
||||||
{group, default_config},
|
{group, default_config},
|
||||||
|
@ -831,6 +834,7 @@ stream_pub_sub_metrics(Config) ->
|
||||||
lists:sort(maps:to_list(MaxOffsetLag))),
|
lists:sort(maps:to_list(MaxOffsetLag))),
|
||||||
dispose_stream_connection(S1, C1, list_to_binary(Stream1)),
|
dispose_stream_connection(S1, C1, list_to_binary(Stream1)),
|
||||||
dispose_stream_connection(S2, C2, list_to_binary(Stream2)),
|
dispose_stream_connection(S2, C2, list_to_binary(Stream2)),
|
||||||
|
eventually(?_assertEqual([], rpc(Config, rabbit_amqqueue, list_by_type, [stream]))),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
core_metrics_special_chars(Config) ->
|
core_metrics_special_chars(Config) ->
|
||||||
|
|
Loading…
Reference in New Issue