Skip to content
Snippets Groups Projects
Commit 4c613528 authored by sveseli's avatar sveseli
Browse files

adding ldap platform utility for group management

parent 378977fa
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env python
import ldap
import ldap.modlist
import copy
from dm.common.utility.loggingManager import LoggingManager
from dm.common.exceptions.configurationError import ConfigurationError
from dm.common.exceptions.internalError import InternalError
from dm.common.exceptions.authenticationError import AuthenticationError
from dm.common.exceptions.communicationError import CommunicationError
from dmSubprocess import DmSubprocess
class LdapLinuxPlatformUtility:
SUDO_CMD = '/usr/bin/sudo'
GROUPADD_CMD = '/usr/sbin/groupadd'
USERMOD_CMD = '/usr/sbin/usermod'
SETFACL_CMD = '/usr/bin/setfacl'
CHOWN_CMD = '/bin/chown'
def __init__(self, serverUrl, adminDn, adminPasswordFile, groupDnFormat, minGidNumber=None):
self.serverUrl = serverUrl
self.adminDn = adminDn
self.groupDnFormat = groupDnFormat
self.minGidNumber = minGidNumber
self.getLogger().debug('Min GID number: %s' % minGidNumber)
# Remove first entry from the dn format to get tree base
self.groupBaseDn = ','.join(groupDnFormat.split(',')[1:])
self.getLogger().debug('Group base DN: %s' % self.groupBaseDn)
self.getLogger().debug('Using LDAP Admin password file: %s' % adminPasswordFile)
self.adminPassword = open(adminPasswordFile, 'r').readline().strip()
if not self.adminPassword:
raise ConfigurationError('LDAP password could not be found in %s file' % adminPasswordFile)
self.ldapClient = None
@classmethod
def getLogger(cls):
logger = LoggingManager.getInstance().getLogger(cls.__name__)
return logger
@classmethod
def executeSudoCommand(cls, cmd):
p = DmSubprocess('%s %s' % (cls.SUDO_CMD, cmd))
p.run()
def getLdapClient(self):
if self.ldapClient is not None:
try:
self.ldapClient.simple_bind_s(self.adminDn, self.adminPassword)
except Exception, ex:
self.getLogger().error('Invalidating LDAP client due to error: %s' % ex)
self.unbind(self.ldapClient)
self.ldapClient = None
if not self.ldapClient:
self.ldapClient = self.bind(self.serverUrl, self.adminDn, self.adminPassword)
return self.ldapClient
@classmethod
def bind(cls, serverUrl, adminDn, adminPassword):
try:
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
ldapClient = ldap.initialize(serverUrl)
ldapClient.set_option(ldap.OPT_REFERRALS,0)
ldapClient.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)
ldapClient.simple_bind_s(adminDn, adminPassword)
cls.getLogger().debug('Successful binding with LDAP DN: %s' % adminDn)
return ldapClient
except ldap.INVALID_CREDENTIALS, ex:
ldapClient.unbind()
raise AuthenticationError('Invalid LDAP credentials for admin user %s' % adminDn)
except ldap.SERVER_DOWN, ex:
raise CommunicationError('Cannot reach LDAP server %s' % serverUrl)
except Exception, ex:
raise InternalError('Unrecognized exception while binding to LDAP server %s: %s' % (serverUrl, ex))
@classmethod
def unbind(cls, ldapClient):
try:
ldapClient.unbind()
except Exception, ex:
cls.getLogger().error('Could not unbind LDAP client: %s' % ex)
def createGroup(self, name):
""" Create group if it does not exist. """
logger = self.getLogger()
ldapClient = self.getLdapClient()
try:
groupDn = self.groupDnFormat % name
logger.debug('Looking for group DN: %s' % groupDn)
# this method will throw exception if group is not found
resultList = ldapClient.search_s(groupDn, ldap.SCOPE_BASE)
groupTuple = resultList[0]
logger.debug('Group %s already exists' % groupTuple[0])
return
except ldap.NO_SUCH_OBJECT, ex:
logger.debug('Group DN %s must be created' % groupDn)
except Exception, ex:
raise InternalError(exception=ex)
# determine gidNumber: look through all entries to get max value,
# then increment it
# ldap should really be configured to handle gid's automatically,
# and should prevent invalid entries
try:
logger.debug('Looking for max group id')
resultList = ldapClient.search_s(self.groupBaseDn, ldap.SCOPE_ONELEVEL, attrlist=['gidNumber'])
maxGid = 0
if self.minGidNumber:
maxGid = self.minGidNumber
for result in resultList:
gidList = result[1].get('gidNumber', [])
gid = 0
if gidList:
gid = int(gidList[0])
if gid > maxGid:
maxGid = gid
gidNumber = str(maxGid + 1)
logger.debug('Max GID is %s, new group id will be %s' % (maxGid, gidNumber))
except Exception, ex:
raise InternalError(exception=ex)
attrs = {}
attrs['objectclass'] = ['posixGroup','top']
attrs['cn'] = name
attrs['gidNumber'] = [gidNumber]
attrs['memberUid'] = []
try:
groupLdif = ldap.modlist.addModlist(attrs)
ldapClient.add_s(groupDn, groupLdif)
except Exception, ex:
logger.error('Could not add group %s: %s' % (groupDn, ex))
raise InternalError(exception=ex)
def addUserToGroup(self, username, groupName):
""" Add user to group. """
logger = self.getLogger()
ldapClient = self.getLdapClient()
try:
groupDn = self.groupDnFormat % groupName
resultList = ldapClient.search_s(groupDn, ldap.SCOPE_BASE)
groupTuple = resultList[0]
groupAttrs = groupTuple[1]
memberUidList = groupAttrs.get('memberUid', [])
if username in memberUidList:
logger.debug('Group %s already contains user %s' % (groupName, username))
return
except Exception, ex:
raise InternalError(exception=ex)
logger.debug('Adding user %s to group %s' % (username, groupName))
memberUidList2 = copy.copy(memberUidList)
memberUidList2.append(username)
groupAttrs2 = copy.copy(groupAttrs)
groupAttrs2['memberUid'] = memberUidList2
try:
groupLdif = ldap.modlist.modifyModlist(groupAttrs, groupAttrs2)
ldapClient.modify_s(groupDn, groupLdif)
except Exception, ex:
logger.error('Could not add user %s to group %s: %s' % (username, groupName, ex))
raise InternalError(exception=ex)
@classmethod
def setPathReadExecutePermissionsForGroup(cls, path, groupName):
""" Set path permissions for the given group. """
logger = cls.getLogger()
logger.debug('Allowing group %s to read/execute path %s' % (groupName, path))
cmd = '%s -m group\:%s\:rx %s' % (cls.SETFACL_CMD, groupName, path)
cls.executeSudoCommand(cmd)
@classmethod
def changePathGroupOwner(cls, path, groupName):
logger = cls.getLogger()
logger.debug('Changing group owner to %s for path %s' % (groupName, path))
cmd = '%s -R \:%s %s' % (cls.CHOWN_CMD, groupName, path)
cls.executeSudoCommand(cmd)
#######################################################################
# Testing.
if __name__ == '__main__':
utility = LdapLinuxPlatformUtility('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000)
utility.createGroup('exp2')
#utility.createGroup('dmgp000001_TOF')
utility.addUserToGroup('rs1', 'exp2')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment