emqttd_access_SUITE.erl 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2013-2017 EMQ Enterprise, Inc. (http://emqtt.io)
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqttd_access_SUITE).
  17. -compile(export_all).
  18. -include("emqttd.hrl").
  19. -define(AC, emqttd_access_control).
  20. -import(emqttd_access_rule, [compile/1, match/3]).
  21. all() ->
  22. [{group, access_control},
  23. {group, access_rule}].
  24. groups() ->
  25. [{access_control, [sequence],
  26. [reload_acl,
  27. register_mod,
  28. unregister_mod,
  29. check_acl]},
  30. {access_rule, [],
  31. [compile_rule,
  32. match_rule]}].
  33. init_per_group(access_control, Config) ->
  34. application:load(emqttd),
  35. prepare_config(),
  36. Config;
  37. init_per_group(_Group, Config) ->
  38. Config.
  39. prepare_config() ->
  40. Rules = [{allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]},
  41. {allow, {user, "testuser"}, subscribe, ["a/b/c", "d/e/f/#"]},
  42. {allow, {user, "admin"}, pubsub, ["a/b/c", "d/e/f/#"]},
  43. {allow, {client, "testClient"}, subscribe, ["testTopics/testClient"]},
  44. {allow, all, subscribe, ["clients/%c"]},
  45. {allow, all, pubsub, ["users/%u/#"]},
  46. {deny, all, subscribe, ["$SYS/#", "#"]},
  47. {deny, all}],
  48. write_config("access_SUITE_acl.conf", Rules),
  49. Config = [{auth, anonymous, []},
  50. {acl, internal, [{config, "access_SUITE_acl.conf"},
  51. {nomatch, allow}]}],
  52. write_config("access_SUITE_emqttd.conf", Config),
  53. application:set_env(emqttd, conf, "access_SUITE_emqttd.conf").
  54. write_config(Filename, Terms) ->
  55. file:write_file(Filename, [io_lib:format("~tp.~n", [Term]) || Term <- Terms]).
  56. end_per_group(_Group, Config) ->
  57. Config.
  58. init_per_testcase(TestCase, Config) when TestCase =:= reload_acl;
  59. TestCase =:= register_mod;
  60. TestCase =:= unregister_mod;
  61. TestCase =:= check_acl ->
  62. {ok, _Pid} = ?AC:start_link(), Config;
  63. init_per_testcase(_TestCase, Config) ->
  64. Config.
  65. end_per_testcase(TestCase, _Config) when TestCase =:= reload_acl;
  66. TestCase =:= register_mod;
  67. TestCase =:= unregister_mod;
  68. TestCase =:= check_acl ->
  69. ?AC:stop();
  70. end_per_testcase(_TestCase, _Config) ->
  71. ok.
  72. %%--------------------------------------------------------------------
  73. %% emqttd_access_control
  74. %%--------------------------------------------------------------------
  75. reload_acl(_) ->
  76. [] = ?AC:reload_acl().
  77. register_mod(_) ->
  78. ok = ?AC:register_mod(acl, emqttd_acl_test_mod, []),
  79. {error, already_existed} = ?AC:register_mod(acl, emqttd_acl_test_mod, []),
  80. [{emqttd_acl_test_mod, _, 0}] = ?AC:lookup_mods(acl),
  81. ok = ?AC:register_mod(auth, emqttd_auth_anonymous_test_mod,[]),
  82. ok = ?AC:register_mod(auth, emqttd_auth_dashboard, [], 99),
  83. [{emqttd_auth_dashboard, _, 99},
  84. {emqttd_auth_anonymous_test_mod, _, 0}] = ?AC:lookup_mods(auth).
  85. unregister_mod(_) ->
  86. ok = ?AC:register_mod(acl, emqttd_acl_test_mod, []),
  87. [{emqttd_acl_test_mod, _, 0}] = ?AC:lookup_mods(acl),
  88. ok = ?AC:unregister_mod(acl, emqttd_acl_test_mod),
  89. timer:sleep(5),
  90. [] = ?AC:lookup_mods(acl),
  91. ok = ?AC:register_mod(auth, emqttd_auth_anonymous_test_mod,[]),
  92. [{emqttd_auth_anonymous_test_mod, _, 0}] = ?AC:lookup_mods(auth),
  93. ok = ?AC:unregister_mod(auth, emqttd_auth_anonymous_test_mod),
  94. timer:sleep(5),
  95. [] = ?AC:lookup_mods(auth).
  96. check_acl(_) ->
  97. User1 = #mqtt_client{client_id = <<"client1">>, username = <<"testuser">>},
  98. User2 = #mqtt_client{client_id = <<"client2">>, username = <<"xyz">>},
  99. allow = ?AC:check_acl(User1, subscribe, <<"users/testuser/1">>),
  100. allow = ?AC:check_acl(User1, subscribe, <<"clients/client1">>),
  101. allow = ?AC:check_acl(User1, subscribe, <<"clients/client1/x/y">>),
  102. allow = ?AC:check_acl(User1, publish, <<"users/testuser/1">>),
  103. allow = ?AC:check_acl(User1, subscribe, <<"a/b/c">>),
  104. allow = ?AC:check_acl(User2, subscribe, <<"a/b/c">>).
  105. %%--------------------------------------------------------------------
  106. %% emqttd_access_rule
  107. %%--------------------------------------------------------------------
  108. compile_rule(_) ->
  109. {allow, {'and', [{ipaddr, {{127,0,0,1}, {127,0,0,1}, 32}},
  110. {user, <<"user">>}]}, subscribe, [ [<<"$SYS">>, '#'], ['#'] ]} =
  111. compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"user">>}]}, subscribe, ["$SYS/#", "#"]}),
  112. {allow, {'or', [{ipaddr, {{127,0,0,1}, {127,0,0,1}, 32}},
  113. {user, <<"user">>}]}, subscribe, [ [<<"$SYS">>, '#'], ['#'] ]} =
  114. compile({allow, {'or', [{ipaddr, "127.0.0.1"}, {user, <<"user">>}]}, subscribe, ["$SYS/#", "#"]}),
  115. {allow, {ipaddr, {{127,0,0,1}, {127,0,0,1}, 32}}, subscribe, [ [<<"$SYS">>, '#'], ['#'] ]} =
  116. compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]}),
  117. {allow, {user, <<"testuser">>}, subscribe, [ [<<"a">>, <<"b">>, <<"c">>], [<<"d">>, <<"e">>, <<"f">>, '#'] ]} =
  118. compile({allow, {user, "testuser"}, subscribe, ["a/b/c", "d/e/f/#"]}),
  119. {allow, {user, <<"admin">>}, pubsub, [ [<<"d">>, <<"e">>, <<"f">>, '#'] ]} =
  120. compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]}),
  121. {allow, {client, <<"testClient">>}, publish, [ [<<"testTopics">>, <<"testClient">>] ]} =
  122. compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]}),
  123. {allow, all, pubsub, [{pattern, [<<"clients">>, <<"%c">>]}]} =
  124. compile({allow, all, pubsub, ["clients/%c"]}),
  125. {allow, all, subscribe, [{pattern, [<<"users">>, <<"%u">>, '#']}]} =
  126. compile({allow, all, subscribe, ["users/%u/#"]}),
  127. {deny, all, subscribe, [ [<<"$SYS">>, '#'], ['#'] ]} =
  128. compile({deny, all, subscribe, ["$SYS/#", "#"]}),
  129. {allow, all} = compile({allow, all}),
  130. {deny, all} = compile({deny, all}).
  131. match_rule(_) ->
  132. User = #mqtt_client{peername = {{127,0,0,1}, 2948}, client_id = <<"testClient">>, username = <<"TestUser">>},
  133. User2 = #mqtt_client{peername = {{192,168,0,10}, 3028}, client_id = <<"testClient">>, username = <<"TestUser">>},
  134. {matched, allow} = match(User, <<"Test/Topic">>, {allow, all}),
  135. {matched, deny} = match(User, <<"Test/Topic">>, {deny, all}),
  136. {matched, allow} = match(User, <<"Test/Topic">>, compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]})),
  137. {matched, allow} = match(User2, <<"Test/Topic">>, compile({allow, {ipaddr, "192.168.0.1/24"}, subscribe, ["$SYS/#", "#"]})),
  138. {matched, allow} = match(User, <<"d/e/f/x">>, compile({allow, {user, "TestUser"}, subscribe, ["a/b/c", "d/e/f/#"]})),
  139. nomatch = match(User, <<"d/e/f/x">>, compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]})),
  140. {matched, allow} = match(User, <<"testTopics/testClient">>, compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]})),
  141. {matched, allow} = match(User, <<"clients/testClient">>, compile({allow, all, pubsub, ["clients/%c"]})),
  142. {matched, allow} = match(#mqtt_client{username = <<"user2">>}, <<"users/user2/abc/def">>,
  143. compile({allow, all, subscribe, ["users/%u/#"]})),
  144. {matched, deny} = match(User, <<"d/e/f">>, compile({deny, all, subscribe, ["$SYS/#", "#"]})),
  145. Rule = compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, <<"Topic">>}),
  146. nomatch = match(User, <<"Topic">>, Rule),
  147. AndRule = compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"TestUser">>}]}, publish, <<"Topic">>}),
  148. {matched, allow} = match(User, <<"Topic">>, AndRule),
  149. OrRule = compile({allow, {'or', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, ["Topic"]}),
  150. {matched, allow} = match(User, <<"Topic">>, OrRule).