From 6968791aa35095058ac4673e9027e7ff9da50bbf Mon Sep 17 00:00:00 2001 From: Simon Unge Date: Mon, 23 Jan 2023 13:00:49 -0800 Subject: [PATCH] See #5957. HTTP api to generate hashed password from cleartext password (cherry picked from commit 7fecfcd26cc4f5ac81ca952ac68b9a98db1448fd) (cherry picked from commit 17059b77df618b15461f5c224101fb9de27c64f7) --- .../src/rabbit_mgmt_dispatcher.erl | 3 +- .../src/rabbit_mgmt_wm_hash_password.erl | 36 +++++++++++++++++++ .../test/rabbit_mgmt_http_SUITE.erl | 12 +++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 deps/rabbitmq_management/src/rabbit_mgmt_wm_hash_password.erl diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl index ba89bf14047e..cf3903707e6b 100644 --- a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl +++ b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl @@ -183,5 +183,6 @@ dispatcher() -> {"/auth/attempts/:node", rabbit_mgmt_wm_auth_attempts, [all]}, {"/auth/attempts/:node/source", rabbit_mgmt_wm_auth_attempts, [by_source]}, {"/login", rabbit_mgmt_wm_login, []}, - {"/config/effective", rabbit_mgmt_wm_environment, []} + {"/config/effective", rabbit_mgmt_wm_environment, []}, + {"/auth/hash_password/:password", rabbit_mgmt_wm_hash_password, []} ]. diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_hash_password.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_hash_password.erl new file mode 100644 index 000000000000..ff7fee225d19 --- /dev/null +++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_hash_password.erl @@ -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) 2007-2023 VMware, Inc. or its affiliates. All rights reserved. +%% + +-module(rabbit_mgmt_wm_hash_password). + +-export([init/2, to_json/2, content_types_provided/2, is_authorized/2]). +-export([variances/2, allowed_methods/2]). + +-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl"). +-include_lib("rabbit_common/include/rabbit.hrl"). + +%%-------------------------------------------------------------------- + +init(Req, _State) -> + {cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}. + +variances(Req, Context) -> + {[<<"accept-encoding">>, <<"origin">>], Req, Context}. + +allowed_methods(ReqData, Context) -> + {[<<"GET">>, <<"OPTIONS">>], ReqData, Context}. + +content_types_provided(ReqData, Context) -> + {rabbit_mgmt_util:responder_map(to_json), ReqData, Context}. + +to_json(ReqData, Context) -> + Password = rabbit_mgmt_util:id(password, ReqData), + HashedPassword = rabbit_password:hash(Password), + rabbit_mgmt_util:reply([{ok, base64:encode(HashedPassword)}], ReqData, Context). + +is_authorized(ReqData, Context) -> + rabbit_mgmt_util:is_authorized_admin(ReqData, Context). diff --git a/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl b/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl index 65450f5d44c3..884048504f6e 100644 --- a/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl +++ b/deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl @@ -71,6 +71,7 @@ all_tests() -> [ users_legacy_administrator_test, adding_a_user_with_password_test, adding_a_user_with_password_hash_test, + adding_a_user_with_generated_password_hash_test, adding_a_user_with_permissions_in_single_operation_test, adding_a_user_without_tags_fails_test, adding_a_user_without_password_or_hash_test, @@ -630,6 +631,17 @@ adding_a_user_with_password_hash_test(Config) -> [?CREATED, ?NO_CONTENT]), http_delete(Config, "/users/user11", ?NO_CONTENT). +adding_a_user_with_generated_password_hash_test(Config) -> + #{ok := HashedPassword} = http_get(Config, "/auth/hash_password/some_password"), + + http_put(Config, "/users/user12", [{tags, <<"administrator">>}, + {password_hash, HashedPassword}], + [?CREATED, ?NO_CONTENT]), + % If the get succeeded, the hashed password generation is correct + User = http_get(Config, "/users/user12", "user12", "some_password", ?OK), + ?assertEqual(maps:get(password_hash, User), HashedPassword), + http_delete(Config, "/users/user12", ?NO_CONTENT). + adding_a_user_with_permissions_in_single_operation_test(Config) -> QArgs = #{}, PermArgs = #{configure => <<".*">>,