Skip to content

Commit 6d73a36

Browse files
MB-61292: Enforce secret name uniqueness
Strictly speaking name uniqueness is not needed, but when names are not unique it comlicates life of UI users a lot, so it seems like it is easier to enforce it. Change-Id: Ib69381b9010ad4e08c8091e5c6f63e49c1b1ad47 Reviewed-on: https://review.couchbase.org/c/ns_server/+/216783 Tested-by: Build Bot <[email protected]> Reviewed-by: Navdeep S Boparai <[email protected]> Well-Formed: Build Bot <[email protected]> Tested-by: Timofey Barmin <[email protected]>
1 parent 16fcc15 commit 6d73a36

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

apps/ns_server/src/cb_cluster_secrets.erl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
sync_with_all_node_monitors/0,
5858
new_key_id/0,
5959
is_valid_key_id/1,
60-
dek_drop_complete/1]).
60+
dek_drop_complete/1,
61+
is_name_unique/3]).
6162

6263
%% gen_server callbacks
6364
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -402,6 +403,12 @@ dek_drop_complete(DekKind) ->
402403
?MODULE ! {dek_drop_complete, DekKind},
403404
ok.
404405

406+
-spec is_name_unique(secret_id(), string(), chronicle_snapshot()) -> boolean().
407+
is_name_unique(Id, Name, Snapshot) ->
408+
lists:all(fun (#{id := Id2}) when Id == Id2 -> true;
409+
(#{name := Name2}) -> Name /= Name2
410+
end, get_all(Snapshot)).
411+
405412
%%%===================================================================
406413
%%% gen_server callbacks
407414
%%%===================================================================
@@ -1121,7 +1128,8 @@ validate_secret_in_txn(NewProps, PrevProps, Snapshot) ->
11211128
ok ?= validate_secrets_encryption_usage_change(NewProps, PrevProps,
11221129
Snapshot),
11231130
ok ?= validate_dek_related_usage_change(NewProps, PrevProps, Snapshot),
1124-
ok ?= validate_encryption_secret_id(NewProps, Snapshot)
1131+
ok ?= validate_encryption_secret_id(NewProps, Snapshot),
1132+
ok ?= validate_name_uniqueness(NewProps, Snapshot)
11251133
end.
11261134

11271135
-spec execute_on_master({module(), atom(), [term()]}) -> term().
@@ -2029,6 +2037,14 @@ initiate_deks_drop(Kind, IdsToDrop, #state{deks = DeksInfo} = State0) ->
20292037
State0
20302038
end.
20312039

2040+
-spec validate_name_uniqueness(secret_props(), chronicle_snapshot()) ->
2041+
ok | {error, name_not_unique}.
2042+
validate_name_uniqueness(#{id := Id, name := Name}, Snapshot) ->
2043+
case is_name_unique(Id, Name, Snapshot) of
2044+
true -> ok;
2045+
false -> {error, name_not_unique}
2046+
end.
2047+
20322048
-ifdef(TEST).
20332049
replace_secret_in_list_test() ->
20342050
?assertEqual(false, replace_secret_in_list(#{id => 3, p => 5}, [])),

apps/ns_server/src/menelaus_web_secrets.erl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ handle_put_secret(IdStr, Req) ->
9696
{error, {encrypt_id, not_allowed}} ->
9797
menelaus_util:reply_global_error(
9898
Req, "encryption secret not allowed");
99+
{error, name_not_unique} ->
100+
menelaus_util:reply_global_error(
101+
Req, "name is not unique");
99102
{error, not_found} ->
100103
menelaus_util:reply_not_found(Req)
101104
end
@@ -109,6 +112,17 @@ handle_put_secret(IdStr, Req) ->
109112
secret_validators(CurProps) ->
110113
[validator:string(name, _),
111114
validator:required(name, _),
115+
validator:validate(
116+
fun ("") -> {error, "Must not not be empty"};
117+
(Str) ->
118+
Id = maps:get(id, CurProps, ?SECRET_ID_NOT_SET),
119+
case cb_cluster_secrets:is_name_unique(Id, Str, direct) of
120+
true -> ok;
121+
%% Checking it here and inside transaction later
122+
%% Check here is needed mostly to make it user friendly in UI
123+
false -> {error, "Must be unique"}
124+
end
125+
end, name, _),
112126
validator:one_of(type, [?GENERATED_KEY_TYPE, ?AWSKMS_KEY_TYPE], _),
113127
validator:convert(type, binary_to_atom(_, latin1), _),
114128
validator:required(type, _),

cluster_tests/testsets/native_encryption_tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ def cfg_encryption_api_test(self):
572572
secret = auto_generated_secret(usage=['bucket-encryption-*'])
573573
bad_id = create_secret(self.random_node(), secret)
574574
secret['usage'] = ['bucket-encryption-*', 'configuration-encryption']
575+
secret['name'] = secret['name'] + ' (good)' # has to be unique
575576
good_id = create_secret(self.random_node(), secret)
576577
node = self.random_node()
577578
set_cfg_encryption(node, 'disabled', -1)

0 commit comments

Comments
 (0)