1: -module(acl_SUITE). 2: -compile([export_all, nowarn_export_all]). 3: 4: -include_lib("eunit/include/eunit.hrl"). 5: 6: -import(mongoose_config, [set_opt/2, unset_opt/1]). 7: 8: all() -> 9: [{group, dynamic_domains}, 10: {group, static_domains}]. 11: 12: groups() -> 13: [{dynamic_domains, [], basic_test_cases() ++ host_type_test_cases()}, 14: {static_domains, [], basic_test_cases()}]. 15: 16: basic_test_cases() -> 17: [ 18: all_rule_returns_allow, 19: none_rule_returns_deny, 20: basic_access_rules, 21: compound_access_rules, 22: host_specific_access_rules, 23: all_and_none_specs, 24: match_domain, 25: different_specs_matching_the_same_user 26: ]. 27: 28: host_type_test_cases() -> 29: [ 30: match_host_specific_rule_for_host_type 31: ]. 32: 33: init_per_suite(Config) -> 34: {ok, _} = application:ensure_all_started(jid), 35: Config. 36: 37: end_per_suite(_Config) -> 38: mongoose_domain_api:stop(), 39: meck:unload(), 40: ok. 41: 42: init_per_group(dynamic_domains, Config) -> 43: [{dynamic_domains, true}|Config]; 44: init_per_group(_Group, Config) -> 45: Config. 46: 47: end_per_group(_Group, Config) -> 48: Config. 49: 50: init_per_testcase(_TC, Config) -> 51: Config. 52: 53: end_per_testcase(_TC, _Config) -> 54: clean_config(). 55: 56: host_type() -> 57: <<"test host type">>. 58: 59: all_rule_returns_allow(_Config) -> 60: JID = jid:make(<<"pawel">>, <<"phost">>, <<"test">>), 61: ?assertEqual(allow, acl:match_rule(global, all, JID)), 62: ?assertEqual(allow, acl:match_rule(<<"phost">>, all, JID)), 63: ?assertEqual(allow, acl:match_rule(<<"localhost">>, all, JID)), 64: ok. 65: 66: none_rule_returns_deny(_Config) -> 67: JID = jid:make(<<"gawel">>, <<"phost">>, <<"test">>), 68: ?assertEqual(deny, acl:match_rule(global, none, JID)), 69: ?assertEqual(deny, acl:match_rule(<<"phost">>, none, JID)), 70: ?assertEqual(deny, acl:match_rule(<<"localhost">>, none, JID)), 71: ok. 72: 73: basic_access_rules(_Config) -> 74: JID = jid:make(<<"pawel">>, <<"phost">>, <<"test">>), 75: 76: %% rule is not defined deny by default - deny 77: ?assertEqual(deny, (acl:match_rule(global, single_rule, JID))), 78: 79: %% add the rule and recheck 80: set_opt({access, global}, #{single_rule => [#{acl => all, value => allow}]}), 81: ?assertEqual(allow, (acl:match_rule(global, single_rule, JID))), 82: 83: %% override it to deny rule 84: set_opt({access, global}, #{single_rule => [#{acl => all, value => deny}]}), 85: ?assertEqual(deny, (acl:match_rule(global, single_rule, JID))), 86: 87: %% deny by default 88: set_opt({access, global}, #{single_rule => []}), 89: ?assertEqual(deny, (acl:match_rule(global, single_rule, JID))), 90: 91: %% allow nobody 92: set_opt({access, global}, #{single_rule => [#{acl => none, value => allow}]}), 93: ?assertEqual(deny, (acl:match_rule(global, single_rule, JID))), 94: ok. 95: 96: host_specific_access_rules(Config) -> 97: given_registered_domains(Config, [<<"poznan">>, <<"wroclaw">>]), 98: 99: PozAdmin = jid:make(<<"gawel">>, <<"poznan">>, <<"test">>), 100: Pawel = jid:make(<<"pawel">>, <<"wroclaw">>, <<"test">>), 101: 102: set_opt({acl, <<"poznan">>}, #{admin_poz => acl(#{user => <<"gawel">>, 103: server => <<"poznan">>})}), 104: set_opt({acl, <<"wroclaw">>}, #{admin_poz => acl(#{user => <<"gawel">>, 105: server => <<"poznan">>})}), 106: set_opt({access, <<"poznan">>}, #{only_poz_admin => [#{acl => admin_poz, value => allow}, 107: #{acl => all, value => deny}]}), 108: set_opt({access, <<"wroclaw">>}, #{only_poz_admin => [#{acl => admin_poz, value => deny}, 109: #{acl => all, value => allow}]}), 110: 111: ?assertEqual(allow, acl:match_rule(<<"poznan">>, <<"poznan">>, only_poz_admin, PozAdmin)), 112: ?assertEqual(deny, acl:match_rule(<<"poznan">>, <<"wroclaw">>, only_poz_admin, Pawel)), 113: 114: ?assertEqual(deny, acl:match_rule(<<"wroclaw">>, <<"poznan">>, only_poz_admin, PozAdmin)), 115: ?assertEqual(allow, acl:match_rule(<<"wroclaw">>, <<"wroclaw">>, only_poz_admin, Pawel)), 116: ok. 117: 118: compound_access_rules(Config) -> 119: given_registered_domains(Config, [<<"krakow">>]), 120: 121: KrkAdmin = jid:make(<<"gawel">>, <<"krakow">>, <<"test">>), 122: KrkNormal = jid:make(<<"pawel">>, <<"krakow">>, <<"test">>), 123: 124: %% add admin user rule 125: set_opt({acl, global}, #{admin_wawa => acl(#{user => <<"gawel">>, server => <<"wawa">>}), 126: admin_krakow => acl(#{user => <<"gawel">>, server => <<"krakow">>})}), 127: set_opt({access, global}, #{only_krakow_admin => [#{acl => admin_krakow, value => allow}, 128: #{acl => all, value => deny}], 129: only_wawa_admin => [#{acl => admin_wawa, value => allow}, 130: #{acl => all, value => deny}]}), 131: 132: ?assertEqual(deny, acl:match_rule(global, only_krakow_admin, KrkNormal)), 133: ?assertEqual(deny, acl:match_rule(global, only_wawa_admin, KrkNormal)), 134: 135: ?assertEqual(allow, acl:match_rule(global, only_krakow_admin, KrkAdmin)), 136: ?assertEqual(deny, acl:match_rule(global, only_wawa_admin, KrkAdmin)), 137: ok. 138: 139: all_and_none_specs(Config) -> 140: given_registered_domains(Config, [<<"zakopane">>]), 141: 142: User = jid:make(<<"pawel">>, <<"zakopane">>, <<"test">>), 143: set_opt({acl, global}, #{a_users => acl(#{match => all}), 144: n_users => acl(#{match => none})}), 145: set_opt({access, global}, #{all_users => [#{acl => a_users, value => allow}, 146: #{acl => all, value => deny}], 147: none_users => [#{acl => n_users, value => allow}, 148: #{acl => all, value => deny}]}), 149: 150: ?assertEqual(allow, acl:match_rule(global, <<"zakopane">>, all_users, User)), 151: ?assertEqual(deny, acl:match_rule(global, <<"zakopane">>, none_users, User)), 152: 153: %% domain doesn't matter for 'all' 154: ?assertEqual(allow, acl:match_rule(global, <<"any domain">>, all_users, User)), 155: ?assertEqual(deny, acl:match_rule(global, <<"any domain">>, none_users, User)), 156: ok. 157: 158: match_domain(Config) -> 159: given_registered_domains(Config, [<<"zakopane">>, <<"gdansk">>]), 160: 161: UserZa = jid:make(<<"pawel">>, <<"zakopane">>, <<"test">>), 162: UserGd = jid:make(<<"pawel">>, <<"gdansk">>, <<"test">>), 163: UserTo = jid:make(<<"pawel">>, <<"torun">>, <<"test">>), 164: UserZb = jid:make(<<"pawel">>, <<"zakopane">>, <<"best">>), 165: 166: set_opt({acl, global}, #{a_users => [#{match => current_domain, resource => <<"test">>}], 167: b_users => [#{match => any_hosted_domain, resource => <<"test">>}], 168: c_users => [#{match => all, resource => <<"test">>}]}), 169: set_opt({access, global}, #{rule => [#{acl => a_users, value => a}, 170: #{acl => b_users, value => b}, 171: #{acl => c_users, value => c}, 172: #{acl => all, value => d}]}), 173: 174: ?assertEqual(a, acl:match_rule(global, <<"zakopane">>, rule, UserZa)), 175: ?assertEqual(b, acl:match_rule(global, <<"zakopane">>, rule, UserGd)), 176: ?assertEqual(c, acl:match_rule(global, <<"zakopane">>, rule, UserTo)), 177: ?assertEqual(d, acl:match_rule(global, <<"zakopane">>, rule, UserZb)), 178: ok. 179: 180: match_host_specific_rule_for_host_type(Config) -> 181: given_registered_domains(Config, [<<"gdansk">>, <<"koszalin">>]), 182: 183: UserGd = jid:make(<<"pawel">>, <<"gdansk">>, <<"res">>), 184: 185: set_opt({acl, <<"test type">>}, #{admin => acl(#{user => <<"pawel">>})}), 186: set_opt({access, <<"test type">>}, #{allow_admin => [#{acl => admin, value => allow}, 187: #{acl => all, value => deny}]}), 188: 189: %% Check for host type for a specific domain 190: ?assertEqual(allow, acl:match_rule(<<"test type">>, <<"gdansk">>, allow_admin, UserGd)), 191: ?assertEqual(deny, acl:match_rule(<<"test type">>, <<"koszalin">>, allow_admin, UserGd)), 192: ?assertEqual(deny, acl:match_rule(<<"empty type">>, <<"gdansk">>, allow_admin, UserGd)), 193: 194: %% Check for host type for any domain 195: ?assertEqual(allow, acl:match_rule(<<"test type">>, allow_admin, UserGd)), 196: ?assertEqual(deny, acl:match_rule(<<"empty type">>, allow_admin, UserGd)), 197: 198: %% Check globally for a specific domain 199: ?assertEqual(deny, acl:match_rule(global, <<"gdansk">>, allow_admin, UserGd)), 200: ?assertEqual(deny, acl:match_rule(global, <<"koszalin">>, allow_admin, UserGd)), 201: 202: %% Check globally for any domain 203: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserGd)). 204: 205: different_specs_matching_the_same_user(Config) -> 206: given_registered_domains(Config, [<<"gdansk">>, <<"koszalin">>]), 207: 208: UserGd = jid:make(<<"pawel">>, <<"gdansk">>, <<"res">>), 209: UserKo = jid:make(<<"pawel">>, <<"koszalin">>,<<"res1">>), 210: 211: %% invariand we are going to change admin acl only 212: set_opt({access, global}, #{allow_admin => [#{acl => admin, value => allow}, 213: #{acl => all, value => deny}]}), 214: 215: %% match on pawel 216: set_opt({acl, global}, #{admin => acl(#{user => <<"pawel">>})}), 217: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 218: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserKo)), 219: 220: %% match on pawel@gdansk 221: set_opt({acl, global}, #{admin => acl(#{user => <<"pawel">>, server => <<"gdansk">>})}), 222: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 223: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 224: 225: %% match on gdansk 226: set_opt({acl, global}, #{admin => acl(#{server => <<"gdansk">>})}), 227: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 228: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 229: 230: %% match on res 231: set_opt({acl, global}, #{admin => acl(#{resource => <<"res">>})}), 232: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 233: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 234: 235: %% match on user regex 236: set_opt({acl, global}, #{admin => acl(#{user_regexp => <<"^paw.*">>})}), 237: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 238: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserKo)), 239: 240: %% match on user regex 241: set_opt({acl, global}, #{admin => acl(#{user_regexp => <<"^paw.*">>, server => <<"gdansk">>})}), 242: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 243: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 244: 245: %% match on server regex 246: set_opt({acl, global}, #{admin => acl(#{server_regexp => <<"^gda.*">>})}), 247: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 248: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 249: 250: %% match on resource regex 251: set_opt({acl, global}, #{admin => acl(#{resource_regexp => <<"^res.*">>})}), 252: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 253: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserKo)), 254: 255: %% match node regex 256: set_opt({acl, global}, #{admin => acl(#{user_regexp => <<"^pawe.*">>, 257: server_regexp => <<"^gda.*">>})}), 258: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 259: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 260: 261: %% match on user glob 262: set_opt({acl, global}, #{admin => acl(#{user_glob => <<"paw??">>})}), 263: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 264: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserKo)), 265: 266: %% match on user glob 267: set_opt({acl, global}, #{admin => acl(#{user_glob => <<"paw??">>, server => <<"gdansk">>})}), 268: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 269: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 270: 271: %% match on server glob 272: set_opt({acl, global}, #{admin => acl(#{server_glob => <<"gda*">>})}), 273: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 274: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 275: 276: %% match on server glob 277: set_opt({acl, global}, #{admin => acl(#{resource_glob => <<"re*">>})}), 278: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 279: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserKo)), 280: 281: %% match on node glob 282: set_opt({acl, global}, #{admin => acl(#{user_glob => <<"pawe?">>, server_glob => <<"gd*">>})}), 283: ?assertEqual(allow, acl:match_rule(global, allow_admin, UserGd)), 284: ?assertEqual(deny, acl:match_rule(global, allow_admin, UserKo)), 285: 286: ok. 287: 288: acl(Spec) -> 289: [maps:merge(#{match => current_domain}, Spec)]. 290: 291: clean_config() -> 292: [persistent_term:erase(Key) || {Key = {mongoose_config, _}, _Value} <- persistent_term:get()], 293: ok. 294: 295: given_registered_domains(Config, DomainsList) -> 296: case proplists:get_value(dynamic_domains, Config, false) of 297: true -> 298: register_dynamic_domains(DomainsList); 299: false -> 300: register_static_domains(DomainsList) 301: end. 302: 303: register_static_domains(DomainsList) -> 304: mongoose_config:set_opt(hosts, DomainsList), 305: mongoose_config:set_opt(host_types, []), 306: mongoose_domain_api:stop(), 307: mongoose_domain_api:init(). 308: 309: register_dynamic_domains(DomainsList) -> 310: mongoose_config:set_opt(hosts, []), 311: mongoose_config:set_opt(host_types, [<<"test type">>, <<"empty type">>]), 312: mongoose_domain_api:stop(), 313: mongoose_domain_api:init(), 314: [mongoose_domain_core:insert(Domain, <<"test type">>, test) || Domain <- DomainsList].