Skip to content

Commit

Permalink
Optionally block enabling certain feature flags via Management UI/API
Browse files Browse the repository at this point in the history
Useful to avoid accidentally enabling for example experiemental
feature flags from the Management UI on sensitive clusters.
  • Loading branch information
gomoripeti committed Mar 5, 2024
1 parent a40f231 commit 7209135
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,10 @@ end}.
{datatype, {enum, [true, false]}},
{include_default, false}
]}.

%% Block enabling certain feature flags over API

{mapping, "management.restrictions.feature_flag_blocked.$name", "rabbitmq_management.restrictions.feature_flag_blocked", [
{datatype, [string, {enum, [false]}]},
{include_default, false}
]}.
8 changes: 8 additions & 0 deletions deps/rabbitmq_management/src/rabbit_mgmt_features.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

-export([is_op_policy_updating_disabled/0,
is_qq_replica_operations_disabled/0,
is_feature_flag_blocked/1,
are_stats_enabled/0]).

is_qq_replica_operations_disabled() ->
Expand All @@ -20,6 +21,13 @@ is_op_policy_updating_disabled() ->
_ -> false
end.

-spec is_feature_flag_blocked(rabbit_feature_flags:feature_name()) -> {true, string()} | false.
is_feature_flag_blocked(FeatureFlag) ->
case get_restriction([feature_flag_blocked, FeatureFlag]) of
Msg when is_list(Msg) -> {true, Msg};
_ -> false
end.

are_stats_enabled() ->
DisabledFromConf = application:get_env(
rabbitmq_management, disable_management_stats, false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
-export([variances/2]).

-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
-include_lib("rabbit_common/include/rabbit.hrl").

%%--------------------------------------------------------------------

Expand All @@ -38,13 +37,18 @@ accept_content(ReqData, #context{} = Context) ->
NameS = rabbit_mgmt_util:id(name, ReqData),
try
Name = list_to_existing_atom(binary_to_list(NameS)),
case rabbit_feature_flags:enable(Name) of
ok ->
{true, ReqData, Context};
{error, Reason1} ->
FormattedReason1 = rabbit_ff_extra:format_error(Reason1),
rabbit_mgmt_util:bad_request(
list_to_binary(FormattedReason1), ReqData, Context)
case rabbit_mgmt_features:is_feature_flag_blocked(Name) of
{true, Message} ->
rabbit_mgmt_util:method_not_allowed(Message, ReqData, Context);
false ->
case rabbit_feature_flags:enable(Name) of
ok ->
{true, ReqData, Context};
{error, Reason1} ->
FormattedReason1 = rabbit_ff_extra:format_error(Reason1),
rabbit_mgmt_util:bad_request(
list_to_binary(FormattedReason1), ReqData, Context)
end
end
catch
_:badarg ->
Expand Down
15 changes: 15 additions & 0 deletions deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ all_tests() -> [
user_limit_set_test,
config_environment_test,
disabled_qq_replica_opers_test,
feature_flag_blocked_test,
list_deprecated_features_test,
list_used_deprecated_features_test
].
Expand Down Expand Up @@ -230,6 +231,11 @@ init_per_testcase(Testcase = disabled_qq_replica_opers_test, Config) ->
rabbit_ct_broker_helpers:rpc_all(Config,
application, set_env, [rabbitmq_management, restrictions, Restrictions]),
rabbit_ct_helpers:testcase_started(Config, Testcase);
init_per_testcase(Testcase = feature_flag_blocked_test, Config) ->
Restrictions = [{feature_flag_blocked, [{khepri_db, "Khepri is blocked"}]}],
rabbit_ct_broker_helpers:rpc_all(Config,
application, set_env, [rabbitmq_management, restrictions, Restrictions]),
rabbit_ct_helpers:testcase_started(Config, Testcase);
init_per_testcase(queues_detailed_test, Config) ->
IsEnabled = rabbit_ct_broker_helpers:is_feature_flag_enabled(
Config, detailed_queues_endpoint),
Expand Down Expand Up @@ -302,6 +308,10 @@ end_per_testcase0(disabled_qq_replica_opers_test, Config) ->
rabbit_ct_broker_helpers:rpc(Config, 0, application, unset_env,
[rabbitmq_management, restrictions]),
Config;
end_per_testcase0(feature_flag_blocked_test, Config) ->
rabbit_ct_broker_helpers:rpc(Config, 0, application, unset_env,
[rabbitmq_management, restrictions]),
Config;
end_per_testcase0(Testcase, Config)
when Testcase == list_deprecated_features_test;
Testcase == list_used_deprecated_features_test ->
Expand Down Expand Up @@ -3716,6 +3726,11 @@ disabled_qq_replica_opers_test(Config) ->
http_delete(Config, "/queues/quorum/replicas/on/" ++ Nodename ++ "/shrink", ?METHOD_NOT_ALLOWED),
passed.

feature_flag_blocked_test(Config) ->
Body = "",
http_put(Config, "/feature-flags/khepri_db/enable", Body, ?METHOD_NOT_ALLOWED),
passed.

list_deprecated_features_test(Config) ->
Desc = "This is a deprecated feature",
DocUrl = "https://rabbitmq.com/",
Expand Down

0 comments on commit 7209135

Please sign in to comment.