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

changes for ldap update functionality; added new command line tools for user account sync

parent 6b7c3818
No related branches found
No related tags found
No related merge requests found
#!/bin/sh
# Run command
if [ -z $DM_ROOT_DIR ]; then
cd `dirname $0` && myDir=`pwd`
setupFile=$myDir/../setup.sh
if [ ! -f $setupFile ]; then
echo "Cannot find setup file: $setupFile"
exit 1
fi
source $setupFile > /dev/null
fi
source dm_command_setup.sh
eval "$DM_ROOT_DIR/src/python/dm/aps_user_db/cli/updateUserFromApsDbCli.py $DM_COMMAND_ARGS"
#!/bin/sh
# Run command
if [ -z $DM_ROOT_DIR ]; then
cd `dirname $0` && myDir=`pwd`
setupFile=$myDir/../setup.sh
if [ ! -f $setupFile ]; then
echo "Cannot find setup file: $setupFile"
exit 1
fi
source $setupFile > /dev/null
fi
source dm_command_setup.sh
eval "$DM_ROOT_DIR/src/python/dm/aps_user_db/cli/updateUsersFromApsDbCli.py $DM_COMMAND_ARGS"
#!/usr/bin/env python #!/usr/bin/env python
import os
from dm.common.exceptions.invalidRequest import InvalidRequest from dm.common.exceptions.invalidRequest import InvalidRequest
from dm.common.exceptions.objectNotFound import ObjectNotFound
from dm.common.exceptions.invalidArgument import InvalidArgument
from dm.common.cli.dmCli import DmCli from dm.common.cli.dmCli import DmCli
from dm.common.utility.ldapUserManager import LdapUserManager from dm.common.utility.ldapUserManager import LdapUserManager
from dm.common.utility.configurationManager import ConfigurationManager
from dm.aps_user_db.api.apsUserDbApi import ApsUserDbApi from dm.aps_user_db.api.apsUserDbApi import ApsUserDbApi
class UpdateUserFromApsDbCli(DmCli): class UpdateUserFromApsDbCli(DmCli):
def __init__(self): def __init__(self):
DmCli.__init__(self) DmCli.__init__(self)
self.addOption('', '--badge', dest='badge', help='User badge number.') self.addOption('', '--badge', dest='badge', help='User badge number.')
self.addOption('', '--config-file', dest='configFile', help='Utility configuration file.')
def checkArgs(self): def checkArgs(self):
if self.options.badge is None: if self.options.badge is None:
raise InvalidRequest('Badge number must be provided.') raise InvalidRequest('Badge number must be provided.')
configFile = self.options.configFile
if configFile is None:
raise InvalidRequest('Config file must be provided.')
if not os.path.exists(configFile):
raise InvalidArgument('Invalid config file: %s.', configFile)
def getBadge(self): def getBadge(self):
return self.options.badge return self.options.badge
def runCommand(self): def runCommand(self):
self.parseArgs(usage=""" self.parseArgs(usage="""
dm-update-user-from-aps-db --badge=BADGE dm-update-user-from-aps-db --badge=BADGE --config-file=CONFIGFILE
Description: Description:
Updates user in DM LDAP and database using information from APS DB. Updates user in DM LDAP and database using information from APS DB.
""") """)
ConfigurationManager.getInstance().setConfigFile(self.options.configFile)
self.checkArgs() self.checkArgs()
apsUserDbApi = ApsUserDbApi() apsUserDbApi = ApsUserDbApi()
badgeNumber = self.getBadge() badge = self.getBadge()
username = 'd%s' % badgeNumber username = 'd%s' % badge
apsUser = apsUserDbApi.getApsUserByBadgeNumber(badgeNumber) apsUser = apsUserDbApi.getApsUserByBadgeNumber(badge)
print 'APS User Info: ', apsUser.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) #print 'APS User Info: ', apsUser.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
ldapUserManager = LdapUserManager('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', userDnFormat='uid=%s,ou=DM,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000) print 'APS User Info: ', apsUser
ldapUser = ldapUserManager.getUserInfo(username) print
print 'Old LDAP User Info: ', ldapUser ldapUserManager = LdapUserManager.createInstance()
attrDict = {} try:
attrDict['gecos'] = apsUser['name'] self.logger.debug('Modifying LDAP user with badge %s: %s' % (badge, apsUser['name']))
attrDict['userPassword'] = apsUser['passwordHashValue'] ldapUser = ldapUserManager.getUserInfo(username)
ldapUserManager.modifyUserInfo(username, attrDict) print 'LDAP User Info (before update): ', ldapUser
ldapUser = ldapUserManager.getUserInfo(username) print 'LDAP User Password Hash (before update): ', ldapUserManager.decodePasswordHash(ldapUser.getUserPassword())
print 'New LDAP User Info: ', ldapUser print
ldapUserManager.modifyUserInfo(username, apsUser)
ldapUser = ldapUserManager.getUserInfo(username)
except ObjectNotFound, ex:
self.logger.debug('User with badge %s does not exist, creating it' % (badge))
ldapUser = ldapUserManager.createUserInfo(username, apsUser)
print 'LDAP User Info (after update): ', ldapUser
print 'LDAP User Password Hash (after update): ', ldapUserManager.decodePasswordHash(ldapUser.getUserPassword())
####################################################################### #######################################################################
# Run command. # Run command.
......
#!/usr/bin/env python #!/usr/bin/env python
import datetime import datetime
import os
from dm.common.exceptions.invalidRequest import InvalidRequest from dm.common.exceptions.invalidRequest import InvalidRequest
from dm.common.exceptions.invalidArgument import InvalidArgument
from dm.common.exceptions.objectAlreadyExists import ObjectAlreadyExists
from dm.common.cli.dmCli import DmCli from dm.common.cli.dmCli import DmCli
from dm.common.db.api.userDbApi import UserDbApi
from dm.common.utility.configurationManager import ConfigurationManager from dm.common.utility.configurationManager import ConfigurationManager
from dm.common.utility.ldapUserManager import LdapUserManager from dm.common.utility.ldapUserManager import LdapUserManager
from dm.aps_user_db.api.apsUserDbApi import ApsUserDbApi from dm.aps_user_db.api.apsUserDbApi import ApsUserDbApi
...@@ -11,39 +15,83 @@ from dm.ds_web_service.api.dsRestApiFactory import DsRestApiFactory ...@@ -11,39 +15,83 @@ from dm.ds_web_service.api.dsRestApiFactory import DsRestApiFactory
class UpdateUsersFromApsDbCli(DmCli): class UpdateUsersFromApsDbCli(DmCli):
def __init__(self): def __init__(self):
DmCli.__init__(self) DmCli.__init__(self)
self.addOption('', '--config-file', dest='configFile', help='Utility configuration file.')
self.addOption('', '--without-dm-db', dest='withoutDmDb', action='store_true', default=False, help='Do not use DM DB for synchronizing user information.')
self.addOption('', '--use-dm-rest-api', dest='useDmRestApi', action='store_true', default=False, help='Use DM REST API for accessing user information. This option does not have any effect if --without-dm-db is set.')
def checkArgs(self):
configFile = self.options.configFile
if configFile is None:
raise InvalidRequest('Config file must be provided.')
if not os.path.exists(configFile):
raise InvalidArgument('Invalid config file: %s.', configFile)
def runCommand(self): def runCommand(self):
self.parseArgs(usage=""" self.parseArgs(usage="""
dm-update-users-from-aps-db dm-update-users-from-aps-db --config-file=CONFIGFILE
[--without-dm-db]
[--use-dm-rest-api]
Description: Description:
Updates all users in DM LDAP and database using information from APS DB. Updates all users in DM LDAP and database using information from APS DB. This command by default uses DM DB to determine whether or not user needs to be created or updated. If the --without-dm-db flag is set, DM DB will not be used nor it will be updated.
""") """)
ConfigurationManager.getInstance().setConfigFile('/home/oxygen/SVESELI/Work/DM/etc/dm.conf') self.checkArgs()
ConfigurationManager.getInstance().setConfigFile(self.options.configFile)
self.logger.debug('Starting sync process') self.logger.debug('Starting sync process')
apsUserDbApi = ApsUserDbApi() apsUserDbApi = ApsUserDbApi()
userRestApi = DsRestApiFactory.getUserRestApi() ldapUserManager = LdapUserManager.createInstance()
# Get DM user API
dmUserApi = None
if not self.options.withoutDmDb:
try:
if self.options.useDmRestApi:
self.logger.debug('Using DM REST API')
dmUserApi = DsRestApiFactory.getUserRestApi()
else:
self.logger.debug('Using DM DB API')
dmUserApi = UserDbApi()
except Exception, ex:
self.logger.error('Cannot use DM DB: %s' % ex)
self.logger.debug('Retrieving APS users') self.logger.debug('Retrieving APS users')
apsUsers = apsUserDbApi.getApsUsers() apsUsers = apsUserDbApi.getApsUsers()
self.logger.debug('Number of APS Users: %s' % len(apsUsers)) self.logger.debug('Number of APS Users: %s' % len(apsUsers))
self.logger.debug('Retrieving DM users')
dmUsers = userRestApi.getUsers() # Retrieve DM users from DB if we got DM user API
self.logger.debug('Number of DM Users: %s' % len(dmUsers)) dmUserMap = {}
dmUserBadgeMap = {} if dmUserApi:
for dmUser in dmUsers: self.logger.debug('Retrieving DM users from DB')
badge = dmUser.get('badge') try:
if badge: nDmUsersWithBadge = 0
dmUserBadgeMap[badge] = dmUser dmUsers = dmUserApi.getUsers()
self.logger.debug('Number of DM Users with badge: %s' % len(dmUserBadgeMap)) self.logger.debug('Number of DM Users: %s' % len(dmUsers))
for dmUser in dmUsers:
username = dmUser.get('username')
if dmUser.get('badge'):
nDmUsersWithBadge += 1
dmUserMap[username] = dmUser
self.logger.debug('Number of DM Users with badge: %s' % nDmUsersWithBadge)
except Exception, ex:
self.logger.error('Error retrieving users from DM DB: %s' % ex)
dmUserApi = None
# We cannot use DM user API, retrieve users from LDAP
if not dmUserApi:
self.logger.debug('Retrieving DM users using LDAP client')
dmUserMap = ldapUserManager.getUserInfoMapByUid()
self.logger.debug('Number of DM LDAP Users: %s' % len(dmUserMap))
nCreatedUsers = 0 nCreatedUsers = 0
nUpdatedUsers = 0 nUpdatedUsers = 0
nErrors = 0
for apsUser in apsUsers: for apsUser in apsUsers:
apsLastChangeDate = apsUser.get('lastChangeDate') apsLastChangeDate = apsUser.get('lastChangeDate')
# DM DB attributes
badge = apsUser['badgeNumber'] badge = apsUser['badgeNumber']
username = 'd%s' % badge username = 'd%s' % badge
firstName = apsUser.get('firstName') firstName = apsUser.get('firstName')
middleName = apsUser.get('middleName') middleName = apsUser.get('middleName')
lastName = apsUser.get('lastName') lastName = apsUser.get('lastName')
...@@ -54,43 +102,98 @@ Description: ...@@ -54,43 +102,98 @@ Description:
description = None description = None
password = None password = None
dmUser = dmUserBadgeMap.get(badge) # LDAP attributes
ldapModAttrDict = {}
ldapModAttrDict['gecos'] = apsUser['name']
ldapModAttrDict['userPassword'] = apsUser['passwordHashValue']
dmUser = dmUserMap.get(username)
if not dmUser: if not dmUser:
self.logger.debug('Creating user with badge %s: %s' % (badge, apsUser['name'])) # We must create user in LDAP/DM DB
try:
try:
self.logger.debug('Creating LDAP user with badge %s: %s' % (badge, apsUser['name']))
ldapUser = ldapUserManager.createUserInfo(username, apsUser)
except ObjectAlreadyExists, ex:
# LDAP user already exists, simply update it.
self.logger.debug('LDAP user with badge %s already exists, attempting to modify it' % (badge))
ldapUserManager.modifyUserInfo(username, ldapModAttrDict)
except Exception, ex:
self.logger.error('LDAP problem caught while creating user with badge %s: %s' % (badge, str(ex)))
nErrors += 1
continue
userRestApi.addUser(username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate) if dmUserApi:
nCreatedUsers += 1 try:
self.logger.debug('Creating DM DB user with badge %s: %s' % (badge, apsUser['name']))
dmUserApi.addUser(username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
nCreatedUsers += 1
except Exception, ex:
self.logger.error('DM DB problem caught while creating user with badge %s: %s' % (badge, str(ex)))
nErrors += 1
continue
else: else:
dmLastUpdate = dmUser.get('lastUpdate') # User already exists, simply update it.
if dmLastUpdate:
# need to convert DM last update time to datetime object if dmUserApi:
# datetime cannot handle time zone at the moment # We have DM DB API
timeZonePos = dmLastUpdate.rfind('-') dmLastUpdate = str(dmUser.get('lastUpdate'))
dmLastUpdate = dmLastUpdate[0:timeZonePos] if dmLastUpdate:
dmLastUpdate = datetime.datetime.strptime(dmLastUpdate, '%Y-%m-%d %H:%M:%S') # need to convert DM last update time to datetime object
if not dmLastUpdate or dmLastUpdate < apsLastChangeDate: # datetime cannot handle time zone at the moment
id = dmUser.get('id') timeZonePos = dmLastUpdate.rfind('-')
self.logger.debug('Modifying user with badge %s: %s (DM id: %s)' % (badge, apsUser['name'], id)) dmLastUpdate = dmLastUpdate[0:timeZonePos]
print apsUser dmLastUpdate = datetime.datetime.strptime(dmLastUpdate, '%Y-%m-%d %H:%M:%S')
userRestApi.updateUser(id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate) if not dmLastUpdate or dmLastUpdate < apsLastChangeDate:
nUpdatedUsers += 1 # User needs update
try:
self.logger.debug('Modifying LDAP user with badge %s, username %s' % (badge, username))
ldapUserManager.modifyUserInfo(username, ldapModAttrDict)
except Exception, ex:
self.logger.error('LDAP problem caught while modifying user with badge %s: %s' % (badge, str(ex)))
nErrors += 1
continue
try:
id = dmUser.get('id')
self.logger.debug('Modifying DM DB user with badge %s: %s (DM id: %s)' % (badge, apsUser['name'], id))
dmUserApi.updateUser(id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
nUpdatedUsers += 1
except Exception, ex:
self.logger.error('DM DB problem caught while modifying user with badge %s: %s' % (badge, str(ex)))
nErrors += 1
continue
else:
# User is up to date
continue
else: else:
# User is up to date # No DM DB API
pass apsPasswordHash = apsUser['passwordHashValue']
dmPasswordHash = ldapUserManager.decodePasswordHash(dmUser['userAttrs']['userPassword'][0])
if apsPasswordHash != dmPasswordHash:
# User needs update
try:
self.logger.debug('Modifying LDAP user with badge %s, username %s' % (badge, username))
self.logger.debug('APS password hash: %s, DM password hash: %s' % (apsPasswordHash, dmPasswordHash))
self.logger.debug('Encoded DM password hash: %s' % (dmUser['userAttrs']['userPassword'][0]))
ldapUserManager.modifyUserInfo(username, ldapModAttrDict)
nUpdatedUsers += 1
except Exception, ex:
self.logger.error('LDAP problem caught while modifying user with badge %s: %s' % (badge, str(ex)))
nErrors += 1
continue
else:
# User is up to date
continue
self.logger.debug('Number of new DM users: %s' % (nCreatedUsers)) self.logger.debug('Number of new DM users: %s' % (nCreatedUsers))
self.logger.debug('Number of updated DM users: %s' % (nUpdatedUsers)) self.logger.debug('Number of updated DM users: %s' % (nUpdatedUsers))
self.logger.debug('Number of update errors: %s' % (nErrors))
self.logger.debug('Completed sync process') self.logger.debug('Completed sync process')
#ldapUserManager = LdapUserManager('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', userDnFormat='uid=%s,ou=DM,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000) print('Number of new DM users: %s' % (nCreatedUsers))
#ldapUser = ldapUserManager.getUserInfo(username) print('Number of updated DM users: %s' % (nUpdatedUsers))
#print 'Old LDAP User Info: ', ldapUser print('Number of update errors: %s' % (nErrors))
#attrDict = {}
#attrDict['gecos'] = apsUser['name']
#attrDict['userPassword'] = apsUser['passwordHashValue']
#ldapUserManager.modifyUserInfo(username, attrDict)
#ldapUser = ldapUserManager.getUserInfo(username)
#print 'New LDAP User Info: ', ldapUser
####################################################################### #######################################################################
# Run command. # Run command.
......
...@@ -24,7 +24,13 @@ class ApsUserDbManager: ...@@ -24,7 +24,13 @@ class ApsUserDbManager:
DB_CONNECTION_LOGGING_FLAG = False DB_CONNECTION_LOGGING_FLAG = False
CONFIG_SECTION_NAME = 'ApsUserDbManager' CONFIG_SECTION_NAME = 'ApsUserDbManager'
CONFIG_OPTION_NAME_LIST = [ 'dbHost', 'dbPort', 'dbUser', 'dbPasswordFile', 'dbName', 'dbSchema' ] DB_KEY = 'db'
DB_USER_KEY = 'dbuser'
DB_HOST_KEY = 'dbhost'
DB_PORT_KEY = 'dbport'
DB_NAME_KEY = 'dbname'
DB_SCHEMA_KEY = 'dbschema'
DB_PASSWORD_FILE_KEY = 'dbpasswordfile'
# Singleton. # Singleton.
__lock = threading.RLock() __lock = threading.RLock()
...@@ -39,6 +45,25 @@ class ApsUserDbManager: ...@@ -39,6 +45,25 @@ class ApsUserDbManager:
mgr = ex mgr = ex
return mgr return mgr
def __configure(self):
cm = ConfigurationManager.getInstance()
self.logger.debug('Configuring APS User DB Manager')
self.db = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_KEY)
self.logger.debug('Using APS DB: %s' % self.db)
self.dbUser = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_USER_KEY)
self.logger.debug('Using APS DB user: %s' % self.dbUser)
self.dbHost = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_HOST_KEY)
self.logger.debug('Using APS DB host: %s' % self.dbHost)
self.dbPort = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_PORT_KEY)
self.logger.debug('Using APS DB port: %s' % self.dbPort)
self.dbName = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_NAME_KEY)
self.logger.debug('Using APS DB name: %s' % self.dbName)
self.dbSchema = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_SCHEMA_KEY)
self.logger.debug('Using APS DB schema: %s' % self.dbSchema)
self.dbPasswordFile = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_PASSWORD_FILE_KEY)
self.logger.debug('Using APS DB password file: %s' % self.dbPasswordFile)
self.dbPassword = open(self.dbPasswordFile, 'r').readline().strip()
def __init__(self): def __init__(self):
ApsUserDbManager.__lock.acquire() ApsUserDbManager.__lock.acquire()
try: try:
...@@ -47,34 +72,17 @@ class ApsUserDbManager: ...@@ -47,34 +72,17 @@ class ApsUserDbManager:
ApsUserDbManager.__instance = self ApsUserDbManager.__instance = self
self.lock = threading.RLock() self.lock = threading.RLock()
self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__) self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__)
cm = ConfigurationManager.getInstance() self.__configure()
#cm.setOptionsFromConfigFile(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.CONFIG_OPTION_NAME_LIST)
engineUrl = '%s://%s:%s@%s:%s/%s' % (self.db, self.dbUser, self.dbPassword, self.dbHost, self.dbPort, self.dbName)
#dbUser = cm.getDbUser() #self.logger.debug('Using engine URL: %s' % engineUrl)
#self.logger.debug('Using DB user: %s' % dbUser)
#dbSchema = cm.getDbSchema()
#dbPasswordFile = cm.getDbPasswordFile()
#self.logger.debug('Using DB password file: %s' % dbPasswordFile)
#dbPassword = open(dbPasswordFile, 'r').readline().strip()
#dbPort = cm.getDbPort()
#dbHost = cm.getDbHost()
#db = cm.getDb()
db = "oracle"
dbPort = 1527
dbHost = "ra.aps.anl.gov"
dbName = "aps1"
dbSchema = "DCC"
dbUser = "glob_conn"
dbPassword = "ur2ytkownicy2u"
engineUrl = '%s://%s:%s@%s:%s/%s' % (db, dbUser, dbPassword, dbHost, dbPort, dbName)
self.logger.debug('Using engine URL: %s' % engineUrl)
self.engine = sqlalchemy.create_engine(engineUrl, self.engine = sqlalchemy.create_engine(engineUrl,
pool_size=ApsUserDbManager.DB_CONNECTION_POOL_SIZE, pool_size=ApsUserDbManager.DB_CONNECTION_POOL_SIZE,
max_overflow=ApsUserDbManager.DB_CONNECTION_POOL_MAX_OVERFLOW, max_overflow=ApsUserDbManager.DB_CONNECTION_POOL_MAX_OVERFLOW,
pool_recycle=ApsUserDbManager.DB_CONNECTION_POOL_RECYCYLE_TIME, pool_recycle=ApsUserDbManager.DB_CONNECTION_POOL_RECYCYLE_TIME,
echo=ApsUserDbManager.DB_CONNECTION_LOGGING_FLAG, echo=ApsUserDbManager.DB_CONNECTION_LOGGING_FLAG,
pool_timeout=ApsUserDbManager.DB_CONNECTION_POOL_TIMEOUT) pool_timeout=ApsUserDbManager.DB_CONNECTION_POOL_TIMEOUT)
self.metadata = sqlalchemy.MetaData(engineUrl, schema=dbSchema) self.metadata = sqlalchemy.MetaData(engineUrl, schema=self.dbSchema)
self.logger.debug('Mapping DB tables') self.logger.debug('Mapping DB tables')
for (dbTableName, (dbEntityClass, dbRelationDict)) in apsUserDbEntityMap.APS_USER_DB_ENTITY_MAP.items(): for (dbTableName, (dbEntityClass, dbRelationDict)) in apsUserDbEntityMap.APS_USER_DB_ENTITY_MAP.items():
......
...@@ -4,7 +4,7 @@ from dmObject import DmObject ...@@ -4,7 +4,7 @@ from dmObject import DmObject
class ApsUserInfo(DmObject): class ApsUserInfo(DmObject):
DEFAULT_KEY_LIST = [ 'id', 'badgeNumber', 'firstName', 'middleName', 'lastName', 'email' ] DEFAULT_KEY_LIST = [ 'id', 'badgeNumber', 'firstName', 'middleName', 'lastName', 'email', 'passwordHashValue' ]
def __init__(self, dict): def __init__(self, dict):
DmObject.__init__(self, dict) DmObject.__init__(self, dict)
......
...@@ -9,3 +9,5 @@ class LdapUserInfo(DmObject): ...@@ -9,3 +9,5 @@ class LdapUserInfo(DmObject):
def __init__(self, dict): def __init__(self, dict):
DmObject.__init__(self, dict) DmObject.__init__(self, dict)
def getUserPassword(self):
return self['userAttrs']['userPassword'][0]
...@@ -25,6 +25,14 @@ from ldapClient import LdapClient ...@@ -25,6 +25,14 @@ from ldapClient import LdapClient
class LdapUserManager(LdapClient): class LdapUserManager(LdapClient):
CONFIG_SECTION_NAME = 'LdapUserManager'
SERVER_URL_KEY = 'serverurl'
ADMIN_DN_KEY = 'admindn'
ADMIN_PASSWORD_FILE_KEY = 'adminpasswordfile'
USER_DN_FORMAT_KEY = 'userdnformat'
GROUP_DN_FORMAT_KEY = 'groupdnformat'
MIN_GID_NUMBER_KEY = 'mingidnumber'
def __init__(self, serverUrl, adminDn, adminPasswordFile, userDnFormat, groupDnFormat, minGidNumber=None): def __init__(self, serverUrl, adminDn, adminPasswordFile, userDnFormat, groupDnFormat, minGidNumber=None):
LdapClient.__init__(self, serverUrl, adminDn, adminPasswordFile) LdapClient.__init__(self, serverUrl, adminDn, adminPasswordFile)
self.userDnFormat = userDnFormat self.userDnFormat = userDnFormat
...@@ -35,9 +43,29 @@ class LdapUserManager(LdapClient): ...@@ -35,9 +43,29 @@ class LdapUserManager(LdapClient):
self.groupBaseDn = ','.join(groupDnFormat.split(',')[1:]) self.groupBaseDn = ','.join(groupDnFormat.split(',')[1:])
self.getLogger().debug('Group base DN: %s' % self.groupBaseDn) self.getLogger().debug('Group base DN: %s' % self.groupBaseDn)
@classmethod
def createInstance(cls):
cm = ConfigurationManager.getInstance()
logger = cls.getLogger()
logger.debug('Creating LDAP User Manager instance')
serverUrl = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.SERVER_URL_KEY)
logger.debug('Using server URL: %s' % serverUrl)
adminDn = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.ADMIN_DN_KEY)
logger.debug('Using admin DN: %s' % adminDn)
adminPasswordFile = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.ADMIN_PASSWORD_FILE_KEY)
logger.debug('Using admin password file: %s' % adminPasswordFile)
userDnFormat = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.USER_DN_FORMAT_KEY)
logger.debug('Using user DN format: %s' % userDnFormat)
groupDnFormat = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.GROUP_DN_FORMAT_KEY)
logger.debug('Using group DN format: %s' % groupDnFormat)
minGidNumber = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.MIN_GID_NUMBER_KEY)
logger.debug('Using min GID number: %s' % minGidNumber)
return LdapUserManager(serverUrl, adminDn, adminPasswordFile, userDnFormat, groupDnFormat, minGidNumber)
@classmethod @classmethod
def decodePasswordHash(cls, b64EncodedString): def decodePasswordHash(cls, b64EncodedString):
decodedString = b64EncodedString.replace('{SHA}','') beginEncoding = b64EncodedString.find('}')
decodedString = b64EncodedString[beginEncoding+1:]
decodedString = b16encode(b64decode(decodedString)).upper() decodedString = b16encode(b64decode(decodedString)).upper()
return decodedString return decodedString
...@@ -51,10 +79,41 @@ class LdapUserManager(LdapClient): ...@@ -51,10 +79,41 @@ class LdapUserManager(LdapClient):
""" Get user info. """ """ Get user info. """
userDn = self.userDnFormat % str(username) userDn = self.userDnFormat % str(username)
ldapClient = self.getLdapClient() ldapClient = self.getLdapClient()
resultList = ldapClient.search_s(userDn, ldap.SCOPE_BASE) resultList = ldapClient.search_s(userDn, ldap.SCOPE_BASE, attrlist=['*','createTimeStamp','modifyTimestamp'])
userTuple = resultList[0] userTuple = resultList[0]
return LdapUserInfo({'userDn' : userTuple[0], 'userAttrs' : userTuple[1]}) return LdapUserInfo({'userDn' : userTuple[0], 'userAttrs' : userTuple[1]})
@LdapClient.executeLdapCall
def getUserInfos(self):
""" Get user infos. """
baseDnPos = self.userDnFormat.find(',')
baseDn = self.userDnFormat[baseDnPos+1:]
searchFilter = self.userDnFormat[0:baseDnPos] % '*'
ldapClient = self.getLdapClient()
resultList = ldapClient.search_s(baseDn, ldap.SCOPE_SUBTREE, searchFilter, attrlist=['*','createTimeStamp','modifyTimestamp'])
userList = []
for result in resultList:
userDn = result[0]
userAttrs = result[1]
userList.append(LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs}))
return userList
@LdapClient.executeLdapCall
def getUserInfoMapByUid(self):
""" Get user infos. """
baseDnPos = self.userDnFormat.find(',')
baseDn = self.userDnFormat[baseDnPos+1:]
searchFilter = self.userDnFormat[0:baseDnPos] % '*'
ldapClient = self.getLdapClient()
resultList = ldapClient.search_s(baseDn, ldap.SCOPE_SUBTREE, searchFilter)
userMap = {}
for result in resultList:
userDn = result[0]
userAttrs = result[1]
uid = userAttrs['uid'][0]
userMap[uid] = LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs})
return userMap
@LdapClient.executeLdapCall @LdapClient.executeLdapCall
def modifyUserInfo(self, username, attrDict): def modifyUserInfo(self, username, attrDict):
""" Modify user. """ """ Modify user. """
...@@ -64,21 +123,36 @@ class LdapUserManager(LdapClient): ...@@ -64,21 +123,36 @@ class LdapUserManager(LdapClient):
userDn = ldapUserInfo.get('userDn') userDn = ldapUserInfo.get('userDn')
userAttrs = ldapUserInfo.get('userAttrs') userAttrs = ldapUserInfo.get('userAttrs')
userAttrs2 = copy.copy(userAttrs) userAttrs2 = copy.copy(userAttrs)
for name,value in attrDict.items():
ldapName = name middleName = attrDict.get('middleName', '')
ldapValue = value fullName = '%s, %s' % (attrDict.get('lastName', ''), attrDict.get('firstName', ''))
if name == 'passwordHashValue': if middleName:
ldapName = 'userPassword' fullName = '%s %s' % (fullName, middleName)
ldapValue = self.encodePasswordHash(value)
if not userAttrs2.has_key(ldapName): if attrDict.has_key('name'):
raise InvalidArgument('No such attribute: %s' % ldapName) userAttrs2['cn'] = [attrDict.get('name')]
userAttrs2['revcn'] = ['%s %s' % (attrDict.get('lastName'), attrDict.get('firstName'))]
if type(ldapValue) == types.ListType: userAttrs2['sn'] = [attrDict.get('lastName')]
userAttrs2[ldapName] = ldapValue userAttrs2['givenName'] = [attrDict.get('firstName')]
userAttrs2['gecos'] = [attrDict.get('name')]
for key in ['loginShell', 'allowed-host', 'homeDirectory', 'home7Directory', 'gidNumber' ]:
if attrDict.has_key(key):
userAttrs2[key] = [attrDict.get(key)]
if attrDict.has_key('grp'):
userAttrs2['o'] = [attrDict.get('grp')]
if attrDict.has_key('inactive'):
if attrDict.get('inactive', 'N') == 'Y':
userAttrs2['inetUserStatus'] = ['inactive']
else: else:
userAttrs2[ldapName] = [str(ldapValue)] userAttrs2['inetUserStatus'] = ['active']
passwordHash = attrDict.get('userPassword')
if not passwordHash:
passwordHash = attrDict.get('passwordHashValue')
if passwordHash:
userAttrs2['userPassword'] = [self.encodePasswordHash(passwordHash)]
logger.debug('Encoded password entry: %s' % passwordHash)
logger.debug('Modifying user %s with attrs %s' % (username, userAttrs2))
logger.debug('Modifying user %s attrs %s' % (username, userAttrs2))
userLdif = ldap.modlist.modifyModlist(userAttrs, userAttrs2) userLdif = ldap.modlist.modifyModlist(userAttrs, userAttrs2)
ldapClient.modify_s(userDn, userLdif) ldapClient.modify_s(userDn, userLdif)
return LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs2}) return LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs2})
...@@ -93,9 +167,9 @@ class LdapUserManager(LdapClient): ...@@ -93,9 +167,9 @@ class LdapUserManager(LdapClient):
raise ObjectAlreadyExists('User %s already exists.' % username) raise ObjectAlreadyExists('User %s already exists.' % username)
except ObjectNotFound, ex: except ObjectNotFound, ex:
pass pass
middleName = attrDict.get('middleName', '') middleName = attrDict.get('middleName')
fullName = '%s, %s' % (attrDict.get('lastName', ''), attrDict.get('firstName', '')) fullName = '%s, %s' % (attrDict.get('lastName', ''), attrDict.get('firstName', ''))
if len(middleName): if middleName:
fullName = '%s %s' % (fullName, middleName) fullName = '%s %s' % (fullName, middleName)
badgeNumber = attrDict.get('badgeNumber') badgeNumber = attrDict.get('badgeNumber')
uid = 'd%s' % badgeNumber uid = 'd%s' % badgeNumber
...@@ -113,7 +187,10 @@ class LdapUserManager(LdapClient): ...@@ -113,7 +187,10 @@ class LdapUserManager(LdapClient):
userAttrs['homeDirectory'] = ['/data'] userAttrs['homeDirectory'] = ['/data']
userAttrs['home7Directory'] = ['/data'] userAttrs['home7Directory'] = ['/data']
userAttrs['o'] = [attrDict.get('grp')] userAttrs['o'] = [attrDict.get('grp')]
userAttrs['inetUserStatus'] = ['active'] if attrDict.get('inactive', 'N') == 'Y':
userAttrs['inetUserStatus'] = ['inactive']
else:
userAttrs['inetUserStatus'] = ['active']
userAttrs['gidNumber'] = ['66001'] userAttrs['gidNumber'] = ['66001']
userAttrs['gecos'] = [attrDict.get('name', fullName)] userAttrs['gecos'] = [attrDict.get('name', fullName)]
userAttrs['sn'] = [attrDict.get('lastName', '')] userAttrs['sn'] = [attrDict.get('lastName', '')]
...@@ -285,22 +362,37 @@ class LdapUserManager(LdapClient): ...@@ -285,22 +362,37 @@ class LdapUserManager(LdapClient):
if __name__ == '__main__': if __name__ == '__main__':
utility = LdapUserManager('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', userDnFormat='uid=%s,ou=DM,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000) utility = LdapUserManager('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', userDnFormat='uid=%s,ou=DM,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000)
print utility.getGroupInfo(u's1id-test03') #print utility.getGroupInfo(u's1id-test03')
user = utility.getUserInfo(u'd225159') user = utility.getUserInfo(u'd225159')
print user print user
print user.getUserPassword()
print utility.decodePasswordHash(user.getUserPassword())
userMap = utility.getUserInfoMapByUid()
print 'N entries: ', len(userMap)
print userMap['d225159']
#for user in userList:
# print user
utility.modifyUserInfo(u'd225159', {'homeDirectory' : '/data/'}) utility.modifyUserInfo(u'd225159', {'homeDirectory' : '/data/'})
user = utility.getUserInfo(u'd225159') user = utility.getUserInfo(u'd225159')
print user print user
user = utility.getUserInfo(u'd65114') #user = utility.getUserInfo(u'd65114')
print user #print user
passwordHash = LdapUserManager.decodePasswordHash(user['userAttrs']['userPassword'][0]) #passwordHash = LdapUserManager.decodePasswordHash(user['userAttrs']['userPassword'][0])
print passwordHash #print passwordHash
attrDict = {'badgeNumber' : '000001', 'name' : 'Test, User 1.', 'firstName' : 'User', 'middleName' : '1.', 'lastName' : 'Test', 'passwordHashValue' : '84673F4A8774846B1C096511C7F6B1329CEE5CCC', 'inactive' : 'N', 'grp' : 'XSD-TEST', 'lastChangeDate' : '2015-02-03 15:52:15', 'email' : 'UTEST1@APS.ANL.GOV', 'isUserNotAnlEmployee' : 'N' } #print 'Creating user d000001'
user = utility.createUserInfo(u'd000001', attrDict) #user = utility.getUserInfo(u'd000001')
user = utility.getUserInfo(u'd000001') #print user
print user #attrDict = {'badgeNumber' : '000001', 'name' : 'Test, User 1.', 'firstName' : 'User', 'middleName' : '1.', 'lastName' : 'Test', 'passwordHashValue' : '84673F4A8774846B1C096511C7F6B1329CEE5CCC', 'inactive' : 'N', 'grp' : 'XSD-TEST', 'lastChangeDate' : '2015-02-03 15:52:15', 'email' : 'UTEST1@APS.ANL.GOV', 'isUserNotAnlEmployee' : 'N' }
#try:
# user = utility.createUserInfo(u'd000001', attrDict)
#except ObjectAlreadyExists, ex:
# print 'User d000001 already exists, will modify it'
# user = utility.updateUserInfo(u'd000001', attrDict)
#print user
#print LdapUserManager.encodePasswordHash(passwordHash) #print LdapUserManager.encodePasswordHash(passwordHash)
......
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