mirror of
https://github.com/xcat2/confluent.git
synced 2025-04-01 08:08:46 +00:00
Add user groups to confluent
This allows a system/ldap group to be used instead of directly specifying individual authorized users.
This commit is contained in:
parent
571a34cba2
commit
31f2161b57
@ -26,6 +26,7 @@ import Cryptodome.Protocol.KDF as KDF
|
||||
import hashlib
|
||||
import hmac
|
||||
import multiprocessing
|
||||
import confluent.userutil as userutil
|
||||
try:
|
||||
import PAM
|
||||
except ImportError:
|
||||
@ -121,6 +122,11 @@ def authorize(name, element, tenant=False, operation='create',
|
||||
if skipuserobj:
|
||||
return None, manager, user, tenant, skipuserobj
|
||||
userobj = manager.get_user(user)
|
||||
if not userobj:
|
||||
for group in userutil.grouplist(user):
|
||||
userobj = manager.get_usergroup(group)
|
||||
if userobj:
|
||||
break
|
||||
if userobj: # returning
|
||||
return userobj, manager, user, tenant, skipuserobj
|
||||
return None
|
||||
@ -160,6 +166,14 @@ def check_user_passphrase(name, passphrase, element=None, tenant=False):
|
||||
credobj = Credentials(user, passphrase)
|
||||
cfm = configmanager.ConfigManager(tenant, username=user)
|
||||
ucfg = cfm.get_user(user)
|
||||
if ucfg is None:
|
||||
try:
|
||||
for group in userutil.grouplist(user):
|
||||
ucfg = cfm.get_usergroup(group)
|
||||
if ucfg:
|
||||
break
|
||||
except KeyError:
|
||||
pass
|
||||
if ucfg is None:
|
||||
eventlet.sleep(0.05)
|
||||
return None
|
||||
|
@ -169,6 +169,24 @@ def _do_notifier(cfg, watcher, callback):
|
||||
logException()
|
||||
|
||||
|
||||
|
||||
def _rpc_master_del_usergroup(tenant, name, attributemap):
|
||||
ConfigManager(tenant).set_user(name, attributemap)
|
||||
|
||||
|
||||
def _rpc_del_usergroup(tenant, name, attributemap):
|
||||
ConfigManager(tenant)._true_set_user(name, attributemap)
|
||||
|
||||
|
||||
|
||||
def _rpc_master_set_usergroup(tenant, name, attributemap):
|
||||
ConfigManager(tenant).set_user(name, attributemap)
|
||||
|
||||
|
||||
def _rpc_set_usergroup(tenant, name, attributemap):
|
||||
ConfigManager(tenant)._true_set_user(name, attributemap)
|
||||
|
||||
|
||||
def _rpc_master_set_user(tenant, name, attributemap):
|
||||
ConfigManager(tenant).set_user(name, attributemap)
|
||||
|
||||
@ -220,9 +238,19 @@ def _rpc_del_user(tenant, name):
|
||||
def _rpc_master_create_user(tenant, *args):
|
||||
ConfigManager(tenant).create_user(*args)
|
||||
|
||||
|
||||
def _rpc_master_create_usergroup(tenant, *args):
|
||||
ConfigManager(tenant).create_usergroup(*args)
|
||||
|
||||
|
||||
def _rpc_create_user(tenant, *args):
|
||||
ConfigManager(tenant)._true_create_user(*args)
|
||||
|
||||
|
||||
def _rpc_create_usergroup(tenant, *args):
|
||||
ConfigManager(tenant)._true_create_usergroup(*args)
|
||||
|
||||
|
||||
def _rpc_master_del_groups(tenant, groups):
|
||||
ConfigManager(tenant).del_groups(groups)
|
||||
|
||||
@ -1182,6 +1210,12 @@ class ConfigManager(object):
|
||||
except KeyError:
|
||||
return []
|
||||
|
||||
def list_usergroups(self):
|
||||
try:
|
||||
return list(self._cfgstore['usergroups'])
|
||||
except KeyError:
|
||||
return []
|
||||
|
||||
def get_user(self, name):
|
||||
"""Get user information from DB
|
||||
|
||||
@ -1219,12 +1253,37 @@ class ConfigManager(object):
|
||||
:param groupname: the name of teh group to modify
|
||||
:param attributemap: The mapping of keys to values to set
|
||||
"""
|
||||
if cfgleader:
|
||||
return exec_on_leader('_rpc_master_set_usergroup', self.tenant,
|
||||
groupname, attributemap)
|
||||
if cfgstreams:
|
||||
exec_on_followers('_rpc_set_usergroup', self.tenant, groupname,
|
||||
attributemap)
|
||||
self._true_set_usergroup(groupname, attributemap)
|
||||
|
||||
def _true_set_usergroup(self, groupname, attributemap):
|
||||
for attribute in attributemap:
|
||||
self._cfgstore['usergroups'][attribute] = attributemap[attribute]
|
||||
_mark_dirtykey('usergroups', groupname, self.tenant)
|
||||
self._bg_sync_to_file()
|
||||
|
||||
def create_usergroup(self, groupname, role="Administrator"):
|
||||
"""Create a new user
|
||||
|
||||
:param groupname: The name of the user group
|
||||
:param role: The role the user should be considered. Can be
|
||||
"Administrator" or "Technician", defaults to
|
||||
"Administrator"
|
||||
"""
|
||||
if cfgleader:
|
||||
return exec_on_leader('_rpc_master_create_usergroup', self.tenant,
|
||||
groupname, role)
|
||||
if cfgstreams:
|
||||
exec_on_followers('_rpc_create_usergroup', self.tenant, groupname,
|
||||
role)
|
||||
self._true_create_usergroup(groupname, role)
|
||||
|
||||
def _true_create_usergroup(self, groupname, role="Administrator"):
|
||||
if 'usergroups' not in self._cfgstore:
|
||||
self._cfgstore['usergroups'] = {}
|
||||
groupname = groupname.encode('utf-8')
|
||||
@ -1232,6 +1291,20 @@ class ConfigManager(object):
|
||||
raise Exception("Duplicate groupname requested")
|
||||
self._cfgstore['usergroups'][groupname] = {'role': role}
|
||||
_mark_dirtykey('usergroups', groupname, self.tenant)
|
||||
self._bg_sync_to_file()
|
||||
|
||||
def del_usergroup(self, name):
|
||||
if cfgleader:
|
||||
return exec_on_leader('_rpc_master_del_usergroup', self.tenant, name)
|
||||
if cfgstreams:
|
||||
exec_on_followers('_rpc_del_usergroup', self.tenant, name)
|
||||
self._true_del_usergroup(name)
|
||||
|
||||
def _true_del_usergroup(self, name):
|
||||
if name in self._cfgstore['usergroups']:
|
||||
del self._cfgstore['usergroups'][name]
|
||||
_mark_dirtykey('usergroups', name, self.tenant)
|
||||
self._bg_sync_to_file()
|
||||
|
||||
def set_user(self, name, attributemap):
|
||||
"""Set user attribute(s)
|
||||
|
@ -124,7 +124,7 @@ def load_plugins():
|
||||
|
||||
|
||||
rootcollections = ['discovery/', 'events/', 'networking/',
|
||||
'noderange/', 'nodes/', 'nodegroups/', 'users/', 'version']
|
||||
'noderange/', 'nodes/', 'nodegroups/', 'usergroups/' , 'users/', 'version']
|
||||
|
||||
|
||||
class PluginRoute(object):
|
||||
@ -396,6 +396,21 @@ def create_user(inputdata, configmanager):
|
||||
configmanager.create_user(username, attributemap=inputdata)
|
||||
|
||||
|
||||
def create_usergroup(inputdata, configmanager):
|
||||
try:
|
||||
groupname = inputdata['name']
|
||||
del inputdata['name']
|
||||
except (KeyError, ValueError):
|
||||
raise exc.InvalidArgumentException()
|
||||
configmanager.create_usergroup(groupname)
|
||||
|
||||
|
||||
def update_usergroup(groupname, attribmap, configmanager):
|
||||
try:
|
||||
configmanager.set_usergroup(name, attribmap)
|
||||
except ValueError:
|
||||
raise exc.InvalidArgumentException()
|
||||
|
||||
def update_user(name, attribmap, configmanager):
|
||||
try:
|
||||
configmanager.set_user(name, attribmap)
|
||||
@ -403,6 +418,9 @@ def update_user(name, attribmap, configmanager):
|
||||
raise exc.InvalidArgumentException()
|
||||
|
||||
|
||||
def show_usergroup(groupname, configmanager):
|
||||
return []
|
||||
|
||||
def show_user(name, configmanager):
|
||||
userobj = configmanager.get_user(name)
|
||||
rv = {}
|
||||
@ -451,6 +469,10 @@ def delete_user(user, configmanager):
|
||||
configmanager.del_user(user)
|
||||
yield msg.DeletedResource(user)
|
||||
|
||||
def delete_usergroup(usergroup, configmanager):
|
||||
configmanager.del_usergroup(usergroup)
|
||||
yield msg.DeletedResource(usergroup)
|
||||
|
||||
|
||||
def delete_nodegroup_collection(collectionpath, configmanager):
|
||||
if len(collectionpath) == 2: # just the nodegroup
|
||||
@ -1005,6 +1027,31 @@ def handle_path(path, operation, configmanager, inputdata=None, autostrip=True):
|
||||
configmanager, inputdata, operation, pathcomponents)
|
||||
elif pathcomponents[0] == 'version':
|
||||
return (msg.Attributes(kv={'version': confluent.__version__}),)
|
||||
elif pathcomponents[0] == 'usergroups':
|
||||
# TODO: when non-administrator accounts exist,
|
||||
# they must only be allowed to see their own user
|
||||
try:
|
||||
usergroup = pathcomponents[1]
|
||||
except IndexError: # it's just users/
|
||||
if operation == 'create':
|
||||
inputdata = msg.get_input_message(
|
||||
pathcomponents, operation, inputdata,
|
||||
configmanager=configmanager)
|
||||
create_usergroup(inputdata.attribs, configmanager)
|
||||
return iterate_collections(configmanager.list_usergroups(),
|
||||
forcecollection=False)
|
||||
if usergroup not in configmanager.list_usergroups():
|
||||
raise exc.NotFoundException("Invalid usergroup %s" % usergroup)
|
||||
if operation == 'retrieve':
|
||||
return show_usergroup(usergroup, configmanager)
|
||||
elif operation == 'delete':
|
||||
return delete_usergroup(usergroup, configmanager)
|
||||
elif operation == 'update':
|
||||
inputdata = msg.get_input_message(
|
||||
pathcomponents, operation, inputdata,
|
||||
configmanager=configmanager)
|
||||
update_usergroup(usergroup, inputdata.attribs, configmanager)
|
||||
return show_usergroup(usergroup, configmanager)
|
||||
elif pathcomponents[0] == 'users':
|
||||
# TODO: when non-administrator accounts exist,
|
||||
# they must only be allowed to see their own user
|
||||
|
@ -401,7 +401,7 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False,
|
||||
return InputExpression(path, inputdata, nodes)
|
||||
elif path == ['attributes', 'rename']:
|
||||
return InputConfigChangeSet(path, inputdata, nodes, configmanager)
|
||||
elif path[0] in ('attributes', 'users') and operation != 'retrieve':
|
||||
elif path[0] in ('attributes', 'users', 'usergroups') and operation != 'retrieve':
|
||||
return InputAttributes(path, inputdata, nodes)
|
||||
elif path == ['boot', 'nextdevice'] and operation != 'retrieve':
|
||||
return InputBootDevice(path, nodes, inputdata)
|
||||
|
Loading…
x
Reference in New Issue
Block a user