Comparison

core/usermanager.lua @ 12658:7ca5645f46cd

usermanager: Remove concept of global authz provider Rationale: - Removes a bunch of code! - We don't have many cases where an actor is not bound to one of our hosts - A notable exception is the admin shell, but if we ever attempt to lock those sessions down, there is a load of other work that also has to be done. And it's not clear if we would need a global authz provider for that anyway. - Removes an extra edge case from the necessary mental model for operators - Sessions that aren't bound to a host generally are anonymous or have an alternative auth model (such as by IP addres). - With the encapsulation now provided by util.roles, ad-hoc "detached roles" can still be created anyway by code that needs them.
author Matthew Wild <mwild1@gmail.com>
date Fri, 12 Aug 2022 16:21:57 +0100
parent 12657:1ab845e80fe7
child 12659:c0eea4f6c739
comparison
equal deleted inserted replaced
12657:1ab845e80fe7 12658:7ca5645f46cd
7 -- 7 --
8 8
9 local modulemanager = require "core.modulemanager"; 9 local modulemanager = require "core.modulemanager";
10 local log = require "util.logger".init("usermanager"); 10 local log = require "util.logger".init("usermanager");
11 local type = type; 11 local type = type;
12 local it = require "util.iterators"; 12 local jid_split = require "util.jid".split;
13 local jid_prep, jid_split = require "util.jid".prep, require "util.jid".split;
14 local config = require "core.configmanager"; 13 local config = require "core.configmanager";
15 local sasl_new = require "util.sasl".new; 14 local sasl_new = require "util.sasl".new;
16 local storagemanager = require "core.storagemanager"; 15 local storagemanager = require "core.storagemanager";
17 local set = require "util.set";
18 16
19 local prosody = _G.prosody; 17 local prosody = _G.prosody;
20 local hosts = prosody.hosts; 18 local hosts = prosody.hosts;
21 19
22 local setmetatable = setmetatable; 20 local setmetatable = setmetatable;
32 return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, { 30 return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, {
33 __index = function(self, method) return dummy; end --luacheck: ignore 212 31 __index = function(self, method) return dummy; end --luacheck: ignore 212
34 }); 32 });
35 end 33 end
36 34
37 local global_admins_config = config.get("*", "admins"); 35 local fallback_authz_provider = {
38 if type(global_admins_config) ~= "table" then
39 global_admins_config = nil; -- TODO: factor out moduleapi magic config handling and use it here
40 end
41 local global_admins = set.new(global_admins_config) / jid_prep;
42
43 local admin_role = { ["prosody:admin"] = true };
44 local global_authz_provider = {
45 get_user_roles = function (user) end; --luacheck: ignore 212/user 36 get_user_roles = function (user) end; --luacheck: ignore 212/user
46 get_jids_with_role = function (role) 37 get_jids_with_role = function (role) end; --luacheck: ignore 212
47 if role ~= "prosody:admin" then return {}; end
48 return it.to_array(global_admins);
49 end;
50 set_user_roles = function (user, roles) end; -- luacheck: ignore 212 38 set_user_roles = function (user, roles) end; -- luacheck: ignore 212
51 set_jid_roles = function (jid, roles) end; -- luacheck: ignore 212 39 set_jid_roles = function (jid, roles) end; -- luacheck: ignore 212
52 40
53 get_user_default_role = function (user) end; -- luacheck: ignore 212 41 get_user_default_role = function (user) end; -- luacheck: ignore 212
54 get_users_with_role = function (role_name) end; -- luacheck: ignore 212 42 get_users_with_role = function (role_name) end; -- luacheck: ignore 212
64 local host_session = hosts[host]; 52 local host_session = hosts[host];
65 53
66 local authz_provider_name = config.get(host, "authorization") or "internal"; 54 local authz_provider_name = config.get(host, "authorization") or "internal";
67 55
68 local authz_mod = modulemanager.load(host, "authz_"..authz_provider_name); 56 local authz_mod = modulemanager.load(host, "authz_"..authz_provider_name);
69 host_session.authz = authz_mod or global_authz_provider; 57 host_session.authz = authz_mod or fallback_authz_provider;
70 58
71 if host_session.type ~= "local" then return; end 59 if host_session.type ~= "local" then return; end
72 60
73 host_session.events.add_handler("item-added/auth-provider", function (event) 61 host_session.events.add_handler("item-added/auth-provider", function (event)
74 local provider = event.item; 62 local provider = event.item;
153 -- Returns a map of { [role_name] = role, ... } that a user is allowed to assume 141 -- Returns a map of { [role_name] = role, ... } that a user is allowed to assume
154 local function get_user_roles(user, host) 142 local function get_user_roles(user, host)
155 if host and not hosts[host] then return false; end 143 if host and not hosts[host] then return false; end
156 if type(user) ~= "string" then return false; end 144 if type(user) ~= "string" then return false; end
157 145
158 host = host or "*"; 146 return hosts[host].authz.get_user_roles(user);
159
160 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
161 return authz_provider.get_user_roles(user);
162 end 147 end
163 148
164 local function get_user_default_role(user, host) 149 local function get_user_default_role(user, host)
165 if host and not hosts[host] then return false; end 150 if host and not hosts[host] then return false; end
166 if type(user) ~= "string" then return false; end 151 if type(user) ~= "string" then return false; end
167 152
168 host = host or "*"; 153 return hosts[host].authz.get_user_default_role(user);
169
170 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
171 return authz_provider.get_user_default_role(user);
172 end 154 end
173 155
174 -- Accepts a set of role names which the user is allowed to assume 156 -- Accepts a set of role names which the user is allowed to assume
175 local function set_user_roles(user, host, roles) 157 local function set_user_roles(user, host, roles)
176 if host and not hosts[host] then return false; end 158 if host and not hosts[host] then return false; end
177 if type(user) ~= "string" then return false; end 159 if type(user) ~= "string" then return false; end
178 160
179 host = host or "*"; 161 local ok, err = hosts[host].authz.set_user_roles(user, roles);
180
181 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
182 local ok, err = authz_provider.set_user_roles(user, roles);
183 if ok then 162 if ok then
184 prosody.events.fire_event("user-roles-changed", { 163 prosody.events.fire_event("user-roles-changed", {
185 username = user, host = host 164 username = user, host = host
186 }); 165 });
187 end 166 end
188 return ok, err; 167 return ok, err;
189 end 168 end
190 169
191 local function get_jid_role(jid, host) 170 local function get_jid_role(jid, host)
192 host = host or "*";
193 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
194 local jid_node, jid_host = jid_split(jid); 171 local jid_node, jid_host = jid_split(jid);
195 if host == jid_host and jid_node then 172 if host == jid_host and jid_node then
196 return authz_provider.get_user_default_role(jid_node); 173 return hosts[host].authz.get_user_default_role(jid_node);
197 end 174 end
198 return authz_provider.get_jid_role(jid); 175 return hosts[host].authz.get_jid_role(jid);
199 end 176 end
200 177
201 local function set_jid_role(jid, host, role_name) 178 local function set_jid_role(jid, host, role_name)
202 host = host or "*";
203 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
204 local _, jid_host = jid_split(jid); 179 local _, jid_host = jid_split(jid);
205 if host == jid_host then 180 if host == jid_host then
206 return nil, "unexpected-local-jid"; 181 return nil, "unexpected-local-jid";
207 end 182 end
208 return authz_provider.set_jid_role(jid, role_name) 183 return hosts[host].authz.set_jid_role(jid, role_name)
209 end 184 end
210 185
211 local function get_users_with_role(role, host) 186 local function get_users_with_role(role, host)
212 if not hosts[host] then return false; end 187 if not hosts[host] then return false; end
213 if type(role) ~= "string" then return false; end 188 if type(role) ~= "string" then return false; end
214
215 return hosts[host].authz.get_users_with_role(role); 189 return hosts[host].authz.get_users_with_role(role);
216 end 190 end
217 191
218 local function get_jids_with_role(role, host) 192 local function get_jids_with_role(role, host)
219 if host and not hosts[host] then return false; end 193 if host and not hosts[host] then return false; end
220 if type(role) ~= "string" then return false; end 194 if type(role) ~= "string" then return false; end
221 195 return hosts[host].authz.get_jids_with_role(role);
222 host = host or "*";
223
224 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
225 return authz_provider.get_jids_with_role(role);
226 end 196 end
227 197
228 local function get_role_by_name(role_name, host) 198 local function get_role_by_name(role_name, host)
229 if host and not hosts[host] then return false; end 199 if host and not hosts[host] then return false; end
230 if type(role_name) ~= "string" then return false; end 200 if type(role_name) ~= "string" then return false; end
231 201 return hosts[host].authz.get_role_by_name(role_name);
232 host = host or "*";
233
234 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
235 return authz_provider.get_role_by_name(role_name);
236 end 202 end
237 203
238 return { 204 return {
239 new_null_provider = new_null_provider; 205 new_null_provider = new_null_provider;
240 initialize_host = initialize_host; 206 initialize_host = initialize_host;