Skip to content

Commit 81bd886

Browse files
MB-61292: Use snapshot when checking key existance...
... in encr at rest API and when extracting props for testing Change-Id: I4c365bbefb906da3ad5b7f5abecea713eb06736d Reviewed-on: https://review.couchbase.org/c/ns_server/+/232628 Reviewed-by: Navdeep S Boparai <[email protected]> Well-Formed: Build Bot <[email protected]> Tested-by: Timofey Barmin <[email protected]>
1 parent 3e9b4a5 commit 81bd886

File tree

1 file changed

+64
-61
lines changed

1 file changed

+64
-61
lines changed

apps/ns_server/src/menelaus_web_secrets.erl

Lines changed: 64 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -64,52 +64,46 @@ handle_post_secret(Req) ->
6464
menelaus_util:assert_is_enterprise(),
6565
assert_is_79(),
6666
with_validated_secret(
67-
fun (ToAdd) ->
67+
fun (ToAdd, _) ->
6868
maybe
6969
{ok, Res} ?= cb_cluster_secrets:add_new_secret(ToAdd),
7070
Formatted = export_secret(Res),
7171
ns_audit:set_encryption_secret(Req, Formatted),
7272
menelaus_util:reply_json(Req, {Formatted}),
7373
ok
7474
end
75-
end, #{}, Req).
75+
end, undefined, Req).
7676

7777
handle_put_secret(IdStr, Req) ->
7878
menelaus_util:assert_is_enterprise(),
7979
assert_is_79(),
8080
Id = parse_id(IdStr),
81-
case cb_cluster_secrets:get_secret(Id) of
82-
{ok, CurProps} ->
83-
with_validated_secret(
84-
fun (Props) ->
85-
maybe
86-
IsSecretWritableMFA = {?MODULE, is_writable_remote,
87-
[?HIDE(Req), node()]},
88-
%% replace_secret will check "old usages" inside txn
89-
{ok, Res} ?= cb_cluster_secrets:replace_secret(
90-
Id, Props, IsSecretWritableMFA),
91-
Formatted = export_secret(Res),
92-
ns_audit:set_encryption_secret(Req, Formatted),
93-
menelaus_util:reply_json(Req, {Formatted}),
94-
ok
95-
end
96-
end, CurProps, Req);
97-
{error, not_found} ->
98-
%% We don't want PUT to create secrets because we generate id's
99-
menelaus_util:reply_not_found(Req)
100-
end.
81+
with_validated_secret(
82+
fun (Props, _) ->
83+
maybe
84+
IsSecretWritableMFA = {?MODULE, is_writable_remote,
85+
[?HIDE(Req), node()]},
86+
%% replace_secret will check "old usages" inside txn
87+
{ok, Res} ?= cb_cluster_secrets:replace_secret(
88+
Id, Props, IsSecretWritableMFA),
89+
Formatted = export_secret(Res),
90+
ns_audit:set_encryption_secret(Req, Formatted),
91+
menelaus_util:reply_json(Req, {Formatted}),
92+
ok
93+
end
94+
end, Id, Req).
10195

10296
handle_test_post_secret(Req) ->
10397
menelaus_util:assert_is_enterprise(),
10498
assert_is_79(),
10599
with_validated_secret(
106-
fun (Params) ->
100+
fun (Params, _) ->
107101
maybe
108102
ok ?= cb_cluster_secrets:test(Params, undefined),
109103
menelaus_util:reply(Req, 200),
110104
ok
111105
end
112-
end, #{}, Req).
106+
end, undefined, Req).
113107

114108
handle_test_post_secret(IdStr, Req) ->
115109
menelaus_util:assert_is_enterprise(),
@@ -140,21 +134,16 @@ handle_test_put_secret(IdStr, Req) ->
140134
menelaus_util:assert_is_enterprise(),
141135
assert_is_79(),
142136
Id = parse_id(IdStr),
143-
case cb_cluster_secrets:get_secret(Id) of
144-
{ok, CurProps} ->
145-
with_validated_secret(
146-
fun (Params) ->
147-
maybe
148-
ok ?= cb_cluster_secrets:test(Params, CurProps),
149-
menelaus_util:reply(Req, 200),
150-
ok
151-
end
152-
end, CurProps, Req);
153-
{error, not_found} ->
154-
menelaus_util:reply_not_found(Req)
155-
end.
156-
157-
with_validated_secret(Fun, CurProps, Req) ->
137+
with_validated_secret(
138+
fun (Params, CurProps) ->
139+
maybe
140+
ok ?= cb_cluster_secrets:test(Params, CurProps),
141+
menelaus_util:reply(Req, 200),
142+
ok
143+
end
144+
end, Id, Req).
145+
146+
with_validated_secret(Fun, ExistingId, Req) ->
158147
%% We need to fetch snapshot with read_consistency in order to deal with
159148
%% the following scenario:
160149
%% 1. User creates a bucket on a node which is not an orchestrator
@@ -167,28 +156,42 @@ with_validated_secret(Fun, CurProps, Req) ->
167156
%[ns_bucket:fetch_snapshot(all, _, [uuid])],
168157
[cb_cluster_secrets:fetch_snapshot_in_txn(_)],
169158
#{read_consistency => quorum}),
170-
validator:handle(
171-
fun (RawProps) ->
172-
maybe
173-
Props = import_secret(RawProps),
174-
%% Note: All "usages" should be writable by current user.
175-
%% This includes "new usages" (usages that are being set)
176-
%% and "old usages" (usages that are being replaced)
177-
%% Checking "new usages" here:
178-
true ?= is_writable(Props, Req),
179-
%% Fun is responsible for checking "old usages" inside txn
180-
ok ?= Fun(Props)
181-
else
182-
false ->
183-
menelaus_util:web_exception(403, format_error(forbidden));
184-
{error, forbidden} ->
185-
menelaus_util:web_exception(403, format_error(forbidden));
186-
{error, no_quorum} ->
187-
menelaus_util:web_exception(503, format_error(no_quorum));
188-
{error, Reason} ->
189-
menelaus_util:reply_global_error(Req, format_error(Reason))
190-
end
191-
end, Req, json, secret_validators(CurProps, Snapshot)).
159+
CurPropsRes = case ExistingId of
160+
undefined -> {ok, #{}};
161+
_ -> cb_cluster_secrets:get_secret(ExistingId, Snapshot)
162+
end,
163+
164+
case CurPropsRes of
165+
{ok, CurProps} ->
166+
validator:handle(
167+
fun (RawProps) ->
168+
maybe
169+
Props = import_secret(RawProps),
170+
%% Note: All "usages" should be writable by current user.
171+
%% This includes "new usages" (usages that are being set)
172+
%% and "old usages" (usages that are being replaced)
173+
%% Checking "new usages" here:
174+
true ?= is_writable(Props, Req),
175+
%% Fun is responsible for checking "old usages" inside txn
176+
ok ?= Fun(Props, CurProps)
177+
else
178+
false ->
179+
menelaus_util:web_exception(403,
180+
format_error(forbidden));
181+
{error, forbidden} ->
182+
menelaus_util:web_exception(403,
183+
format_error(forbidden));
184+
{error, no_quorum} ->
185+
menelaus_util:web_exception(503,
186+
format_error(no_quorum));
187+
{error, Reason} ->
188+
menelaus_util:reply_global_error(Req,
189+
format_error(Reason))
190+
end
191+
end, Req, json, secret_validators(CurProps, Snapshot));
192+
{error, not_found} ->
193+
menelaus_util:reply_not_found(Req)
194+
end.
192195

193196
%% Note: CurProps can only be used for static fields validation here.
194197
%% Any field that can be modified and needs to use CurProps should be

0 commit comments

Comments
 (0)