-
Notifications
You must be signed in to change notification settings - Fork 391
/
riak_core_security_tests.erl
289 lines (279 loc) · 23.8 KB
/
riak_core_security_tests.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
-module(riak_core_security_tests).
-compile(export_all).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
start_manager(Node) ->
Dir = atom_to_list(Node),
case length(Dir) of
0 -> exit(no_dir); %% make sure we don't do something stupid below
_ -> ok
end,
os:cmd("mkdir " ++ Dir),
os:cmd("rm -rf " ++ Dir ++ "/"),
{ok, Mgr} = riak_core_metadata_manager:start_link([{data_dir, Dir},
{node_name, Node}]),
TreeDir = Dir ++ "/trees",
{ok, Tree} = riak_core_metadata_hashtree:start_link(TreeDir),
{ok, Bcst} = riak_core_broadcast:start_link([node()], [], [], []),
unlink(Bcst),
unlink(Tree),
unlink(Mgr),
application:set_env(riak_core, permissions, [{riak_kv,[get,put]}]),
{Mgr, Tree, Bcst}.
stop_manager({Mgr, Tree, Bcst}) ->
catch exit(Mgr, kill),
catch exit(Tree, kill),
catch exit(Bcst, kill),
ok.
security_test_() ->
{foreach,
fun() ->
start_manager(node())
end,
fun(S) ->
stop_manager(S)
end,
[{timeout, 60, { "find_user", fun test_find_user/0 }},
{timeout, 60, { "test_find_bucket_grants", fun test_find_bucket_grants/0 }},
{timeout, 60, { "find_one_user_by_metadata", fun test_find_one_user_by_metadata/0 }},
{timeout, 60, { "find_unique_user_by_metadata", fun test_find_unique_user_by_metadata/0 }},
{timeout, 60, { "trust auth works",
fun() ->
?assertMatch({error, _}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}])),
?assertEqual(ok, riak_core_security:add_user(<<"user">>,
[{"password","password"}])),
?assertMatch({error, _}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}])),
?assertEqual(ok, riak_core_security:add_source(all, {{127, 0, 0, 1}, 32}, trust, [])),
?assertMatch({ok, _}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}])),
%% make sure these don't crash, at least
?assertEqual(ok, riak_core_security:print_users()),
?assertEqual(ok, riak_core_security:print_sources()),
?assertEqual(ok, riak_core_security:print_user(<<"user">>)),
ok
end}},
{timeout, 60, { "password auth works",
fun() ->
?assertMatch({error, _}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}])),
?assertEqual(ok, riak_core_security:add_user(<<"user">>,
[])),
?assertMatch({error, _}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}])),
?assertEqual(ok, riak_core_security:add_source(all, {{127, 0, 0, 1}, 32}, password, [])),
?assertEqual({error, missing_password}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}])),
?assertEqual(ok, riak_core_security:alter_user(<<"user">>, [{"password", "password"}])),
?assertMatch({error, _}, riak_core_security:authenticate(<<"user">>, <<"badpassword">>,
[{ip, {127, 0, 0, 1}}])),
?assertMatch({ok, _}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}])),
%% make sure these don't crash, at least
?assertEqual(ok, riak_core_security:print_users()),
?assertEqual(ok, riak_core_security:print_sources()),
?assertEqual(ok, riak_core_security:print_user(<<"user">>)),
ok
end}},
{timeout, 60, { "user grant/revoke on type/bucket works",
fun() ->
?assertEqual(ok, riak_core_security:add_user(<<"user">>,
[{"password","password"}])),
?assertEqual(ok, riak_core_security:add_source(all, {{127, 0, 0, 1}, 32}, password, [])),
{ok, Ctx} = riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}]),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_grant([<<"user">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.get", "riak_kv.put"])),
?assertMatch({error, {unknown_permission, _}}, riak_core_security:add_grant([<<"user">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.upsert"])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_revoke([<<"user">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.get"])),
?assertMatch({error, {unknown_permission, _}}, riak_core_security:add_revoke([<<"user">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.upsert"])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.put", {<<"default">>, <<"mybucket">>}}, Ctx)),
%% make sure these don't crash, at least
?assertEqual(ok, riak_core_security:print_users()),
?assertEqual(ok, riak_core_security:print_sources()),
?assertEqual(ok, riak_core_security:print_user(<<"user">>)),
%% delete the user
?assertMatch(ok, riak_core_security:del_user(<<"user">>)),
%% re-add them
?assertEqual(ok, riak_core_security:add_user(<<"user">>,
[{"password","password"}])),
%% make sure their old grants are gone
{ok, Ctx2} = riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}]),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.put", {<<"default">>, <<"mybucket">>}}, Ctx2)),
ok
end}},
{timeout, 60, { "group grant/revoke on type/bucket works",
fun() ->
?assertEqual(ok, riak_core_security:add_user(<<"user">>,
[{"password","password"}])),
?assertEqual(ok, riak_core_security:add_group(<<"group">>,
[])),
?assertEqual(ok, riak_core_security:add_source([<<"user">>], {{127, 0, 0, 1}, 32}, password, [])),
{ok, Ctx} = riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}]),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_grant([<<"group">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.get"])),
?assertMatch({error, {unknown_permission, _}}, riak_core_security:add_grant([<<"group">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.upsert"])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:alter_user(<<"user">>, [{"groups", ["group"]}])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_revoke([<<"group">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.get"])),
?assertMatch({error, {unknown_permission, _}}, riak_core_security:add_revoke([<<"group">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.upsert"])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_grant([<<"group">>], {<<"default">>, <<"mybucket">>}, ["riak_kv.get"])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertMatch({error, {unknown_groups, _}}, riak_core_security:alter_user(<<"user">>, [{"groups", ["nogroup"]}])),
?assertEqual(ok, riak_core_security:alter_user(<<"user">>, [{"groups", []}])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:alter_user(<<"user">>, [{"groups", ["group"]}])),
%% make sure these don't crash, at least
?assertEqual(ok, riak_core_security:print_users()),
?assertEqual(ok, riak_core_security:print_sources()),
?assertEqual(ok, riak_core_security:print_user(<<"user">>)),
?assertEqual(ok, riak_core_security:print_groups()),
?assertEqual(ok, riak_core_security:print_group(<<"group">>)),
ok
end}},
{timeout, 60, { "all grant/revoke on type/bucket works",
fun() ->
?assertEqual(ok, riak_core_security:add_user(<<"user">>,
[{"password","password"}])),
?assertEqual(ok, riak_core_security:add_source([<<"user">>], {{127, 0, 0, 1}, 32}, password, [])),
{ok, Ctx} = riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}]),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_grant(all, {<<"default">>, <<"mybucket">>}, ["riak_kv.get"])),
?assertMatch({error, {unknown_permission, _}}, riak_core_security:add_grant(all, {<<"default">>, <<"mybucket">>}, ["riak_kv.upsert"])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_revoke(all, {<<"default">>, <<"mybucket">>}, ["riak_kv.get"])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
%% make sure these don't crash, at least
?assertEqual(ok, riak_core_security:print_users()),
?assertEqual(ok, riak_core_security:print_sources()),
?assertEqual(ok, riak_core_security:print_user(<<"user">>)),
?assertEqual(ok, riak_core_security:print_groups()),
?assertEqual({error, {unknown_group, <<"all">>}}, riak_core_security:print_group(<<"all">>)),
ok
end}},
{timeout, 60, { "groups can be members of groups and inherit permissions from them",
fun() ->
?assertEqual(ok, riak_core_security:add_group(<<"sysadmin">>, [])),
?assertEqual(ok, riak_core_security:add_group(<<"superuser">>, [{"groups", ["sysadmin"]}])),
?assertEqual(ok, riak_core_security:add_user(<<"user">>,
[{"password","password"}])),
?assertEqual(ok, riak_core_security:add_source([<<"user">>], {{127, 0, 0, 1}, 32}, password, [])),
%% sysadmins can get/put on any key in a default bucket
?assertEqual(ok, riak_core_security:add_grant([<<"sysadmin">>], <<"default">>, ["riak_kv.get", "riak_kv.put"])),
%% authenticating from the wrong IP
?assertMatch({error, no_matching_sources}, riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {10, 0, 0, 1}}])),
{ok, Ctx} = riak_core_security:authenticate(<<"user">>, <<"password">>,
[{ip, {127, 0, 0, 1}}]),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.put", {<<"default">>, <<"myotherbucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:alter_user(<<"user">>, [{"groups", ["superuser"]}])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.put", {<<"default">>, <<"myotherbucket">>}}, Ctx)),
%% make sure these don't crash, at least
?assertEqual(ok, riak_core_security:print_users()),
?assertEqual(ok, riak_core_security:print_sources()),
?assertEqual(ok, riak_core_security:print_user(<<"user">>)),
?assertEqual(ok, riak_core_security:print_grants(<<"user">>)),
?assertEqual(ok, riak_core_security:print_groups()),
?assertEqual(ok, riak_core_security:print_group(<<"superuser">>)),
?assertEqual(ok, riak_core_security:print_group(<<"sysadmin">>)),
?assertEqual(ok, riak_core_security:alter_group(<<"superuser">>, [{"groups", []}])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:alter_group(<<"superuser">>, [{"groups", ["sysadmin"]}])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertMatch(ok, riak_core_security:del_group(<<"sysadmin">>)),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
%% check re-adding the group does not resurrect old permissions or memberships
?assertEqual(ok, riak_core_security:add_group(<<"sysadmin">>, [])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:add_grant([<<"sysadmin">>], <<"default">>, ["riak_kv.get", "riak_kv.put"])),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
%% re-adding the group membership does restore the permissions, though
?assertEqual(ok, riak_core_security:alter_group(<<"superuser">>, [{"groups", ["sysadmin"]}])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
ok
end}},
{timeout, 60, { "user/group disambiguation",
fun() ->
?assertEqual(ok, riak_core_security:add_group(<<"sysadmin">>, [])),
?assertEqual(ok, riak_core_security:add_user(<<"sysadmin">>, [{"password", "password"}])),
?assertEqual(ok, riak_core_security:add_source(all, {{127, 0, 0, 1}, 32}, password, [])),
?assertEqual({error, {duplicate_roles, [<<"sysadmin">>]}}, riak_core_security:add_grant([<<"sysadmin">>], <<"default">>, ["riak_kv.get", "riak_kv.put"])),
?assertEqual(ok, riak_core_security:add_grant([<<"user/sysadmin">>], <<"default">>, ["riak_kv.get", "riak_kv.put"])),
?assertEqual(ok, riak_core_security:add_grant([<<"group/sysadmin">>], any, ["riak_kv.get", "riak_kv.put"])),
{ok, Ctx} = riak_core_security:authenticate(<<"sysadmin">>, <<"password">>,
[{ip, {127, 0, 0, 1}}]),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"default">>, <<"mybucket">>}}, Ctx)),
?assertMatch({false, _, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"custom">>, <<"mybucket">>}}, Ctx)),
?assertEqual(ok, riak_core_security:alter_user(<<"sysadmin">>, [{"groups", ["sysadmin"]}])),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get", {<<"custom">>, <<"mybucket">>}}, Ctx)),
?assertMatch({true, _}, riak_core_security:check_permissions({"riak_kv.get"}, Ctx)),
?assertEqual(ok, riak_core_security:print_grants(<<"sysadmin">>)),
ok
end}},
{timeout, 60, { "Expected user/group errors",
fun() ->
?assertMatch({error, _}, riak_core_security:add_group(<<"all">>, [])),
?assertMatch({error, _}, riak_core_security:alter_user(<<"sysadmin">>, [{"password", "password"}])),
?assertMatch({error, _}, riak_core_security:print_user(<<"sysadmin">>)),
?assertMatch({error, _}, riak_core_security:alter_group(<<"sysadmin">>, [{"password", "password"}])),
?assertMatch({error, _}, riak_core_security:print_group(<<"sysadmin">>)),
?assertEqual(ok, riak_core_security:add_group(<<"sysadmin">>, [])),
?assertMatch({error, _}, riak_core_security:add_group(<<"sysadmin">>, [])),
?assertEqual(ok, riak_core_security:add_user(<<"sysadmin">>, [])),
?assertEqual({error, {duplicate_roles, [<<"sysadmin">>]}}, riak_core_security:add_grant([<<"sysadmin">>], <<"default">>, ["riak_kv.get", "riak_kv.put"])),
?assertMatch({error, {unknown_roles, [<<"sysadm">>]}}, riak_core_security:add_grant([<<"sysadm">>], any, ["riak_kv.put"])),
?assertMatch({error, {unknown_permission, _}}, riak_core_security:add_grant([<<"group/sysadmin">>], any, ["riak_kv.upsert"])),
?assertMatch({errors, [_, _]}, riak_core_security:add_grant([<<"group/foo">>], any, ["riak_kv.upsert"])),
?assertMatch({errors, [_, _]}, riak_core_security:add_grant([<<"sysadmin">>], any, ["riak_kv.upsert"])),
?assertMatch({error, {unknown_role, _}}, riak_core_security:print_grants(<<"foo">>)),
?assertEqual(ok, riak_core_security:add_user(<<"fred">>, [])),
?assertMatch({error, {unknown_role, _}}, riak_core_security:print_grants(<<"group/fred">>)),
ok
end}}
]}.
test_find_bucket_grants() ->
ok = riak_core_security:add_group("testgroup", []),
ok = riak_core_security:add_user("testuser1", [{groups, "testgroup"}]),
ok = riak_core_security:add_user("testuser2", []),
ok = riak_core_security:add_grant(["testuser1", "testuser2"], <<"bucket">>, ["riak_kv.get"]),
ok = riak_core_security:add_grant(["testuser2"], <<"bucket">>, ["riak_kv.put"]),
ok = riak_core_security:add_grant(all, <<"bucket">>, ["riak_kv.get"]),
ok = riak_core_security:add_grant(["group/testgroup"], <<"bucket">>, ["riak_kv.put"]),
Grants = riak_core_security:find_bucket_grants(<<"bucket">>, user),
GroupGrants = riak_core_security:find_bucket_grants(<<"bucket">>, group),
?assertMatch({_, ["riak_kv.get"]}, lists:keyfind("testuser1", 1, Grants)),
{_, Perms} = lists:keyfind("testuser2", 1, Grants),
?assertEqual(lists:sort(["riak_kv.get", "riak_kv.put"]), lists:sort(Perms)),
?assertMatch({_, ["riak_kv.get"]}, lists:keyfind(all, 1, GroupGrants)),
?assertMatch({_, ["riak_kv.put"]}, lists:keyfind("testgroup", 1, GroupGrants)).
test_find_user() ->
Options = [{key, value}],
Username = "testuser",
ok = riak_core_security:add_user(Username, Options),
?assertMatch(Options, riak_core_security:find_user(Username)).
test_find_one_user_by_metadata() ->
ok = riak_core_security:add_user("paul", [{"key_and_value", "match"}]),
?assertMatch({<<"paul">>, _Options},
riak_core_security:find_one_user_by_metadata("key_and_value", "match")),
?assertMatch({error, not_found},
riak_core_security:find_one_user_by_metadata("no", "match")).
-endif.
test_find_unique_user_by_metadata() ->
?assertMatch({error, not_found},
riak_core_security:find_unique_user_by_metadata("key", "val")),
ok = riak_core_security:add_user("user1", [{"key", "val"}]),
?assertMatch({<<"user1">>, _Options},
riak_core_security:find_unique_user_by_metadata("key", "val")),
ok = riak_core_security:add_user("user2", [{"key", "val"}]),
?assertMatch({error, not_unique},
riak_core_security:find_unique_user_by_metadata("key", "val")).