def rotate(record, newpassword): """ Grab any required fields from the record """ user = record.login oldpassword = record.password result = False host = record.get('cmdr:host') searchdn = record.get('cmdr:searchdn') try: server = Server(host, use_ssl=True, get_info=ALL) dn = 'uid=%s, cn=users, cn=accounts, %s'%(user, searchdn) conn = Connection(server, dn, oldpassword, auto_bind=True) conn.modify(dn, {'password': [(MODIFY_REPLACE, newpassword)]}) if (conn.result['result'] == 0): return True else: print("Server returned this message: %s"%(conn.result['message'])) conn.unbind() except: print("Error during connection to AD server") return result
def search_ldap(username): '''Searches the Tilburg University LDAP server for the given username and returns a tuple of first name, last name, full name, ANR, emplId and email address. Permission has been granted by TiU's legal department for retrieving this data. Raises LDAPError on any kind of error.''' result = () baseDN = "o=Universiteit van Tilburg,c=NL" searchFilter = '(uid={})'.format(username) attributes = ['givenName', 'sortableSurname', 'cn', 'employeeNumber', 'emplId', 'mail'] try: server = Server('ldaps.uvt.nl', use_ssl=True) conn = Connection(server, auto_bind=True) conn.search(baseDN, searchFilter, attributes=attributes) response = conn.response[0]['attributes'] for a in attributes: if a in response and response[a]: if type(response[a]) is list: result += (response[a][0],) else: result += (response[a],) else: result += ('',) except IndexError: raise LDAPError('Username not found') except Exception: raise LDAPError('Unknown error in LDAP query') return result
def useruid(s, login): """Connect to a LDAP and check the uid matching the given field data""" uid = False c = Connection(s, config.LDAPACC, password=config.LDAPPASS, auto_bind=True) if c.result["description"] != "success": print("Error connecting to the LDAP with the service account") return False # Look for the user entry. if not c.search(config.LDAPBASE, "(" + config.LDAPFIELD + "=" + login + ")") : print("Error: Connection to the LDAP with service account failed") else: if len(c.entries) >= 1 : if len(c.entries) > 1 : print("Error: multiple entries with this login. "+ \ "Trying first entry...") uid = c.entries[0].entry_dn else: print("Error: Login not found") c.unbind() return uid
def test_ldapi_encoded_url(self): if test_server_type == 'SLAPD': server = Server('ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi') connection = Connection(server, authentication=SASL, sasl_mechanism=EXTERNAL, sasl_credentials='') connection.open() connection.bind() self.assertTrue(connection.bound)
def get_ldap_connection(dn=None, password=None): try: cacert = configuration.conf.get("ldap", "cacert") except AirflowConfigException: pass try: ignore_malformed_schema = configuration.conf.get("ldap", "ignore_malformed_schema") except AirflowConfigException: pass if ignore_malformed_schema: set_config_parameter('IGNORE_MALFORMED_SCHEMA', ignore_malformed_schema) tls_configuration = Tls(validate=ssl.CERT_REQUIRED, ca_certs_file=cacert) server = Server(configuration.conf.get("ldap", "uri"), use_ssl=True, tls=tls_configuration) conn = Connection(server, native(dn), native(password)) if not conn.bind(): log.error("Cannot bind to ldap server: %s ", conn.last_error) raise AuthenticationError("Cannot bind to ldap server") return conn
def _authenticate(self,username,password,login=False): server_options = { 'host': repr(self._settings.host), 'use_ssl': self._settings.ssl.value, 'get_info': ALL } if self._settings.port.value != None: server_options['port'] = self._settings.port.value server = Server(**server_options) conn = Connection(server, user=username,password=password,auto_referrals=False,raise_exceptions=True) result = False try: result = conn.bind() except self._exceptions.LDAPSocketOpenError: raise self._exceptions.InvalidServer except self._exceptions.LDAPInvalidCredentialsResult: raise self._exceptions.InvalidCredentials if self._settings.port.value == None: self._settings.port = conn.server.port if login: if result == False: raise self._exceptions.InvalidCredentials if self._settings.basedn == None: self._settings.basedn = conn.server.info.raw['defaultNamingContext'][0].decode('utf-8') #fix to convert byte to string return conn return result
def rotate(record, newpassword): result = False host = record.get('cmdr:host') user_dn = record.get('cmdr:userdn') try: server = Server( host=host, use_ssl=True, get_info=ALL) conn = Connection( server=server, user=user_dn, password=record.password, auto_bind=True) changePwdResult = conn.extend.microsoft.modify_password(user_dn, newpassword) if (changePwdResult == True): print('Password changed successfully') record.password = newpassword result = True else: print("Server returned this message: %s" % (changePwdResult)) conn.unbind() except: print("Error during connection to AD server") return result
def connection(self): if self._conn is None: server = Server(self.server_uri, use_ssl=self.use_ssl) conn = Connection(server, self.bind_dn, self.password) conn.bind() self._conn = conn return self._conn
def ldapaccts(servername,ldappw): ldapacct_list=[] ldapserver='ldap://10.88.126.150' dn='cn=root,dc=example,dc=org' ldap_base='ou='+servername+',ou=proftpd servers,dc=example,dc=org' print(ldap_base) # define the Server and the Connection objects ldapserver='ldap://10.88.126.150' #s = Server(ldapserver, port = 389, get_info = ALL) # define an unsecure LDAP server, requesting info on the server and the schema #c = Connection(s, auto_bind = True, client_strategy = SYNC, user=dn, password=pw, authentication=SIMPLE, check_names=True) ldapconn=Connection(ldapserver,auto_bind=True,client_strategy = SYNC, user=dn, password=ldappw, authentication=SIMPLE, check_names=True) #print(s.info) # display info from the server. OID are decoded when recognized by the library #c.search(search_base=ldap_base,search_filter='') entry_list = ldapconn.extend.standard.paged_search(search_base =ldap_base, search_filter='(objectClass=shadowAccount)', search_scope=SUBTREE, attributes=['uid'], paged_size=5, generator=False) for entry in entry_list: user=''.join(entry['attributes']['uid']) ldapacct_list.append(user) #print(user) #print(entry['attributes']['uid']) # request a few objects from the LDAP server ldapconn.unbind() return ldapacct_list
def load_user_info(username): user = None # Initial connection to the LDAP server. server = Server(app.config['LDAP_URI']) connection = Connection(server) try: if not connection.bind(): return None # Verify that the user exists. result = connection.search(search_base=app.config['LDAP_SEARCH_BASE'], search_filter='(uid={})'.format(username), attributes=['mail', 'cn']) if not result: return None # The user exists! name = connection.response[0]['attributes']['cn'][0] email = connection.response[0]['attributes']['mail'][0] user = User(username, name, email) finally: connection.unbind() return user
def test_ldapi(self): if test_server_type == 'SLAPD': server = Server('ldapi:///var/run/slapd/ldapi') connection = Connection(server, authentication=SASL, sasl_mechanism=EXTERNAL, sasl_credentials='') connection.open() connection.bind() self.assertTrue(connection.bound)
class LDAP: _server = None _conn = None @staticmethod def append_if_not_in(target, faculty): if not faculty in target: target.append(faculty) def __init__(self): self._server = Server('centaur.unimelb.edu.au') self._conn = Connection(self._server) if not self._conn.bind(): raise Exception('Could not bind to ldap server') def find_department(self, email): if email is None: return None, None if 'unimelb' not in email: return 'External', None query = '(&(objectclass=person)(mail=%s))' % email self._conn.search('o=unimelb', query, attributes=['department', 'departmentNumber', 'auEduPersonSubType', 'displayName']) if len(self._conn.entries) == 0: return None, None department_no = [] for entry in self._conn.entries: if hasattr(entry, 'departmentNumber'): department_no.extend(entry.departmentNumber) return Faculties.get_from_departments(department_no) def __del__(self): self._conn.unbind()
def getuserdata(login): server = LDAP_SERVER # getInfo=GET_ALL_INFO attributes = ['uid', 'distinguishedName', 'cn', 'mail', 'telephoneNumber', 'department', 'gidNumber', 'uidNumber'] # basedn = 'OU=Accounts,DC=nrel,DC=gov' basedn = 'DC=nrel,DC=gov' search_filter = '(uid=%s)' % login # define a synchronous connection with basic authentication conn = Connection(server, auto_bind=True, client_strategy=STRATEGY_ASYNC_THREADED, user=LDAP_USER, password=LDAP_PASS, authentication=AUTH_SIMPLE) ##client_strategy=STRATEGY_SYNC #conn.tls = tls() #conn.start_tls() result = conn.search(basedn, search_filter=search_filter, search_scope=SEARCH_SCOPE_WHOLE_SUBTREE, attributes=attributes ) conn.get_response(result, timeout=10) data = conn.response # Check if a dict was returned, # meaning loginID is in LDAP and password works. if not data: return False # User has passed LDAP auth... # Finally, return the user's attribs. dn = data[0]['attributes'] return dn
def query_LDAP(server_kwargs, connection_kwargs, search_kwargs): total_entries = -1 s = Server(**server_kwargs) connection_kwargs["server"] = s c = Connection(**connection_kwargs) c.search(**search_kwargs) total_entries += len(c.response) stdout.write("%3d entries returned\r" % total_entries) response = c.response[:-1] cookie = c.result['controls']['1.2.840.113556.1.4.319']['value']['cookie'] while cookie: search_kwargs["paged_cookie"] = cookie c.search(**search_kwargs) stdout.flush() stdout.write("%3d entries returned\r" % total_entries) for entry in c.response: total_entries += 1 response.append(entry) cookie = c.result['controls']['1.2.840.113556.1.4.319']['value']['cookie'] print("Total response length: ", total_entries) print("\n") return response
class Test(unittest.TestCase): def setUp(self): server = Server(test_server, test_port, allowed_referral_hosts=('*', True)) self.connection = Connection(server, auto_bind=True, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=False, pool_name='pool1') def tearDown(self): self.connection.unbind() if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED: self.connection.strategy.terminate() self.assertFalse(self.connection.bound) def test_modify(self): attribute1 = Attribute() vals1 = ValsAtLeast1() vals1[0] = AttributeValue('tost') attribute1['type'] = AttributeDescription('sn') attribute1['vals'] = vals1 attribute2 = Attribute() vals2 = ValsAtLeast1() vals2[0] = AttributeValue('tust') attribute2['type'] = AttributeDescription('givenName') attribute2['vals'] = vals2 attribute3 = Attribute() vals3 = ValsAtLeast1() vals3[0] = AttributeValue('inetOrgPerson') attribute3['type'] = AttributeDescription('objectClass') attribute3['vals'] = vals3 attributes = AttributeList() attributes[0] = attribute1 attributes[1] = attribute2 attributes[2] = attribute3 add_req = AddRequest() add_req['entry'] = LDAPDN(dn_for_test(test_base, 'test-modify')) add_req['attributes'] = attributes result = self.connection.post_send_single_response(self.connection.send('addRequest', add_req)) if not isinstance(result, bool): self.connection.get_response(result) vals_mod1 = Vals() vals_mod1[0] = 'test-modified' part_attr1 = PartialAttribute() part_attr1['type'] = AttributeDescription('sn') part_attr1['vals'] = vals_mod1 change1 = Change() change1['operation'] = Operation('replace') change1['modification'] = part_attr1 changes = Changes() changes[0] = change1 modify_req = ModifyRequest() modify_req['object'] = LDAPDN(dn_for_test(test_base, 'test-modify')) modify_req['changes'] = changes result = self.connection.post_send_single_response(self.connection.send('modifyRequest', modify_req)) if not isinstance(result, bool): self.connection.get_response(result) self.assertTrue(True)
def ldap_lookup_user(username): # print("lookup called with {!s}".format(username)) # to do: make this asynchronous if LOCAL_DEV: result = { "cn": [ "Isabella F Jorissen", "ijorissen" ], "eduPersonAffiliation": [ "student" ], "eduPersonEntitlement": [ "cascade", "thesis-vpn" ], "eduPersonPrimaryAffiliation": "student", "eduPersonPrincipalName": "*****@*****.**", "gecos": "Isabella F Jorissen", "gidNumber": 503, "givenName": [ "Isabella" ], "homeDirectory": "/afs/reed.edu/user/i/s/isjoriss", "loginShell": "/bin/bash", "mail": [ "*****@*****.**" ], "objectClass": [ "top", "inetOrgPerson", "eduPerson", "ReedCollegePerson", "posixAccount", "inetLocalMailRecipient" ], "rcLocalHomeDirectory": "/home/isjoriss", "rcMiddleName": [ "F" ], "sn": [ "Jorissen" ], "uid": [ "isjoriss" ], "uidNumber": 39878} else: server = Server('ldap.reed.edu', port=389, get_info=ALL) con = Connection(server, auto_bind=True) query = 'uid={!s},ou=people,dc=reed,dc=edu'.format(username) con.search( search_base=query, search_filter='(objectClass=*)', search_scope=SUBTREE, attributes=ALL_ATTRIBUTES) result = con.response[0]['attributes'] return result
def checkpassword(self, **params): username = cherrypy.request.params.get('username').lower() password = cherrypy.request.params.get('password') # check if password is empty if not password: smsgwglobals.wislogger.debug("FRONT: No password on login") raise cherrypy.HTTPRedirect("/smsgateway") # check if username is valid if not username: smsgwglobals.wislogger.debug("FRONT: No username on login") raise cherrypy.HTTPRedirect("/smsgateway") if len(username) > wisglobals.validusernamelength: smsgwglobals.wislogger.debug("FRONT: Username to long on login") raise cherrypy.HTTPRedirect("/smsgateway") if (re.compile(wisglobals.validusernameregex).findall(username)): smsgwglobals.wislogger.debug("FRONT: Username is not valid login") raise cherrypy.HTTPRedirect("/smsgateway") if 'root' in username: smsgwglobals.wislogger.debug("FRONT: ROOT Login " + username) try: if Helper.checkpassword(username, password) is True: cherrypy.session['logon'] = True raise cherrypy.HTTPRedirect("/smsgateway/main") else: raise cherrypy.HTTPRedirect("/smsgateway") except error.UserNotFoundError: raise cherrypy.HTTPRedirect("/smsgateway") else: try: smsgwglobals.wislogger.debug("FRONT: Ldap Login " + username) if wisglobals.ldapenabled is None or 'true' not in wisglobals.ldapenabled.lower(): smsgwglobals.wislogger.debug("FRONT: Ldap Login disabled " + username) raise cherrypy.HTTPRedirect("/smsgateway") smsgwglobals.wislogger.debug("FRONT: Ldap Login " + username) smsgwglobals.wislogger.debug("FRONT: Ldap Users " + str(wisglobals.ldapusers)) if username not in wisglobals.ldapusers: smsgwglobals.wislogger.debug("FRONT: Ldap username not in ldapusers") raise cherrypy.HTTPRedirect("/smsgateway") smsgwglobals.wislogger.debug("FRONT: Ldap Server " + wisglobals.ldapserver) s = Server(wisglobals.ldapserver, get_info=ALL) userdn = 'cn=' + username + ',' + wisglobals.ldapbasedn c = Connection(s, user=userdn, password=password) if c.bind(): smsgwglobals.wislogger.debug("FRONT: Ldap login successful " + username) cherrypy.session['logon'] = True raise cherrypy.HTTPRedirect("/smsgateway/main") else: raise cherrypy.HTTPRedirect("/smsgateway") except error.UserNotFoundError: raise cherrypy.HTTPRedirect("/smsgateway")
def process_request(request): """Login Page""" form = LoginForm() if request.method == "POST": form = LoginForm(request.POST) if form.is_valid(): try: # define the server and the connection s = Server( "128.187.61.50", port=636, get_info=GET_ALL_INFO ) # define an unsecure LDAP server, requesting info on DSE and schema c = Connection( s, auto_bind=True, client_strategy=STRATEGY_SYNC, user=form.cleaned_data["username"], password=form.cleaned_data["password"], authentication=AUTH_SIMPLE, ) print(s.info) # display info from the DSE. OID are decoded when recognized by the library c.unbind() except: print("-----------------------------------------------") print("Failed to authenticate against Active Directory") print("-----------------------------------------------") user = authenticate(username=form.cleaned_data["username"], password=form.cleaned_data["password"]) if user is not None: if user.is_active: login(request, user) # converts session to database -- see below add_history_to_database(request, user) if form.cleaned_data["remember"] == True: # The user is logged out after 'x' seconds request.session.set_expiry(1209600) else: # The user is logged out upon closing the browser request.session.set_expiry(0) # Redirect to a success page. ################################### WONT WORK ####################### # return HttpResponseRedirect('/homepage/dash/') return HttpResponse('<script> window.location.href="";</script>') else: # Return a 'disabled account' error message return HttpResponseRedirect("/manager/searchinventory/") else: # Return an 'invalid login' error message. return HttpResponseRedirect("/manager/searchstores/") tvars = {"form": form} return templater.render_to_response(request, "login.html", tvars)
def test_raises_size_limit_exceeded_exception(self): connection = Connection(self.server, user='******', password='******', client_strategy=MOCK_SYNC, raise_exceptions=True) # create fixtures connection.strategy.add_entry('cn=user1,ou=test', {'userPassword': '******', 'revision': 1}) connection.strategy.add_entry('cn=user2,ou=test', {'userPassword': '******', 'revision': 2}) connection.strategy.add_entry('cn=user3,ou=test', {'userPassword': '******', 'revision': 3}) connection.bind() with self.assertRaises(LDAPSizeLimitExceededResult): connection.search('ou=test', '(cn=*)', size_limit=1)
def __init__(self, user): if MongoConnector.db is None: MongoConnector(BiomajConfig.global_config.get('GENERAL', 'db.url'), BiomajConfig.global_config.get('GENERAL', 'db.name')) self.users = MongoConnector.users self.id = user self.user = self.users.find_one({'id': user}) ldap_server = None con = None if not self.user and BiomajConfig.global_config.get('GENERAL', 'use_ldap') == '1': # Check if in ldap #import ldap from ldap3 import Server, Connection, AUTH_SIMPLE, STRATEGY_SYNC, STRATEGY_ASYNC_THREADED, SEARCH_SCOPE_WHOLE_SUBTREE, GET_ALL_INFO try: ldap_host = BiomajConfig.global_config.get('GENERAL', 'ldap.host') ldap_port = BiomajConfig.global_config.get('GENERAL', 'ldap.port') #con = ldap.initialize('ldap://' + ldap_host + ':' + str(ldap_port)) ldap_server = Server(ldap_host, port=int(ldap_port), get_info=GET_ALL_INFO) con = Connection(ldap_server, auto_bind=True, client_strategy=STRATEGY_SYNC, check_names=True) except Exception as err: logging.error(str(err)) self.user = None ldap_dn = BiomajConfig.global_config.get('GENERAL', 'ldap.dn') base_dn = 'ou=People,' + ldap_dn ldapfilter = "(&(|(uid=" + user + ")(mail=" + user + ")))" try: #con.simple_bind_s() attrs = ['mail'] #results = con.search_s(base_dn, ldap.SCOPE_SUBTREE, filter, attrs) con.search(base_dn, ldapfilter, SEARCH_SCOPE_WHOLE_SUBTREE, attributes=attrs) if con.response: ldapMail = None #for dn, entry in results: for r in con.response: user_dn = str(r['dn']) #if 'mail' not in entry: if 'mail' not in r['attributes']: logging.error('Mail not set for user '+user) else: #ldapMail = entry['mail'][0] ldapMail = r['attributes']['mail'][0] self.user = { 'id' : user, 'email': ldapMail, 'is_ldap': True } self.user['_id'] = self.users.insert(self.user) else: self.user = None except Exception as err: logging.error(str(err)) if con: con.unbind()
def get_fake_ldap_connection(): server = Server('my_fake_server') connection = Connection( server, client_strategy=MOCK_SYNC ) connection.bind() connection.strategy.add_entry(PETER[0], PETER[1]) connection.strategy.add_entry(BILL[0], BILL[1]) return connection
def _connect(self, full_username, password): connection = Connection( self.url, user=full_username, password=password, authentication=SIMPLE, read_only=True, version=self.version ) connection.bind() return connection
def auth(username, password): un_init = init_conf() ldap = ast.literal_eval(un_init['ldap']) # 后台录入的验证用户信息,连接到ldap后通过查询登陆的用户名所在的OU,DN信息,然后进一步去ldap服务器进行账户和密码验证。 LDAP_SERVER = ldap['host'] LDAP_DOMAIN = ldap['domain'] LDAP_TYPE = ldap['type'] LDAP_SCBASE = ldap['sc'] if LDAP_TYPE == '1': user = username + '@' + LDAP_DOMAIN elif LDAP_TYPE == '2': user = "******" % (username, LDAP_SCBASE) else: user = "******" % (username, LDAP_SCBASE) c = ldap3.Connection( ldap3.Server(LDAP_SERVER, get_info=ldap3.ALL), user=user, password=password) ret = c.bind() if ret: if ldap['ou']: res = c.search( search_base=LDAP_SCBASE, search_filter='(cn={})'.format(username), search_scope=SUBTREE, attributes=['cn', 'uid', 'mail'], ) if res: entry = c.response[0] dn = entry['dn'] attr_dict = entry['attributes'] # check password by dn try: conn2 = Connection(ldap3.Server(LDAP_SERVER, get_info=ldap3.ALL), user=dn, password=password, check_names=True, lazy=False, raise_exceptions=False) conn2.bind() if conn2.result["description"] == "success": print((True, attr_dict["mail"], attr_dict["cn"], attr_dict["uid"])) c.unbind() conn2.unbind() return True else: print("auth fail") return False except: print("auth fail") return False else: return True else: return False
def QueryLdap(query, attr): server = Server(DC_SERVER, get_info=ALL) conn = Connection(server, 'cn=' + ADMIN + ',cn=users,dc=matorin,dc=local', ADMIN_PASSWORD, auto_bind=True) conn.search(search_base ='DC=matorin,DC=local', search_filter = query, attributes = attr,) return_list = [] for entry in conn.response: try: return_list.append(entry['attributes']) except KeyError: continue return return_list
def test_ldapi_encoded_url(self): if test_server_type == 'SLAPD': try: server = Server('ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi') connection = Connection(server, authentication=SASL, sasl_mechanism=EXTERNAL, sasl_credentials=('',)) connection.open() connection.bind() self.assertTrue(connection.bound) except LDAPSocketOpenError: return self.assertTrue(False)
def test_raise_exceptions(self): server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True), get_info=test_get_info) connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1', check_names=test_check_names, raise_exceptions=True) ok = False try: result = connection.search('xxx=xxx', '(cn=*)') if not isinstance(result, bool): connection.get_response(result) except LDAPNoSuchObjectResult: ok = True self.assertTrue(ok)
class LDAPSRelayClient(LDAPRelayClient): PLUGIN_NAME = "LDAPS" MODIFY_ADD = MODIFY_ADD def __init__(self, serverConfig, target, targetPort = 636, extendedSecurity=True ): LDAPRelayClient.__init__(self, serverConfig, target, targetPort, extendedSecurity) def initConnection(self): self.server = Server("ldaps://%s:%s" % (self.targetHost, self.targetPort), get_info=ALL) self.session = Connection(self.server, user="******", password="******", authentication=NTLM) self.session.open(False) return True
class LDAP(object): """ LDAP connection class """ def __init__(self, server, base): self.server = server self.base = base self.conn = Connection(self.server, auto_bind=True) def getGroup(self, groupname): self.conn.search('ou=People,' + self.base, '(&(objectclass=person)(memberof=cn=' + groupname + ',ou=Groups,' + self.base + '))', attributes=['uid', 'sn', 'givenName']) return self.conn.response
class Test(unittest.TestCase): def setUp(self): server = Server(test_server, test_port, allowed_referral_hosts=('*', True)) self.connection = Connection(server, auto_bind=True, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=False, pool_name='pool1') def tearDown(self): self.connection.unbind() if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED: self.connection.strategy.terminate() def test_compare(self): attribute1 = Attribute() vals1 = ValsAtLeast1() vals1[0] = AttributeValue('tost') attribute1['type'] = AttributeDescription('sn') attribute1['vals'] = vals1 attribute2 = Attribute() vals2 = ValsAtLeast1() vals2[0] = AttributeValue('tust') attribute2['type'] = AttributeDescription('givenName') attribute2['vals'] = vals2 attribute3 = Attribute() vals3 = ValsAtLeast1() vals3[0] = AttributeValue('inetOrgPerson') attribute3['type'] = AttributeDescription('objectClass') attribute3['vals'] = vals3 attributes = AttributeList() attributes[0] = attribute1 attributes[1] = attribute2 attributes[2] = attribute3 add_req = AddRequest() add_req['entry'] = LDAPDN(dn_for_test(test_base, 'test-compare')) add_req['attributes'] = attributes result = self.connection.post_send_single_response(self.connection.send('addRequest', add_req)) if not isinstance(result, bool): self.connection.get_response(result) ava = AttributeValueAssertion() ava['attributeDesc'] = AttributeDescription('givenName') ava['assertionValue'] = AssertionValue('tust') compare_req = CompareRequest() compare_req['entry'] = LDAPDN(dn_for_test(test_base, 'test-compare')) compare_req['ava'] = ava result = self.connection.post_send_single_response(self.connection.send('compareRequest', compare_req)) if not isinstance(result, bool): self.connection.get_response(result) self.assertTrue(True)
def test_open_ssl_with_defaults(self): if isinstance(test_server, (list, tuple)): server = ServerPool(pool_strategy=test_pooling_strategy, active=test_pooling_active, exhaust=test_pooling_exhaust) for host in test_server: server.add(Server(host=host, port=test_port, allowed_referral_hosts=('*', True), get_info=test_get_info, mode=test_server_mode)) else: server = Server(host=test_server, port=test_port_ssl, use_ssl=True) connection = Connection(server, user=test_user, password=test_password) connection.open() self.assertFalse(connection.closed) connection.unbind() if connection.strategy.pooled: connection.strategy.terminate()
def main(): ''' INSTANCE CONFIGURATION ''' SERVER_IP = demisto.params().get('server_ip') USERNAME = demisto.params().get('credentials')['identifier'] PASSWORD = demisto.params().get('credentials')['password'] DEFAULT_BASE_DN = demisto.params().get('base_dn') SECURE_CONNECTION = demisto.params().get('secure_connection') DEFAULT_PAGE_SIZE = int(demisto.params().get('page_size')) NTLM_AUTH = demisto.params().get('ntlm') UNSECURE = demisto.params().get('unsecure', False) PORT = demisto.params().get('port') if PORT: # port was configured, cast to int PORT = int(PORT) last_log_detail_level = None try: try: set_library_log_hide_sensitive_data(True) if is_debug_mode(): demisto.info( 'debug-mode: setting library log detail to EXTENDED') last_log_detail_level = get_library_log_detail_level() set_library_log_detail_level(EXTENDED) server = initialize_server(SERVER_IP, PORT, SECURE_CONNECTION, UNSECURE) except Exception as e: return_error(str(e)) return global conn if NTLM_AUTH: # intialize connection to LDAP server with NTLM authentication # user example: domain\user domain_user = SERVER_IP + '\\' + USERNAME if '\\' not in USERNAME else USERNAME conn = Connection(server, user=domain_user, password=PASSWORD, authentication=NTLM) else: # here username should be the user dn conn = Connection(server, user=USERNAME, password=PASSWORD) # bind operation is the “authenticate” operation. try: # open socket and bind to server if not conn.bind(): message = "Failed to bind to server. Please validate the credentials configured correctly.\n{}".format( json.dumps(conn.result)) return_error(message) return except Exception as e: exc_msg = str(e) demisto.info("Failed bind to: {}:{}. {}: {}".format( SERVER_IP, PORT, type(e), exc_msg + "\nTrace:\n{}".format(traceback.format_exc()))) message = "Failed to access LDAP server. Please validate the server host and port are configured correctly" if 'ssl wrapping error' in exc_msg: message = "Failed to access LDAP server. SSL error." if not UNSECURE: message += ' Try using: "Trust any certificate" option.' return_error(message) return demisto.info('Established connection with AD LDAP server') if not base_dn_verified(DEFAULT_BASE_DN): message = "Failed to verify the base DN configured for the instance.\n" \ "Last connection result: {}\n" \ "Last error from LDAP server: {}".format(json.dumps(conn.result), json.dumps(conn.last_error)) return_error(message) return demisto.info('Verfied base DN "{}"'.format(DEFAULT_BASE_DN)) ''' COMMAND EXECUTION ''' if demisto.command() == 'test-module': if conn.user == '': # Empty response means you have no authentication status on the server, so you are an anonymous user. raise Exception("Failed to authenticate user") demisto.results('ok') if demisto.command() == 'ad-search': free_search(DEFAULT_BASE_DN, DEFAULT_PAGE_SIZE) if demisto.command() == 'ad-expire-password': expire_user_password(DEFAULT_BASE_DN) if demisto.command() == 'ad-set-new-password': set_user_password(DEFAULT_BASE_DN) if demisto.command() == 'ad-unlock-account': unlock_account(DEFAULT_BASE_DN) if demisto.command() == 'ad-disable-account': disable_user(DEFAULT_BASE_DN) if demisto.command() == 'ad-enable-account': enable_user(DEFAULT_BASE_DN) if demisto.command() == 'ad-remove-from-group': remove_member_from_group(DEFAULT_BASE_DN) if demisto.command() == 'ad-add-to-group': add_member_to_group(DEFAULT_BASE_DN) if demisto.command() == 'ad-create-user': create_user() if demisto.command() == 'ad-delete-user': delete_user() if demisto.command() == 'ad-update-user': update_user(DEFAULT_BASE_DN) if demisto.command() == 'ad-modify-computer-ou': modify_computer_ou(DEFAULT_BASE_DN) if demisto.command() == 'ad-create-contact': create_contact() if demisto.command() == 'ad-update-contact': update_contact() if demisto.command() == 'ad-get-user': search_users(DEFAULT_BASE_DN, DEFAULT_PAGE_SIZE) if demisto.command() == 'ad-get-computer': search_computers(DEFAULT_BASE_DN, DEFAULT_PAGE_SIZE) if demisto.command() == 'ad-get-group-members': search_group_members(DEFAULT_BASE_DN, DEFAULT_PAGE_SIZE) except Exception as e: message = str(e) if conn: message += "\nLast connection result: {}\nLast error from LDAP server: {}".format( json.dumps(conn.result), conn.last_error) return_error(message) return finally: # disconnect and close the connection if conn: conn.unbind() if last_log_detail_level: set_library_log_detail_level(last_log_detail_level)
def get_ad_users(self): """Returns a list of users from specific OUs via LDAPS. Outputs: user_list - A list of active users in AD. Raises: OSError - Occurs when the script is unable to locate or open the configuration file. It can also occur when the value used as input for the wintime_to_timestr function receives an invalid input. LDAPExceptionError - Occurs when the LDAP3 functions generate an error. The base class for all LDAPExcetionErrors is used so that the log.exception call will catch the detailed exception while not missing any potential exceptions. A fail safe, as it were.""" # Setting logging and configuration. config = ConfigParser() try: config.read(self.conf) except OSError: self.log.exception( 'Fatal Error: Unable to open configuration file.') exit(1) ldap_url = config['ldap']['url'] ldap_bind_dn = config['ldap']['bind_dn'] search_ou = config['ldap']['search_ou'].split('|') ldap_bind_secret = get_credentials({ 'api_key': config['ldap']['scss_api'], 'otp': config['ldap']['scss_otp'], 'userid': config['ldap']['scss_user'], 'url': config['ldap']['scss_url'] }) # Connecting to LDAP. Raising an exception with logging if the # connection is unsuccessful. start = time() tls_config = Tls(validate=CERT_NONE, version=PROTOCOL_TLSv1_2) server = Server(ldap_url, use_ssl=True, tls=tls_config) try: conn = Connection(server, user=ldap_bind_dn, password=ldap_bind_secret, auto_bind=True) except LDAPExceptionError: self.log.exception('Error occurred connecting to LDAP server.') self.log.debug('Successfully connected to LDAP server: %s', ldap_url) # Getting user data from LDAP, and converting the data (a list # of strings) to a dictionary so that it can be easily written # to different outputs if so desired. user_list = [] raw_user_data = [] # Searching LDAP for users that are in the OUs (and all sub-OUs) # specified in config['ldap']['search_ou']. ldap_filter = ('(&(objectClass=user)(objectCategory=CN=Person,' + 'CN=Schema,CN=Configuration,DC=24hourfit,DC=com))') for ou in search_ou: user_data = conn.extend.standard.paged_search( ou, ldap_filter, search_scope=SUBTREE, attributes=['sAMAccountName'], paged_size=500, ) for raw_data in user_data: raw_user_data.append(raw_data['raw_attributes']) # Mapping LDAP data to a dictionary. We are decoding the values # so that Python recognizes them as a string instead of byte-like # objects for compatibiltiy with other string (or string realted) # functions/methods. for data in raw_user_data: acct_name = data['sAMAccountName'][0].decode().lower() self.ad_users.append(acct_name) self.log.info('Successfully retrieved active user information from %s', config['ldap']['url']) # Unbinding the LDAP object as a good house cleaning measure. conn.unbind() end = time() _elapsed = end - start elapsed = int(round(_elapsed, 0)) self.log.debug('Retrieved active users in %d seconds', elapsed) user_list = self.ad_users return user_list
class AD(): def __init__(self, host='10.9.1.42', display=True, debug=True): from ldap3 import Server, Connection, ALL, NTLM self._ldap_host = host self._ldap_user = '******' self._ldap_pass = '******' server = Server(self._ldap_host, port=389, use_ssl=False, get_info=ALL) self.conn = Connection(server, user=self._ldap_user, password=self._ldap_pass, authentication=NTLM, auto_bind=True) self._dn = {'base': 'dc=ad,dc=base-fx,dc=com'} self._dgattrs = {'user': {}} self._dgattrs['user']['dn'] = ','.join(['ou=Basers', self._dn['base']]) def cur_user(self): return self.conn.extend.standard.who_am_i() def search_attr(self, attrs='cn', value='', search_range=0, reponse=0): from ldap3 import SUBTREE attr = [ 'cn', 'uidNumber', 'displayName', 'department', 'userAccountControl', 'adminCount', 'member', 'lockoutTime' ] if not isinstance(attrs, list): attrs = [attrs] if search_range == 1 and len(attrs) == 1: searchfilter = "(&(objectClass=user)(%s=" % attrs[ 0] + "*" + "%s" % value + "*))" elif search_range == 0 and len(attrs) == 1: searchfilter = "(&(objectClass=user)(%s=%s))" % (attrs[0], value) elif attrs[0] == 'cn': searchfilter = search_range else: searchfilter = search_range attr = attrs self.conn.search(search_base=self._dgattrs['user']['dn'], search_filter=searchfilter, search_scope=SUBTREE, attributes=attr) result = self.conn.entries if reponse: result = self.conn.response # [{},{}] else: result = self.conn.entries if result != []: return result else: return False def check_user_enabled(self, usercontrol): old_usercontrol = int(usercontrol) useraccountcontrol = old_usercontrol useraccountcontrols = [ 16777216, 8388608, 4194304, 2097152, 1048576, 524288, 262144, 131072, 65536, 8192, 4096, 2048, 512, 256, 128, 64, 32, 16, 8, 2, 1 ] uac_array = [] for uac in useraccountcontrols: if useraccountcontrol >= uac: uac_array.append(uac) useraccountcontrol = useraccountcontrol - uac if 2 not in uac_array: return True, old_usercontrol return False, old_usercontrol def check_user_unlocked(self, lockouttime): if lockouttime is None or str( lockouttime) == '1601-01-01 00:00:00+00:00': return True else: return False def check_user(self, username): search_result = self.search_attr(value=username) result_info = {} # print(search_result) if search_result: user_enabled = self.check_user_enabled( search_result[0].userAccountControl.value) user_unlocked = self.check_user_unlocked( search_result[0].lockoutTime.value) result_info.setdefault('enabled', user_enabled[0]) result_info.setdefault('unlocked', user_unlocked) result_info.setdefault('exist', True) return result_info else: result_info.setdefault('exist', False) return result_info def set_user_attr(self, username, attrs): from ldap3 import MODIFY_REPLACE search_result = self.search_attr(value=username, reponse=1) # print(search_result) result_info = {} if search_result: user_dn = search_result[0]['dn'] print(user_dn) modify_attr = {} for k, v in attrs.items(): modify_attr.setdefault(k, []).append(MODIFY_REPLACE) modify_attr.setdefault(k, []).append([v]) self.conn.modify(user_dn, modify_attr) result_info.setdefault('status', self.conn.result['result']) else: result_info.setdefault('exist', False) return result_info def test(self): return self.conn def unlock(self, username): return self.set_user_attr(username, {'lockoutTime': 0}) def enable_user(self, username): return self.set_user_attr(username, {'userAccountControl': 66048}) def disable_user(self, username): return self.set_user_attr(username, {'userAccountControl': 66050})
CFGPATH = HOME + '/etc/admin.ini' config = ConfigParser() config.read(CFGPATH) dirhost = config.get('ldap','ldap1_host') diruser = config.get('ldap','ldap_user') dirpass = config.get('ldap','ldap_pass') dirport = 636 basedn = "dc=example,dc=com" query = "(objectclass=*)" attrs = ['*'] server = Server(dirhost, port=dirport, use_ssl=True) c = Connection(server, user=diruser, password=dirpass, auto_bind=True) total_entries = 0 entry_generator = c.extend.standard.paged_search( search_base=basedn, search_filter=query, search_scope=SUBTREE, attributes=attrs, paged_size = 100, generator = False ) for entry in entry_generator: total_entries += 1 ldif_output = c.response_to_ldif()
def get_bad_svc_acct_pwd(self): """Produces a list of service accounts that have not had a password change in 365 days. Keyword Arguments: None Returns: self.svc_acct_pwd_exp - A list of service accounts that have aged passwords. Raises: OSError - Occurs when the script is unable to locate or open the configuration file. LDAPExceptionError - Occurs when the LDAP3 functions generate an error. The base class for all LDAPExcetionErrors is used so that the log.exception call will catch the detailed exception while not missing any potential exceptions.""" # Retrieving information from the configuration file. config = ConfigParser() try: config.read(self.conf) except OSError: self.log.exception('Unable to open configuration file.') exit(1) ldap_url = config['ldap']['url'] ldap_bind_dn = config['ldap']['bind_dn'] search_ou = config['ldap']['svc_ou'].split('|') # Getting credentials from SCSS. ldap_bind_secret = get_credentials({ 'api_key': config['ldap']['scss_api'], 'otp': config['ldap']['scss_otp'], 'userid': config['ldap']['scss_user'], 'url': config['ldap']['scss_url'] }) # Getting password expiration time (in days). Change this # value in the configuration as approrpiate for your # organization. passwd_exp_days = int(config['ldap']['passwd_exp']) # Connecting to LDAP. tls_config = Tls(validate=CERT_NONE, version=PROTOCOL_TLSv1_2) server = Server(ldap_url, use_ssl=True, tls=tls_config) try: conn = Connection(server, user=ldap_bind_dn, password=ldap_bind_secret, auto_bind=True) except LDAPExceptionError: self.log.exception('Error occurred connecting to LDAP server.') self.log.debug('Successfully connected to LDAP server: %s', ldap_url) raw_user_data = [] # Searching LDAP for service accounts that are in the OUs # (and all sub-OUs) specified in config['ldap']['svc_ou']. ldap_filter = ('(&(objectClass=user)(objectCategory=CN=Person,' + 'CN=Schema,CN=Configuration,DC=24hourfit,DC=com))') for ou in search_ou: user_data = conn.extend.standard.paged_search( ou, ldap_filter, search_scope=SUBTREE, attributes=['sAMAccountName', 'passwordLastChange'], paged_size=500, ) for raw_data in user_data: raw_user_data.append(raw_data['raw_attributes']) current_time = round(time()) for data in raw_data: # Coverting wintime to epoch. wintime = int(data[0]['passwordLastChange']) pwd_change = wintime / 10000000 - 11644473600 # Determining password age. pwd_age = int(current_time - pwd_change) / 60 / 24 / 24 # Determing if a password hasn't been changed since the # value specified in the configuration. if pwd_age >= passwd_exp_days: self.svc_acct_pwd_exp.append( data[0]['sAMAccountName'].decode()) return self.svc_acct_pwd_exp
from ldap3 import Server, Connection, SIMPLE, SYNC, ASYNC, SUBTREE, ALL # домен - example.com # DNS имя сервера Active Directory AD_SERVER = 'mskdc7.rusagrotrans.ru' # Пользователь (логин) в Active Directory - нужно указать логин в AD # в формате 'EXAMPLE\aduser' или '*****@*****.**' AD_USER = '******' AD_PASSWORD = '******' AD_SEARCH_TREE = 'dc=rusagrotrans,dc=ru' server = Server(AD_SERVER) conn = Connection(server, user=AD_USER, password=AD_PASSWORD) conn.bind() # в ответ должно быть - True # Поиск в Active Directory # примеры ldap фильтров можно посмотреть здесь - # https://social.technet.microsoft.com/wiki/contents/articles/8077.active-directory-ldap-ru-ru.aspx # Я в нижеследующем фильтре: # - исключаю всеx отключенных пользователей (!(UserAccountControl:1.2.840.113556.1.4.803:=2)) # - добавляю только тех пользователей у которых заполнено имя и фамилия # - и вывожу атрибуты - attributes # Все возможные атрибуты Active Directory можно посмотреть здесь - # https://msdn.microsoft.com/en-us/library/ms675090%28v=vs.85%29.aspx conn.search(AD_SEARCH_TREE, '(&(objectCategory=Person)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(givenName=*)(sn=*))', SUBTREE, attributes=['cn', 'proxyAddresses', 'department', 'sAMAccountName', 'displayName', 'telephoneNumber', 'ipPhone', 'mail', 'title', 'manager', 'objectGUID', 'company', 'lastLogon']
def loginpage(request): state = "Please log in below..." username = password = instance_id = instance_name = status = console = fixed = conn = '' if request.POST: username = request.POST.get('username') password = request.POST.get('password') if username and password: request.session['username'] = username user_name = username + '@' + settings.DOMAIN_NAME password = password try: s = Server(settings.LDAP_SERVER[0], port=settings.LDAP_SERVER_PORT, use_ssl=settings.LDAP_SSL, get_info=ALL) conn = Connection(s, user=user_name, password=password, auto_bind=True) userlog.info("%s user login ", username) instance_name = get_assigned_computer(username) if instance_name == '': state = "No allocated instances..! Please contact your Administrator..!" userlog.info(state) return render_to_response('login.html', {'state': state}) status = instance_status(instance_name) if status == "vm not found....!": state = "Instance not found..! or Problem occuerd to find the instace from the server..!" userlog.info(state) return render_to_response('login.html', {'state': state}) elif (status == "Server not Found"): return render_to_response('Error.html') instance_id = get_instance_id(instance_name) #fixed = get_instance_ipaddress(instance_name) floating_ip = get_instance_floatingip(instance_name) console = vnc_console(instance_name) if status == "ACTIVE": button_color = "btn btn-danger btn-xs" else: button_color = "btn btn-success btn-xs " rdp_file = download_RDP(username, instance_id, instance_name) return render_to_response( 'index.html', { 'password': password, 'username': username, 'instancename': instance_name, 'instanceid': instance_id, 'status': status, 'console': console, 'fixedip': fixed, 'floatingip': floating_ip, 'RDP_file': rdp_file, 'button_color': button_color }) except ldap3.core.exceptions.LDAPBindError: state = 'Wrong username or password' except ldap3.core.exceptions.LDAPSocketOpenError: try: s = Server(settings.LDAP_SERVER[1], port=settings.LDAP_SERVER_PORT, use_ssl=settings.LDAP_SSL, get_info=ALL) conn = Connection(s, user=user_name, password=password, auto_bind=True) userlog.info("%s user login ", username) instance_name = get_assigned_computer(username) if instance_name == '': state = "No allocated instances..! Please contact your Administrator..!" userlog.info(state) return render_to_response('login.html', {'state': state}) status = instance_status(instance_name) if status == "vm not found....!": state = "Instance not found..! or Problem occuerd to find the instace from the server..!" userlog.info(state) return render_to_response('login.html', {'state': state}) elif (status == "Server not Found"): return render_to_response('Error.html') instance_id = get_instance_id(instance_name) #fixed = get_instance_ipaddress(instance_name) floating_ip = get_instance_floatingip(instance_name) console = vnc_console(instance_name) if status == "ACTIVE": button_color = "btn btn-danger btn-xs" else: button_color = "btn btn-success btn-xs " rdp_file = download_RDP(username, instance_id, instance_name) return render_to_response( 'index.html', { 'password': password, 'username': username, 'instancename': instance_name, 'instanceid': instance_id, 'status': status, 'console': console, 'fixedip': fixed, 'floatingip': floating_ip, 'RDP_file': rdp_file, 'button_color': button_color }) except ldap3.core.exceptions.LDAPBindError: state = 'Wrong username or password' except ldap3.core.exceptions.LDAPSocketOpenError: state = 'AD server not available' else: state = "username and password must be NOt Empty...!!!!" return render_to_response('login.html', {'state': state}) return render_to_response('login.html', {'state': state})
def setUp(self): self.connection = Connection(server=None, client_strategy=LDIF) self.connection.open()
def set_init(self, app, request): asyncio.get_event_loop().set_debug(True) logging.basicConfig(level=logging.DEBUG) ldap_server = app.app['settings']['ldap.server'] conn = Connection(ldap_server, auto_bind=True) self.conn = conn # test entry is empty conn.search(self.base_dn, '(objectclass=top)') assert len(conn.entries) == 1, 'Refusing test: ldap entry is not empty' # set app testing settings = app.app['settings'].copy() config_dn = 'ou=config,' + self.base_dn userFilter = 'mail={username},ou=users,' + self.base_dn settings['ldap.base_dn'] = self.base_dn settings['ldap.config_dn'] = config_dn settings['ldap.user_filter'] = userFilter settings['valid_password'] = '******' settings['password_policy'] = 'plone.oauth.password.password_policy' new_app = main(settings) self.app = app self.params = {} self.headers = {} self.app.app['settings'] = new_app['settings'] # mock redis if self.DISABLE_CACHE_REDIS: class AsyncMock(MagicMock): async def __call__(self, *args, **kwargs): return super(AsyncMock, self).__call__(*args, **kwargs) self.original_redis_cache = redis.cache self.original_redis_get = redis.get self.mock_redis_cache = AsyncMock() self.mock_redis_cache.return_value = iter([None]) self.mock_redis_get = AsyncMock(side_effect=KeyError) redis.cache = self.mock_redis_cache redis.get = self.mock_redis_get # pre add conn.add('ou=scopes,' + self.base_dn, 'organizationalUnit') conn.add('ou=users,' + self.base_dn, 'organizationalUnit') conn.add('ou=config,' + self.base_dn, 'organizationalUnit') conn.add('ou=clients,ou=config,' + self.base_dn, 'organizationalUnit') # post delete if request is not None: request.addfinalizer(self.set_teardown) # load data self.ldap = self.app.app['settings']['user_manager'] self.create_scope() self.create_client() self.create_superuser() # load extra data self.create_manager() self.create_user() self.create_group()
def create_group(self, AD_SERVER, OU_BASE, DOMAIN, BIND_USERNAME, BIND_PASSWORD, NEW_GROUP, DESCRIPTION): tlsconfig = Tls(validate=ssl.CERT_NONE) server = Server(AD_SERVER, port=636, use_ssl=True, tls=tlsconfig, get_info=ALL) print(AD_SERVER, OU_BASE, DOMAIN, BIND_USERNAME, BIND_PASSWORD, NEW_GROUP, DESCRIPTION) try: conn = Connection(server, BIND_USERNAME, BIND_PASSWORD) conn.start_tls() if not conn.bind(): return 'Bind ERROR {}'.format(conn.result) temp_group_dn = 'cn=' + NEW_GROUP + ',' + OU_BASE print(temp_group_dn) conn.add(temp_group_dn, 'group', {'description': DESCRIPTION}) if conn.result['result'] != 0: conn.unbind() return conn.result print(conn.result) except Exception as e: return 'Create Group Error : {}'.format(e) conn.unbind() return conn.result
class Test(unittest.TestCase): def setUp(self): self.connection = Connection(server=None, client_strategy=LDIF) self.connection.open() def tearDown(self): self.connection.unbind() self.assertFalse(self.connection.bound) def test_add_request_to_ldif(self): controls = list() controls.append(('2.16.840.1.113719.1.27.103.7', True, 'givenName')) controls.append(('2.16.840.1.113719.1.27.103.7', False, 'sn')) if str != bytes: # python3 controls.append(('2.16.840.1.113719.1.27.103.7', False, bytearray('\u00e0\u00e0', encoding='UTF-8'))) else: controls.append( ('2.16.840.1.113719.1.27.103.7', False, bytearray(unicode('\xe0\xe0', encoding='latin1'), encoding='UTF-8'))) # for python2 compatability controls.append( ('2.16.840.1.113719.1.27.103.7', False, 'trailingspace ')) self.connection.add(generate_dn(test_base, testcase_id, 'ldif-change-1'), 'iNetOrgPerson', { 'objectClass': 'iNetOrgPerson', 'sn': 'ldif-change-1', test_name_attr: 'ldif-change-1' }, controls=controls) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-1,' + test_base in response) self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 true: givenName' in response) self.assertTrue( 'control: 2.16.840.1.113719.1.27.103.7 false: sn' in response) self.assertTrue( 'control: 2.16.840.1.113719.1.27.103.7 false:: w6DDoA==' in response) self.assertTrue( 'control: 2.16.840.1.113719.1.27.103.7 false:: dHJhaWxpbmdzcGFjZSA=' in response) self.assertTrue('changetype: add' in response) self.assertTrue('objectClass: iNetOrgPerson' in response) self.assertTrue('sn: ldif-change-1' in response) self.assertTrue(test_name_attr + ': ldif-change-1' in response) def test_delete_request_to_ldif(self): self.connection.strategy.order = dict( delRequest=['dn:', 'changetype', 'vers']) self.connection.delete( generate_dn(test_base, testcase_id, 'ldif-change-2')) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-2,' + test_base in response) self.assertTrue('changetype: delete' in response) def test_modify_dn_request_to_ldif(self): result = self.connection.modify_dn( generate_dn(test_base, testcase_id, 'ldif-change-3'), test_name_attr + '=' + testcase_id + 'ldif-change-4,' + test_base) if isinstance(result, int): self.connection.get_response(result) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-3,' + test_base in response) self.assertTrue('changetype: moddn' in response) self.assertTrue('newrdn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-4,' + test_base in response) self.assertTrue('deleteoldrdn: 1' in response) def test_move_dn_request_to_ldif(self): result = self.connection.modify_dn( generate_dn(test_base, testcase_id, 'ldif-change-5'), test_name_attr + '=' + testcase_id + 'ldif-change-5', delete_old_dn=False, new_superior=test_moved) if isinstance(result, int): self.connection.get_response(result) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-5,' + test_base in response) self.assertTrue('changetype: modrdn' in response) self.assertTrue('newrdn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-5' in response) self.assertTrue('deleteoldrdn: 0' in response) self.assertTrue('newsuperior: ' + test_moved in response) def test_modify_add_to_ldif(self): result = self.connection.modify( generate_dn(test_base, testcase_id, 'ldif-change-6'), {'givenName': (MODIFY_ADD, ['givenname-6-modified'])}) if isinstance(result, int): self.connection.get_response(result) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-6,' + test_base in response) self.assertTrue('changetype: modify' in response) self.assertTrue('add: givenName' in response) self.assertTrue('givenName: givenname-6-modified' in response) self.assertEqual('-', response[-1]) def test_modify_replace_to_ldif(self): result = self.connection.modify( generate_dn(test_base, testcase_id, 'ldif-change-7'), {'givenName': (MODIFY_REPLACE, ['givenname-7-replaced'])}) if isinstance(result, int): self.connection.get_response(result) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-7,' + test_base in response) self.assertTrue('changetype: modify' in response) self.assertTrue('replace: givenName' in response) self.assertTrue('givenName: givenname-7-replaced' in response) self.assertEqual('-', response[-1]) def test_modify_delete_to_ldif(self): result = self.connection.modify( generate_dn(test_base, testcase_id, 'ldif-change-8'), {'givenName': (MODIFY_DELETE, ['givenname-8-deleted'])}) if isinstance(result, int): self.connection.get_response(result) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-8,' + test_base in response) self.assertTrue('changetype: modify' in response) self.assertTrue('delete: givenName' in response) self.assertTrue('givenName: givenname-8-deleted' in response) self.assertEqual('-', response[-1]) def test_multiple_modify_to_ldif(self): # from rfc 2849 example result = self.connection.modify( 'cn=Paula Jensen, ou=Product Development, dc=airius, dc=com', { 'postaladdress': (MODIFY_ADD, ['123 Anystreet $ Sunnyvale, CA $ 94086']), 'description': (MODIFY_DELETE, []), 'telephonenumber': (MODIFY_REPLACE, ['+1 408 555 1234', '+1 408 555 5678']), 'facsimiletelephonenumber': (MODIFY_DELETE, ['+1 408 555 9876']) }) if isinstance(result, int): self.connection.get_response(result) response = self.connection.response self.assertTrue('version: 1' in response) self.assertTrue( 'dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com' in response) self.assertTrue('changetype: modify' in response) self.assertTrue('delete: facsimiletelephonenumber' in response) self.assertTrue( 'facsimiletelephonenumber: +1 408 555 9876' in response) self.assertTrue('replace: telephonenumber' in response) self.assertTrue('telephonenumber: +1 408 555 1234' in response) self.assertTrue('telephonenumber: +1 408 555 5678' in response) self.assertTrue('add: postaladdress' in response) self.assertTrue( 'postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086' in response) self.assertTrue('delete: description' in response) self.assertEqual('-', response[-1])
def create_user(self, AD_SERVER, OU_BASE, DOMAIN, BIND_USERNAME, BIND_PASSWORD, NEW_USER, NEW_USER_PASWORD, DESCRIPTION): tlsconfig = Tls(validate=ssl.CERT_NONE) server = Server(AD_SERVER, port=636, use_ssl=True, tls=tlsconfig, get_info=ALL) print(AD_SERVER, OU_BASE, DOMAIN, BIND_USERNAME, BIND_PASSWORD, NEW_USER) try: conn = Connection(server, BIND_USERNAME, BIND_PASSWORD) conn.start_tls() if not conn.bind(): return 'Bind ERROR {}'.format(conn.result) temp_user_dn = 'cn=' + NEW_USER + ',' + OU_BASE print(temp_user_dn) conn.add( temp_user_dn, 'user', { 'givenName': NEW_USER, 'description': 'Create Time : ' + time.ctime(), 'company': DESCRIPTION, 'samaccountname': NEW_USER, 'userPrincipalName': NEW_USER + '@' + DOMAIN }) if conn.result['result'] != 0: conn.unbind return conn.result print(conn.result) conn.extend.microsoft.modify_password(temp_user_dn, NEW_USER_PASWORD) if conn.result['result'] != 0: conn.delete(temp_user_dn) conn.unbind return conn.result print(conn.result) conn.modify(temp_user_dn, {'userAccountControl': [(MODIFY_REPLACE, ['512'])]}) except Exception as e: return 'Create User Error : {}'.format(e) conn.unbind() return conn.result
def active_directory_connector(): server = Server(_ad_server) conn = Connection(server, user=_ad_user, password=_ad_password) conn.bind() return conn
class InventoryModule(BaseInventoryPlugin): NAME = 'adgroup' def __init__(self): super(InventoryModule, self).__init__() self._connection = None def verify_file(self, path): if super(InventoryModule, self).verify_file(path): exts = ('.yaml', '.yml') return any((path.endswith(ext) for ext in exts)) return False def parse(self, inventory, loader, path, cache=True): super(InventoryModule, self).parse(inventory, loader, path) self.config_data = self._read_config_data(path) self._create_client() self._build_inventory() def _get_option(self, option): value = self.get_option(option) if value: if option == "scope": return SCOPES.get(value) return value # attempt to auto-detect option if option == "server": value = self._find_closest_dc() if value: self.set_option("server", value) else: value = self._get_domain() if value: self.set_option("server", value) else: raise AnsibleError("Server name could not be determined") return value def _get_connection_args(self): username = self._get_option("username") password = self._get_option("password") if username: if password: return {"user": username, "password": password} else: raise AnsibleError("Username defined without a password") return {"authentication": SASL, "sasl_mechanism": "GSSAPI"} def _create_client(self): if self._connection: return self._connection server = self._get_option("server") port = self._get_option("port") base = self._get_option("base") if server: sargs = {"use_ssl": True} if port == 636 else {} ldap_server = Server(server, port=port, get_info=DSA, **sargs) cargs = self._get_connection_args() self._connection = Connection(ldap_server, **cargs) self._connection.open() self._connection.start_tls() self._connection.bind() if base is None: result = self._connection.search( search_base="", search_filter="(dnsHostName=%s)" % server, search_scope=BASE, attributes=["defaultNamingContext"]) if result: base = (self._connection.server.info. other["defaultNamingContext"][0]) self.set_option("base", base) else: raise AnsibleError("Server name could not be determined") def _get_domain(self): fqdn = socket.getfqnd() return fqdn[fqdn.find(".") + 1:] if "." in fqdn else None def _find_closest_dc(self): from multiprocessing.pool import ThreadPool as Pool def ldap_ping(args): server, cargs = args try: with Connection(Server(server, get_info=DSA), **cargs) as connection: result = connection.search( search_base="", search_filter= "(&(NtVer=\\06\\00\\00\\00)(AAC=\\00\\00\\00\\00))", search_scope=BASE, attributes=["netlogon"]) if result: if "netlogon" in connection.entries[0]: data = connection.entries[0].netlogon.value flags = struct.unpack("<i", data[4:8])[0] if flags & 0x00000080: # DS_CLOSEST_FLAG return server except LDAPSocketOpenError: return None return None # === ldap_ping if dns_resolver is None: return self._get_domain() ldap_servers = [] for server in dns_resolver.query("_ldap._tcp", "SRV"): ldap_servers.append(server) if ldap_servers: ldap_servers.sort(key=lambda x: (x.priority, x.weight)) cargs = self._get_connection_args() pool = Pool(processes=len(ldap_servers)) results = pool.map(ldap_ping, [(str(server.target)[:-1], cargs) for server in ldap_servers]) pool.close() closest = ([server for server in results if server] or (None, ))[0] if closest is None: return str(ldap_servers[0].target)[:-1] return closest def _set_variables(self, entity, values): if isinstance(values, dict): for k, v in values.items(): self.inventory.set_variable(entity, k, v) def _build_inventory(self): if self._connection is None: self._create_client() base = self._get_option("base") root_group_name = self._get_option("root group") scope = self._get_option("scope") var_attribute = self._get_option("var attribute") import_vars = var_attribute is not None xattrib = [var_attribute] if import_vars else [] if any([root_group_name.lower().startswith(v) for v in ("cn=", "ou=")]): result = self._connection.search( search_base=root_group_name, search_filter="(objectClass=group)", search_scope=BASE, attributes=["member"] + xattrib) else: result = self._connection.search( search_base=base, search_filter="(&(objectClass=group)(sAMAccountName=%s))" % root_group_name, search_scope=scope, attributes=["member"] + xattrib) if not result: return root_group = self._connection.entries[0] if "member" not in root_group: return if import_vars and var_attribute in root_group: try: raw_info = self._connection.entries[0].info.value if raw_info: info = yaml.safe_load(raw_info) self._set_variables("all", info) except yaml.scanner.ScannerError: pass members = root_group.member.values for member in members: result = self._connection.search( search_base=member, search_filter="(objectClass=*)", search_scope=BASE, attributes=["objectClass", "member", "name", "sAMAccountName" ] + xattrib) if result: entry = self._connection.entries[0] if "computer" in entry.objectClass: # Computer in root group; treat as "all" host_name = entry.sAMAccountName.value.lower() is_group = False elif "member" not in self._connection.entries[0]: continue else: is_group = True users = entry.member.values group_name = entry.sAMAccountName.value.lower() group_marker = self._get_option("group marker") if group_marker: group_name = group_name.replace(group_marker, "") self.inventory.add_group(group_name) if import_vars and var_attribute in entry: try: raw_info = entry.info.value if raw_info: info = yaml.safe_load(raw_info) if is_group: self._set_variables(group_name, info) else: self._set_variables(host_name, info) except (yaml.scanner.ScannerError, LDAPAttributeError): pass if is_group: for user in users: result = self._connection.search( search_base=user, search_filter="(objectClass=computer)", search_scope=BASE, attributes=[ "info", "member", "name", "objectClass" ] + xattrib) if result: host_name = self._connection.entries[ 0].name.value.lower() try: raw_info = entry.info.value if raw_info: info = yaml.safe_load(raw_info) self._set_variables(host_name, info) except (yaml.scanner.ScannerError, LDAPAttributeError): pass self.inventory.add_host(host_name, group=group_name) self.inventory.add_host(host_name, group="all") else: host_name = entry.name.value self.inventory.add_host(host_name, group="all")
def compare_to_ldap(sis_users, needs_sis_username=0): server = Server(host='www.xxx.yyy.zzz', port=636, use_ssl=True, get_info=NONE) # logging.info('Please enter your LDAP username: '******'myname' password = '******' attempts = 0 conn = Connection(server, user='******' + login_name + ',o=xyz', password=password) conn.bind() while conn.result['description'] == 'invalidCredentials': logging.info('Incorrect username or password. Please try again.') logging.info('Please enter your LDAP username: '******'CN=' + login_name + ',o=xyz', password=password) conn.bind() logging.info('LDAP Login successful') ldap_un_list = [] logging.info('\n') search_filter = '(objectclass=Person)' for i in range(3, 5): curr_grade = 'Grade-PK' + str(i) search_base = 'ou=' + curr_grade + ',o=xyz' logging.info('Searching ' + curr_grade) conn.search(search_base=search_base, search_filter=search_filter, search_scope=SUBTREE, attributes=['uid']) for entry in conn.entries: uid = entry['uid'].value ldap_un_list.append(uid.lower()) for i in range(0, 13): curr_grade = 'Grade-' + str(i).zfill(2) search_base = 'ou=' + curr_grade + ',o=xyz' logging.info('Searching ' + curr_grade) conn.search(search_base=search_base, search_filter=search_filter, search_scope=SUBTREE, attributes=['uid']) for entry in conn.entries: uid = entry['uid'].value ldap_un_list.append(uid.lower()) ldap_un_list.sort() # *** Add any potential chromebook enrollment accounts here if necessary. e.g., PK3 or PK4 exclusion_list = [ 'PK3', 'PK4', '00', '1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th', '11th', '12th', 'billybob' ] for name in exclusion_list: if name in ldap_un_list: ldap_un_list.remove(name) if needs_sis_username == 1: return ldap_un_list logging.info('\n' + str(len(ldap_un_list)) + ' total students in LDAP, Grades PK3-12.') with open('ldap_un_list.log', mode='w') as file: for student in ldap_un_list: file.write(student + '\n') needs_deletion = [] for student in ldap_un_list: if student in sis_users.keys(): continue needs_deletion.append(student) logging.info('\nStudents who need to be deleted from LDAP:') logging.info(needs_deletion) logging.info('\n' + str(len(needs_deletion)) + ' accounts recommended to be deleted.') needs_account = OrderedDict() for student in sis_users.keys(): conn.search(search_base='o=xyz', search_filter='(uid=' + student + ')', search_scope=SUBTREE) if len(conn.entries) > 0: continue needs_account[student] = sis_users[student] logging.info('\nStudents who need to be added to LDAP:') logging.info(needs_account.keys()) logging.info('\n' + str(len(needs_account)) + ' accounts to be created in LDAP.') if len(needs_deletion) == 0: logging.info('No accounts need to be deleted.') else: error_count = 0 # User exists in LDAP but not SIS -> we can delete them from LDAP for username in needs_deletion: conn.search(search_base='o=xyz', search_filter='(uid=' + username + ')') user = conn.entries[0].entry_dn conn.delete(user) if str(conn.result['description']) == 'success': logging.info('Success - ' + username + ' deleted.') else: logging.info('Error - ' + username + ' could not be deleted.') error_count += 1 logging.info('\n') logging.info('\nAccount deletion process completed with ' + str(error_count) + ' errors.') pass_list = create_ldap_accounts(needs_account) update_students_in_sis(needs_account, pass_list) conn.unbind()
server = Server('10.134.2.43', port=389, use_ssl=False, get_info=ALL_ATTRIBUTES) #server = Server('10.4.1.68' ,port=389, use_ssl=False, get_info=ALL_ATTRIBUTES) set_config_parameter('DEFAULT_CLIENT_ENCODING', 'utf8') BaseAD = "ou=grp_partages,ou=groupes,dc=adchpg,dc=chpg,dc=mc" #BaseeDir = "ou=grp_partages,O=chpg" Scope = 'SUBTREE' FilterAD = "(&(objectClass=Group)(!(objectClass=computer)))" FiltereDir = "(&(objectClass=Group))" AttrsAD = ['samAccountName', 'dn', 'member', 'cn'] AttrseDir = ['dn', 'member', 'cn'] conn = Connection( server, 'cn=Netonline,ou=Externes,ou=Utilisateurs,dc=adchpg,dc=chpg,dc=mc', 'Netonline@26', auto_bind=True) conn.search(search_base=BaseAD, search_filter=FilterAD, search_scope=Scope, attributes=AttrsAD) #conn = Connection(server, 'cn=netonline,ou=presta,ou=ext,o=chpg', 'Netonline@26', auto_bind=True) #conn.search(search_base=BaseeDir, search_filter=FiltereDir, search_scope=Scope, attributes=AttrseDir) print(conn.entries) #trustee_data = open('listmembreeDir-Partages.csv', 'w') trustee_data = open('listmembreAD-Partages.csv', 'w') csvwriter = csv.writer(trustee_data)
import ldap3, sys, configparser from ldap3 import Connection, ALL, core, MODIFY_REPLACE base_dn = sys.argv[1] username = sys.argv[2] password = sys.argv[3] user_dn = 'CN=' + username + ',' + base_dn config = configparser.ConfigParser() config.read(sys.path[0] + '/config/app.ini') usr = config.get('Section1', 'username') data = config.get('Section1', 'data') # LDAP connection try: ldap_connection = Connection('ldaps://ldap0319.nordstrom.net:636', usr, data, auto_bind=True) except core.exceptions.LDAPBindError as e: print("Error connecting to LDAP server: %s" % e) sys.exit(1) # Check and see if user exists user_search = ldap_connection.search(base_dn, '(&(sAMAccountName=' + username + ')(objectClass=person))', attributes=['distinguishedName']) # Check the results if not user_search: print("User", username, "not found in AD:") sys.exit(1)
def main(): parser = argparse.ArgumentParser( description= 'Query/modify DNS records for Active Directory integrated DNS via LDAP' ) parser._optionals.title = "Main options" parser._positionals.title = "Required options" #Main parameters #maingroup = parser.add_argument_group("Main options") parser.add_argument( "host", type=str, metavar='HOSTNAME', help="Hostname/ip or ldap://host:port connection string to connect to") parser.add_argument("-u", "--user", type=str, metavar='USERNAME', help="DOMAIN\\username for authentication.") parser.add_argument( "-p", "--password", type=str, metavar='PASSWORD', help="Password or LM:NTLM hash, will prompt if not specified") parser.add_argument( "--forest", action='store_true', help="Search the ForestDnsZones instead of DomainDnsZones") parser.add_argument( "--zone", help="Zone to search in (if different than the current domain)") parser.add_argument( "--print-zones", action='store_true', help= "Only query all zones on the DNS server, no other modifications are made" ) recordopts = parser.add_argument_group("Record options") recordopts.add_argument("-r", "--record", type=str, metavar='TARGETRECORD', help="Record to target (FQDN)") recordopts.add_argument( "-a", "--action", choices=['add', 'modify', 'query', 'remove', 'ldapdelete'], default='query', help="Action to perform. Options: add (add a new record), modify (" "modify an existing record), query (show existing), remove (mark record " "for cleanup from DNS cache), delete (delete from LDAP). Default: query" ) recordopts.add_argument( "-t", "--type", choices=['A'], default='A', help="Record type to add (Currently only A records supported)") recordopts.add_argument("-d", "--data", metavar='RECORDDATA', help="Record data (IP address)") recordopts.add_argument("--allow-multiple", action='store_true', help="Allow multiple A records for the same name") recordopts.add_argument("--ttl", type=int, default=180, help="TTL for record (default: 180)") args = parser.parse_args() #Prompt for password if not set authentication = None if args.user is not None: authentication = NTLM if not '\\' in args.user: print_f('Username must include a domain, use: DOMAIN\\username') sys.exit(1) if args.password is None: args.password = getpass.getpass() # define the server and the connection s = Server(args.host, get_info=ALL) print_m('Connecting to host...') c = Connection(s, user=args.user, password=args.password, authentication=authentication) print_m('Binding to host') # perform the Bind operation if not c.bind(): print_f('Could not bind with specified credentials') print_f(c.result) sys.exit(1) print_o('Bind OK') domainroot = s.info.other['defaultNamingContext'][0] if args.forest: dnsroot = 'CN=MicrosoftDNS,DC=ForestDnsZones,%s' % domainroot else: dnsroot = 'CN=MicrosoftDNS,DC=DomainDnsZones,%s' % domainroot if args.print_zones: zones = get_dns_zones(c, dnsroot) if len(zones) > 0: print_m('Found %d domain DNS zones:' % len(zones)) for zone in zones: print(' %s' % zone) # TODO: Should this be the root domain? forestroot = 'CN=MicrosoftDNS,DC=ForestDnsZones,%s' % s.info.other[ 'rootDomainNamingContext'][0] zones = get_dns_zones(c, forestroot) if len(zones) > 0: print_m('Found %d forest DNS zones:' % len(zones)) for zone in zones: print(' %s' % zone) return target = args.record if args.zone: zone = args.zone else: # Default to current domain zone = ldap2domain(domainroot) if target.lower().endswith(zone.lower()): target = target[:-(len(zone) + 1)] searchtarget = 'DC=%s,%s' % (zone, dnsroot) # print s.info.naming_contexts c.search(searchtarget, '(&(objectClass=dnsNode)(name=%s))' % ldap3.utils.conv.escape_filter_chars(target), attributes=['dnsRecord', 'dNSTombstoned', 'name']) targetentry = None for entry in c.response: if entry['type'] != 'searchResEntry': continue targetentry = entry # Check if we have the required data if args.action in ['add', 'modify', 'remove'] and not args.data: print_f( 'This operation requires you to specify record data with --data') return # Check if we need the target record to exists, and if yes if it does if args.action in ['modify', 'remove', 'delete', 'query' ] and not targetentry: print_f('Target record not found!') return if args.action == 'query': print_o('Found record %s' % targetentry['attributes']['name']) for record in targetentry['raw_attributes']['dnsRecord']: dr = DNS_RECORD(record) # dr.dump() print targetentry['dn'] print_record(dr, targetentry['attributes']['dNSTombstoned']) continue elif args.action == 'add': # Only A records for now addtype = 1 # Entry exists if targetentry: if not args.allow_multiple: for record in targetentry['raw_attributes']['dnsRecord']: dr = DNS_RECORD(record) if dr['Type'] == 1: address = DNS_RPC_RECORD_A(dr['Data']) print_f( 'Record already exists and points to %s. Use --action modify to overwrite or --allow-multiple to override this' % address.formatCanonical()) return False # If we are here, no A records exists yet record = new_record(addtype, get_next_serial(args.host, zone)) record['Data'] = DNS_RPC_RECORD_A() record['Data'].fromCanonical(args.data) print_m('Adding extra record') c.modify(targetentry['dn'], {'dnsRecord': [(MODIFY_ADD, record.getData())]}) print_operation_result(c.result) else: node_data = { 'objectCategory': 'CN=Dns-Node,CN=Schema,CN=Configuration,%s' % domainroot, 'dNSTombstoned': False, 'name': target } record = new_record(addtype, get_next_serial(args.host, zone)) record['Data'] = DNS_RPC_RECORD_A() record['Data'].fromCanonical(args.data) record_dn = 'DC=%s,%s' % (target, searchtarget) node_data['dnsRecord'] = [record.getData()] print_m('Adding new record') c.add(record_dn, ['top', 'dnsNode'], node_data) print_operation_result(c.result) elif args.action == 'modify': # Only A records for now addtype = 1 # We already know the entry exists targetrecord = None records = [] for record in targetentry['raw_attributes']['dnsRecord']: dr = DNS_RECORD(record) if dr['Type'] == 1: targetrecord = dr else: records.append(record) if not targetrecord: print_f('No A record exists yet. Use --action add to add it') targetrecord['Serial'] = get_next_serial(args.host, zone) targetrecord['Data'] = DNS_RPC_RECORD_A() targetrecord['Data'].fromCanonical(args.data) records.append(targetrecord.getData()) print_m('Modifying record') c.modify(targetentry['dn'], {'dnsRecord': [(MODIFY_REPLACE, records)]}) print_operation_result(c.result) elif args.action == 'remove': addtype = 0 if len(targetentry['raw_attributes']['dnsRecord']) > 1: print_m('Target has multiple records, removing the one specified') targetrecord = None for record in targetentry['raw_attributes']['dnsRecord']: dr = DNS_RECORD(record) if dr['Type'] == 1: tr = DNS_RPC_RECORD_A(dr['Data']) if tr.formatCanonical() == args.data: targetrecord = record if not targetrecord: print_f('Could not find a record with the specified data') return c.modify(targetentry['dn'], {'dnsRecord': [(MODIFY_DELETE, targetrecord)]}) print_operation_result(c.result) else: print_m('Target has only one record, tombstoning it') diff = datetime.datetime.today() - datetime.datetime(1601, 1, 1) tstime = int(diff.total_seconds() * 10000) # Add a null record record = new_record(addtype, get_next_serial(args.host, zone)) record['Data'] = DNS_RPC_RECORD_TS() record['Data']['entombedTime'] = tstime c.modify( targetentry['dn'], { 'dnsRecord': [(MODIFY_REPLACE, [record])], 'dNSTombstoned': [(MODIFY_REPLACE, True)] }) print_operation_result(c.result)
def main(): parser = argparse.ArgumentParser(description='Query/modify DNS records for Active Directory integrated DNS via LDAP') parser._optionals.title = "Main options" parser._positionals.title = "Required options" #Main parameters #maingroup = parser.add_argument_group("Main options") parser.add_argument("host", type=native_str,metavar='HOSTNAME',help="Hostname/ip or ldap://host:port connection string to connect to") parser.add_argument("-u","--user",type=native_str,metavar='USERNAME',help="DOMAIN\\username for authentication.") parser.add_argument("-p","--password",type=native_str,metavar='PASSWORD',help="Password or LM:NTLM hash, will prompt if not specified") parser.add_argument("--forest", action='store_true', help="Search the ForestDnsZones instead of DomainDnsZones") parser.add_argument("--legacy", action='store_true', help="Search the System partition (legacy DNS storage)") parser.add_argument("--zone", help="Zone to search in (if different than the current domain)") parser.add_argument("--print-zones", action='store_true', help="Only query all zones on the DNS server, no other modifications are made") parser.add_argument("-v", "--verbose", action='store_true', help="Show verbose info") parser.add_argument("-d", "--debug", action='store_true', help="Show debug info") parser.add_argument("-r", "--resolve", action='store_true', help="Resolve hidden recoreds via DNS") parser.add_argument("--dns-tcp", action='store_true', help="Use DNS over TCP") parser.add_argument("--include-tombstoned", action='store_true', help="Include tombstoned (deleted) records") parser.add_argument("--ssl", action='store_true', help="Connect to LDAP server using SSL") parser.add_argument("--referralhosts", action='store_true', help="Allow passthrough authentication to all referral hosts") parser.add_argument("--dcfilter", action='store_true', help="Use an alternate filter to identify DNS record types") parser.add_argument("--sslprotocol", type=native_str, help="SSL version for LDAP connection, can be SSLv23, TLSv1, TLSv1_1 or TLSv1_2") args = parser.parse_args() #Prompt for password if not set authentication = None if args.user is not None: authentication = NTLM if not '\\' in args.user: print_f('Username must include a domain, use: DOMAIN\\username') sys.exit(1) if args.password is None: args.password = getpass.getpass() # define the server and the connection s = Server(args.host, get_info=ALL) if args.ssl: s = Server(args.host, get_info=ALL, port=636, use_ssl=True) if args.sslprotocol: v = {'SSLv23' : 2, 'TLSv1' : 3, 'TLSv1_1' : 4, 'TLSv1_2' : 5} if args.sslprotocol not in v.keys(): parser.print_help(sys.stderr) sys.exit(1) s = Server(args.host, get_info=ALL, port=636, use_ssl=True, tls=Tls(validate=0, version=v[args.sslprotocol]) ) if args.referralhosts: s.allowed_referral_hosts = [('*', True)] print_m('Connecting to host...') c = Connection(s, user=args.user, password=args.password, authentication=authentication, auto_referrals=False) print_m('Binding to host') # perform the Bind operation if not c.bind(): print_f('Could not bind with specified credentials') print_f(c.result) sys.exit(1) print_o('Bind OK') domainroot = s.info.other['defaultNamingContext'][0] forestroot = s.info.other['rootDomainNamingContext'][0] if args.forest: dnsroot = 'CN=MicrosoftDNS,DC=ForestDnsZones,%s' % forestroot else: if args.legacy: dnsroot = 'CN=MicrosoftDNS,CN=System,%s' % domainroot else: dnsroot = 'CN=MicrosoftDNS,DC=DomainDnsZones,%s' % domainroot if args.print_zones: domaindnsroot = 'CN=MicrosoftDNS,DC=DomainDnsZones,%s' % domainroot zones = get_dns_zones(c, domaindnsroot, args.verbose) if len(zones) > 0: print_m('Found %d domain DNS zones:' % len(zones)) for zone in zones: print(' %s' % zone) forestdnsroot = 'CN=MicrosoftDNS,DC=ForestDnsZones,%s' % forestroot zones = get_dns_zones(c, forestdnsroot, args.verbose) if len(zones) > 0: print_m('Found %d forest DNS zones:' % len(zones)) for zone in zones: print(' %s' % zone) legacydnsroot = 'CN=MicrosoftDNS,CN=System,%s' % domainroot zones = get_dns_zones(c, legacydnsroot, args.verbose) if len(zones) > 0: print_m('Found %d legacy DNS zones:' % len(zones)) for zone in zones: print(' %s' % zone) return if args.zone: zone = args.zone else: # Default to current domain zone = ldap2domain(domainroot) searchtarget = 'DC=%s,%s' % (zone, dnsroot) print_m('Querying zone for records') sfilter = '(objectClass=*)' if not args.dcfilter else '(DC=*)' c.extend.standard.paged_search(searchtarget, sfilter, search_scope=LEVEL, attributes=['dnsRecord','dNSTombstoned','name'], paged_size=500, generator=False) targetentry = None dnsresolver = get_dns_resolver(args.host) outdata = [] for targetentry in c.response: if targetentry['type'] != 'searchResEntry': print(targetentry) continue if not targetentry['attributes']['name']: # No permission to view those records recordname = targetentry['dn'][3:targetentry['dn'].index(searchtarget)-1] if not args.resolve: outdata.append({'name':recordname, 'type':'?', 'value': '?'}) if args.verbose: print_o('Found hidden record %s' % recordname) else: # Resolve A query try: res = dnsresolver.query('%s.%s.' % (recordname, zone), 'A', tcp=args.dns_tcp, raise_on_no_answer=False) except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.resolver.Timeout, dns.name.EmptyLabel) as e: if args.verbose: print_f(str(e)) print_m('Could not resolve node %s (probably no A record assigned to name)' % recordname) outdata.append({'name':recordname, 'type':'?', 'value': '?'}) continue if len(res.response.answer) == 0: print_m('Could not resolve node %s (probably no A record assigned to name)' % recordname) outdata.append({'name':recordname, 'type':'?', 'value': '?'}) continue if args.verbose: print_o('Resolved hidden record %s' % recordname) for answer in res.response.answer: try: outdata.append({'name':recordname, 'type':RECORD_TYPE_MAPPING[answer.rdtype], 'value': str(answer[0])}) except KeyError: print_m('Unexpected record type seen: {}'.format(answer.rdtype)) else: recordname = targetentry['attributes']['name'] if args.verbose: print_o('Found record %s' % targetentry['attributes']['name']) # Skip tombstoned records unless requested if targetentry['attributes']['dNSTombstoned'] and not args.include_tombstoned: continue for record in targetentry['raw_attributes']['dnsRecord']: dr = DNS_RECORD(record) # dr.dump() # print targetentry['dn'] if args.debug: print_record(dr, targetentry['attributes']['dNSTombstoned']) if dr['Type'] == 1: address = DNS_RPC_RECORD_A(dr['Data']) outdata.append({'name':recordname, 'type': RECORD_TYPE_MAPPING[dr['Type']], 'value': address.formatCanonical()}) if dr['Type'] in [a for a in RECORD_TYPE_MAPPING if RECORD_TYPE_MAPPING[a] in ['CNAME', 'NS']]: address = DNS_RPC_RECORD_NODE_NAME(dr['Data']) outdata.append({'name':recordname, 'type':RECORD_TYPE_MAPPING[dr['Type']], 'value': address[list(address.fields)[0]].toFqdn()}) elif dr['Type'] == 28: address = DNS_RPC_RECORD_AAAA(dr['Data']) outdata.append({'name':recordname, 'type':RECORD_TYPE_MAPPING[dr['Type']], 'value': address.formatCanonical()}) elif dr['Type'] not in [a for a in RECORD_TYPE_MAPPING if RECORD_TYPE_MAPPING[a] in ['A', 'AAAA,' 'CNAME', 'NS']]: if args.debug: print_m('Unexpected record type seen: {}'.format(dr['Type'])) continue print_o('Found %d records' % len(outdata)) with codecs.open('records.csv', 'w', 'utf-8') as outfile: outfile.write('type,name,value\n') for row in outdata: outfile.write('{type},{name},{value}\n'.format(**row))
from ldap3.core.exceptions import LDAPCursorError import xlwt #DN = [email protected], secret=password, un=username # One of those scripts # server_name = 'HOST' domain_name = 'DOMAIN' user_name = '*****@*****.**' password = '******' server = Server(server_name, get_info=ALL) conn = Connection(server, user=user_name, password=password, auto_bind=True) # say rickman.co.ne # dc = rickman # dc = co # dc = ne # OU = Object to be authenticated, ie computer, user, service, bot etc conn.search('OU=Users, dc=rickman,dc=co,dc=ne'.format(domain_name), '(&(objectCategory=user))', attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES]) print("**************************ALL ATTRIBUTES**************************") print("") print(conn.entries) print("*******************SOME ATTTR*********************************") format_string = '{:25} {:30} {:10} {:10} {:20} {}' print(
def change_password(request): username = password = console = '' if request.GET: if request.session.has_key('username'): username1 = request.session['username'] username = request.GET.get('username') password = request.GET.get('password') return render_to_response('changepassword.html', { 'password': password, 'username': username }) else: return redirect('login.views.loginpage') if request.POST: if request.session.has_key('username'): username1 = request.session['username'] username = request.POST.get('username') password = request.POST.get('currentpassword') new_password = request.POST.get('newpassword') new_password1 = str(new_password) user_name = username + '@' + settings.DOMAIN_NAME password = password try: s = Server(settings.LDAP_SERVER[0], port=settings.LDAP_SERVER_PORT, use_ssl=settings.LDAP_SSL, get_info=ALL) conn = Connection(s, user=user_name, password=password, auto_bind=True) conn.unbind() conn = bind() dn = ("cn=%s," + settings.WINDOWS_SERVER_USERPATH + "," + settings.WINDOWS_SERVER_DOMAINPATH) % username unicode_pass = unicode('"' + new_password1 + '"', 'iso-8859-1') encoded_pass = unicode_pass.encode('utf-16-le') conn.modify(dn, {'unicodePwd': [(MODIFY_REPLACE, [encoded_pass])]}) conn.modify(dn, {'unicodePwd': [(MODIFY_REPLACE, [encoded_pass])]}) status = conn.result['description'] userlog.info("%s change password ", username) # status='success' if status == 'success': return redirect('login.views.loginpage') else: return render_to_response( 'changepassword.html', { 'password': password, 'username': username, 'status': status }) except ldap3.core.exceptions.LDAPBindError: status = 'worng current password' userlog.error("%s change password %s", username, status) return render_to_response('changepassword.html', { 'password': password, 'username': username, 'status': status }) except ldap3.core.exceptions.LDAPSocketOpenError: try: s = Server(settings.LDAP_SERVER[1], port=settings.LDAP_SERVER_PORT, use_ssl=settings.LDAP_SSL, get_info=ALL) conn = Connection(s, user=user_name, password=password, auto_bind=True) conn.unbind() conn = bind() dn = ("cn=%s," + settings.WINDOWS_SERVER_USERPATH + "," + settings.WINDOWS_SERVER_DOMAINPATH) % username unicode_pass = unicode('"' + new_password1 + '"', 'iso-8859-1') encoded_pass = unicode_pass.encode('utf-16-le') conn.modify( dn, {'unicodePwd': [(MODIFY_REPLACE, [encoded_pass])]}) conn.modify( dn, {'unicodePwd': [(MODIFY_REPLACE, [encoded_pass])]}) status = conn.result['description'] userlog.info("%s change password ", username) # status='success' if status == 'success': return redirect('login.views.loginpage') else: return render_to_response( 'changepassword.html', { 'password': password, 'username': username, 'status': status }) except ldap3.core.exceptions.LDAPBindError: status = 'worng current password' userlog.error("%s change password %s", username, status) return render_to_response( 'changepassword.html', { 'password': password, 'username': username, 'status': status }) except ldap3.core.exceptions.LDAPSocketOpenError: status = 'windows active directory not available' userlog.error("%s change password %s", username, status) return redirect('login.views.loginpage')
DEFAULT_FROM_EMAIL = mailaddress #设置发件人 else: pass except Exception as e: print(e) try: ldap3configtion = getldap3configtion() if ldap3configtion: if int(ldap3configtion['use_ssl']) == 1: use_ssl = True else: use_ssl = False ldap3Server = Server(ldap3configtion['server'], get_info=ALL, use_ssl=use_ssl) password = encrypt_and_decode().decrypted_text(ldap3configtion['password']) ldap3RESTARTABLE = Connection(server=ldap3Server, user=ldap3configtion['user'], password=password, auto_bind=True, client_strategy=RESTARTABLE) ladp3search_base=ldap3configtion['search_base'] ladp3search_server=ldap3configtion['server'] ladp3search_domain=ldap3configtion['domain'].split('.')[0] else: ldap3RESTARTABLE='None' ladp3search_base='None' ladp3search_server='None' ladp3search_domain = 'None' except Exception as e: ldap3RESTARTABLE = 'None' ladp3search_base = 'None' ladp3search_server = 'None' ladp3search_domain = 'None' returnadminusernamevalue = 'adminportal'
def audit_domain_admins(self): """Returns a list of unauthorized domain admins. Keyword Arguments: None Returns: self.bad_domain_admins - A list of user account names and descriptionsthat are not authorized to have domain admin privileges. Raises: OSError - Occurs when the script is unable to locate or open the configuration file. LDAPExceptionError - Occurs when the LDAP3 functions generate an error. The base class for all LDAPExcetionErrors is used so that the log.exception call will catch the detailed exception while not missing any potential exceptions.""" # Retrieving information from the configuration file. config = ConfigParser() try: config.read(self.conf) except OSError: self.log.exception('Unable to open configuration file.') exit(1) ldap_url = config['ldap']['url'] ldap_bind_dn = config['ldap']['bind_dn'] adm_dn = config['ldap']['adm_dn'] # Creating list of approved admins. approved_admins = [] _file = open(config['ldap']['domain_admins'], 'r') for entry in _file: approved_admins.append(entry.strip('\n')) # Getting credentials from SCSS. ldap_bind_secret = get_credentials({ 'api_key': config['ldap']['scss_api'], 'otp': config['ldap']['scss_otp'], 'userid': config['ldap']['scss_user'], 'url': config['ldap']['scss_url'] }) # Creating variables to use later. admin_list = [] admin_groups = [] # Connecting to LDAP. tls_config = Tls(validate=CERT_NONE, version=PROTOCOL_TLSv1_2) server = Server(ldap_url, use_ssl=True, tls=tls_config) try: conn = Connection(server, user=ldap_bind_dn, password=ldap_bind_secret, auto_bind=True) except LDAPExceptionError: self.log.exception('Error occurred connecting to LDAP server.') self.log.debug('Successfully connected to LDAP server: %s', ldap_url) # Getting admins builtin_admins = conn.extend.standard.paged_search( adm_dn, '(objectClass=group)', search_scope=SUBTREE, attributes=['member'], paged_size=50, generator=False) # Determining if the built-in admininstrator group member is a # group or a user. If it is a group, enumerating that groups # members as well. ldap_filter = '(|(objectClass=group)(objectClass=user))' for builtin_admin in builtin_admins[0]['attributes']['member']: search_base = builtin_admin admin_data = conn.extend.standard.paged_search( search_base, ldap_filter, BASE, attributes=[ 'sAMAccountName', 'distinguishedName', 'objectClass', 'description' ], paged_size=100, generator=False) # Checking to see if the group member is a group. if 'group' in admin_data[0]['attributes']['objectClass']: admin_groups.append( admin_data[0]['attributes']['distinguishedName']) # Checking to see if the group member is a user. elif 'user' in admin_data[0]['attributes']['objectClass']: admin_list.append({ 'name': admin_data[0]['attributes']['sAMAccountName'], 'desc': admin_data[0]['attributes']['description'][0], }) # Retrieving nested group information. If the group member is # a user, we append it to admin_list. If the group member is # a group, we append it to admin_groups. This process is # repeated until there are no more groups (we ahve a list of # only users). while len(admin_groups) > 0: entry = admin_groups.pop(0) admin_data = conn.extend.standard.paged_search( entry, ldap_filter, BASE, attributes=[ 'sAMAccountName', 'distinguishedName', 'objectClass', 'description', 'member' ], paged_size=100, generator=False) # Checking to see if the member is a user. If it is not # already in the admin_list, append it to the admin_list. if 'user' in admin_data[0]['attributes']['objectClass']: admin_data = { 'name': admin_data[0]['attributes']['sAMAccountName'], 'desc': admin_data[0]['attributes']['description'][0] } if admin_data not in admin_list: admin_list.append(admin_data) # Checking to see if the group member is a group. elif 'group' in admin_data[0]['attributes']['objectClass']: for member in admin_data[0]['attributes']['member']: admin_groups.append(member) # Unbinding ldap object. conn.unbind() # Determining if admin is approved or not. for admin in admin_list: if admin['name'] not in approved_admins: self.bad_domain_admins.append(admin) return self.bad_domain_admins
def ldap_auth(self, username, password, search_base, search_filter='cn'): if not self.ldap_server_test(): return False, None, None conn = Connection(self.ldap_server, user=self._ldap_admin_dn, password=self._ldap_admin_password, check_names=True, lazy=False, raise_exceptions=False) conn.open() conn.bind() res = conn.search(search_base=search_base, search_filter='({}={})'.format(search_filter, username), search_scope=SUBTREE, attributes=['cn', 'givenName', 'email', 'mail', 'sAMAccountName'], paged_size=5) if res: entry = conn.response[0] dn = entry['dn'] attr_dict = entry['attributes'] # check password by dn try: conn2 = Connection(self.ldap_server, user=dn, password=password, check_names=True, lazy=False, raise_exceptions=False) conn2.bind() if conn2.result["description"] == "success": if attr_dict["email"]: email = attr_dict["email"][0] elif attr_dict["mail"]: email = attr_dict["mail"][0] else: email = None return True, attr_dict["cn"][0], email else: print("auth fail") return False, None, None except Exception as e: print("auth fail {}".format(e)) return False, None, None else: return False, None, None
def get_no_pwd_exp(self): """Retrieves users with no password expiration. Keyword Arguments: None. Returns: self.no_pwd_exp - A list of user accounts that do not have a password expiration. Raises: OSError - Occurs when the script is unable to locate or open the configuration file. LDAPExceptionError - Occurs when the LDAP3 functions generate an error. The base class for all LDAPExcetionErrors is used so that the log.exception call will catch the detailed exception while not missing any potential exceptions.""" # Obtaining configuration information. config = ConfigParser() try: config.read(self.conf) except OSError: self.log.exception( 'Fatal Error: Unable to open configuration file.') exit(1) ldap_url = config['ldap']['url'] ldap_bind_dn = config['ldap']['bind_dn'] search_ou = config['ldap']['search_ou'].split('|') ldap_bind_secret = get_credentials({ 'api_key': config['ldap']['scss_api'], 'otp': config['ldap']['scss_otp'], 'userid': config['ldap']['scss_user'], 'url': config['ldap']['scss_url'] }) # Connecting to LDAP. Raising an exception with logging if the # connection is unsuccessful. start = time() tls_config = Tls(validate=CERT_NONE, version=PROTOCOL_TLSv1_2) server = Server(ldap_url, use_ssl=True, tls=tls_config) try: conn = Connection(server, user=ldap_bind_dn, password=ldap_bind_secret, auto_bind=True) except LDAPExceptionError: self.log.exception('Error occurred connecting to LDAP server.') self.log.debug('Successfully connected to LDAP server: %s', ldap_url) raw_user_data = [] # Searching LDAP for users that are in the OUs (and all sub-OUs) # specified in config['ldap']['search_ou']. ldap_filter = ('(&(objectClass=user)(objectCategory=CN=Person,' + 'CN=Schema,CN=Configuration,DC=24hourfit,DC=com))') for ou in search_ou: user_data = conn.extend.standard.paged_search( ou, ldap_filter, search_scope=SUBTREE, attributes=[ 'sAMAccountName', 'userAccountControl', 'passwordLastChange' ], paged_size=500, ) for raw_data in user_data: raw_user_data.append(raw_data['raw_attributes']) # Checking to see if each user account has their password set # to never expire based on the value of the userAccountControl # attribute in AD. If the user has their password set to never # expire, append a dictionary containing their SAM account # name and last password change date to a list. for data in raw_user_data: acct_name = data['sAMAccountName'][0].decode().lower() uac = data['userAccountControl'][0] last_pwd_change = data['passwordLastChange'][0] if int(uac) >= 66048 and int(uac) <= 66096: self.no_pwd_exp.append({ 'name': acct_name, 'last_pwd_change': last_pwd_change }) self.log.info('%s has their password set to never expire', acct_name) self.log.info('Password expiration policy audit complete.') # Unbinding the LDAP object as a good house cleaning measure. conn.unbind() end = time() _elapsed = end - start elapsed = int(round(_elapsed, 0)) self.log.debug('Peformed password expiration audit in %d seconds', elapsed) return self.no_pwd_exp
def ldap_auth_v2(self, username, password, search_base, search_filter='cn'): if not self.ldap_server_test(): return False, None, None conn = Connection(self.ldap_server, user=self._ldap_admin_dn, password=self._ldap_admin_password, check_names=True, lazy=False, raise_exceptions=False) conn.open() conn.bind() res = conn.search(search_base=search_base, search_filter=f'({search_filter}={username})', search_scope=SUBTREE, attributes=[search_filter, 'email', 'mail'], paged_size=5) if not res: return False, None, None entry = conn.response[0] dn = entry['dn'] attr_dict = entry['attributes'] # check password by dn try: conn2 = Connection(self.ldap_server, user=dn, password=password, check_names=True, lazy=False, raise_exceptions=False) conn2.bind() if conn2.result["description"] == "success": try: if 'email' in attr_dict and isinstance(attr_dict["email"], list) and attr_dict["email"]: email = attr_dict["email"][0] elif 'email' in attr_dict and not isinstance(attr_dict["email"], list) and attr_dict["email"]: email = attr_dict["email"] elif 'mail' in attr_dict and isinstance(attr_dict["mail"], list) and attr_dict["mail"]: email = attr_dict["mail"][0] elif 'mail' in attr_dict and not isinstance(attr_dict["mail"], list) and attr_dict["mail"]: email = attr_dict["mail"] else: email = None except Exception as err: print(f"email fail, {err}") email = None return True, attr_dict[search_filter][0], email else: print("auth fail") return False, None, None except Exception as e: print("auth fail {}".format(e)) return False, None, None
class ChangeGluuHostname: def __init__(self, old_host, new_host, cert_city, cert_mail, cert_state, cert_country, ldap_password, os_type, ip_address, gluu_version, server='localhost', local=False): self.old_host = old_host self.new_host = new_host self.ip_address = ip_address self.cert_city = cert_city self.cert_mail = cert_mail self.cert_state = cert_state self.cert_country = cert_country self.server = server self.ldap_password = ldap_password self.os_type = os_type self.gluu_version = gluu_version self.local = local self.base_inum = None self.appliance_inum = None def startup(self): if local: ldap_server = 'localhost' else: ldap_server = self.server ldap_server = Server("ldaps://{}:1636".format(self.server), use_ssl=True) self.conn = Connection(ldap_server, user="******", password=self.ldap_password) r = self.conn.bind() if not r: print "Can't conect to LDAP Server" return False self.container = '/opt/gluu-server-{}'.format(self.gluu_version) if not self.local: print "NOT LOCAL?" sys.path.append("..") from clustermgr.core.remote import RemoteClient self.c = RemoteClient(self.server) self.c.startup() else: self.c = FakeRemote() if os.path.exists('/etc/gluu/conf/ox-ldap.properties'): self.container = '/' self.c.fake_remote = True self.installer = Installer(self.c, self.gluu_version, self.os_type) self.appliance_inum = self.get_appliance_inum() self.base_inum = self.get_base_inum() return True def get_appliance_inum(self): self.conn.search(search_base='ou=appliances,o=gluu', search_filter='(objectclass=*)', search_scope=SUBTREE, attributes=['inum']) for r in self.conn.response: if r['attributes']['inum']: return r['attributes']['inum'][0] def get_base_inum(self): self.conn.search(search_base='o=gluu', search_filter='(objectclass=gluuOrganization)', search_scope=SUBTREE, attributes=['o']) for r in self.conn.response: if r['attributes']['o']: return r['attributes']['o'][0] def change_appliance_config(self): print "Changing LDAP Applience configurations" config_dn = 'ou=configuration,inum={},ou=appliances,o=gluu'.format( self.appliance_inum) for dns, cattr in ( ('', 'oxIDPAuthentication'), ('oxauth', 'oxAuthConfDynamic'), ('oxidp', 'oxConfApplication'), ('oxtrust', 'oxTrustConfApplication'), ): if dns: dn = 'ou={},{}'.format(dns, config_dn) else: dn = 'inum={},ou=appliances,o=gluu'.format(self.appliance_inum) self.conn.search(search_base=dn, search_filter='(objectClass=*)', search_scope=BASE, attributes=[cattr]) config_data = json.loads( self.conn.response[0]['attributes'][cattr][0]) for k in config_data: kVal = config_data[k] if type(kVal) == type(u''): if self.old_host in kVal: kVal = kVal.replace(self.old_host, self.new_host) config_data[k] = kVal config_data = json.dumps(config_data) self.conn.modify(dn, {cattr: [MODIFY_REPLACE, config_data]}) def change_clients(self): print "Changing LDAP Clients configurations" dn = "ou=clients,o={},o=gluu".format(self.base_inum) self.conn.search(search_base=dn, search_filter='(objectClass=oxAuthClient)', search_scope=SUBTREE, attributes=[ 'oxAuthPostLogoutRedirectURI', 'oxAuthRedirectURI', 'oxClaimRedirectURI', ]) result = self.conn.response[0]['attributes'] dn = self.conn.response[0]['dn'] for atr in result: for i in range(len(result[atr])): changeAttr = False if self.old_host in result[atr][i]: changeAttr = True result[atr][i] = result[atr][i].replace( self.old_host, self.new_host) self.conn.modify(dn, {atr: [MODIFY_REPLACE, result[atr]]}) def change_uma(self): print "Changing LDAP UMA Configurations" for ou, cattr in ( ('resources', 'oxResource'), ('scopes', 'oxId'), ): dn = "ou={},ou=uma,o={},o=gluu".format(ou, self.base_inum) self.conn.search(search_base=dn, search_filter='(objectClass=*)', search_scope=SUBTREE, attributes=[cattr]) result = self.conn.response for r in result: for i in range(len(r['attributes'][cattr])): changeAttr = False if self.old_host in r['attributes'][cattr][i]: r['attributes'][cattr][i] = r['attributes'][cattr][ i].replace(self.old_host, self.new_host) self.conn.modify( r['dn'], {cattr: [MODIFY_REPLACE, r['attributes'][cattr]]}) def change_httpd_conf(self): print "Changing httpd configurations" if 'CentOS' in self.os_type: httpd_conf = os.path.join(self.container, 'etc/httpd/conf/httpd.conf') https_gluu = os.path.join(self.container, 'etc/httpd/conf.d/https_gluu.conf') conf_files = [httpd_conf, https_gluu] elif 'Ubuntu' in self.os_type: https_gluu = os.path.join( self.container, 'etc/apache2/sites-available/https_gluu.conf') conf_files = [https_gluu] for conf_file in conf_files: result, fileObj = self.c.get_file(conf_file) if result: config_text = fileObj.read() config_text = config_text.replace(self.old_host, self.new_host) self.c.put_file(conf_file, config_text) def create_new_certs(self): print "Creating certificates" cmd_list = [ '/usr/bin/openssl genrsa -des3 -out /etc/certs/{0}.key.orig -passout pass:secret 2048', '/usr/bin/openssl rsa -in /etc/certs/{0}.key.orig -passin pass:secret -out /etc/certs/{0}.key', '/usr/bin/openssl req -new -key /etc/certs/{0}.key -out /etc/certs/{0}.csr -subj ' '"/C={4}/ST={5}/L={1}/O=Gluu/CN={2}/emailAddress={3}"'.format( '{0}', self.cert_city, self.new_host, self.cert_mail, self.cert_country, self.cert_state), '/usr/bin/openssl x509 -req -days 365 -in /etc/certs/{0}.csr -signkey /etc/certs/{0}.key -out /etc/certs/{0}.crt', 'chown root:gluu /etc/certs/{0}.key.orig', 'chmod 700 /etc/certs/{0}.key.orig', 'chown root:gluu /etc/certs/{0}.key', 'chmod 700 /etc/certs/{0}.key', ] cert_list = [ 'httpd', 'asimba', 'idp-encryption', 'idp-signing', 'shibIDP', 'saml.pem' ] for crt in cert_list: for cmd in cmd_list: cmd = cmd.format(crt) print self.installer.run(cmd) if not crt == 'saml.pem': del_key = ( '/opt/jre/bin/keytool -delete -alias {}_{} -keystore ' '/opt/jre/jre/lib/security/cacerts -storepass changeit' ).format(self.old_host, crt) r = self.installer.run(del_key) #if r[1]: # print "Info:", r[1] #if r[2]: # print "** ERROR:", r[2] add_key = ( '/opt/jre/bin/keytool -import -trustcacerts -alias ' '{0}_{1} -file /etc/certs/{2}.crt -keystore ' '/opt/jre/jre/lib/security/cacerts -storepass changeit -noprompt' ).format(self.new_host, crt, crt) r = self.installer.run(add_key) #if r[1]: # print "Info:", r[1] #if r[2]: # print "** ERROR:", r[2] saml_crt_old_path = os.path.join(self.container, 'etc/certs/saml.pem.crt') saml_crt_new_path = os.path.join(self.container, 'etc/certs/saml.pem') self.c.rename(saml_crt_old_path, saml_crt_new_path) self.installer.run('chown jetty:jetty /etc/certs/oxauth-keys.*') def change_host_name(self): print "Changing hostname" hostname_file = os.path.join(self.container, 'etc/hostname') print self.c.put_file(hostname_file, self.new_host) def modify_etc_hosts(self): print "Modifying /etc/hosts" hosts_file = os.path.join(self.container, 'etc/hosts') r = self.c.get_file(hosts_file) if r[0]: old_hosts = r[1] news_hosts = modify_etc_hosts([(self.new_host, self.ip_address)], old_hosts, self.old_host) print self.c.put_file(hosts_file, news_hosts)
from ldap3 import Server, Connection, ALL server = Server('ipa.demo1.freeipa.org') conn = Connection(server) conn.bind() # Create a container for new entries conn.add('ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org', 'organizationalUnit') # True # Add a new user conn.add('cn=b.young,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org', 'inetOrgPerson', { 'Name': 'Fatma', 'sn': 'Young', 'password': '******', 'telephoneNumber': 1111 }) # True # # Looking at the schema for the inetOrgPerson object class we find that there are no mandatory attributes: # server.schema.object_classes['inetOrgPerson'] # Object class: 2.16.840.1.113730.3.2.2 # Short name: inetOrgPerson # Superior: organizationalPerson # May contain attributes: audio, businessCategory, carLicense, departmentNumber, displayName, employeeNumber, employeeType, givenName, homePhone, homePostalAddress, initials, jpegPhoto, labeledURI, mail, manager, mobile, o, pager, photo, roomNumber, secretary, uid, userCertificate, x500UniqueIdentifier, preferredLanguage, userSMIMECertificate, userPKCS12 # Extensions: # X-ORIGIN: RFC 2798 # # # The inetOrgPerson object class is a subclass of the organizationalPerson object that again doesn’t include any mandatory attributes: # >>> server.schema.object_classes['organizationalPerson'] # Object class: 2.5.6.7 # Short name: organizationalPerson
def connectLDAP(self): self.ldap = Connection(self.ldaps_url, user=self.username, password=self.password, auto_bind=True) self.logger.info(self.ldap)
class Generator: def __init__(self, configFile, hostFile, owner): self.configFile = configFile self.hostFile = hostFile self.owner = owner self.initLogging() self.initialise() self.connectLDAP() self.processHostFile() self.disconnectLDAP() def initialise(self): parser = configparser.ConfigParser() with open(self.configFile) as f: lines = '[top]\n' + f.read( ) # hack, do not want [top] in config file, so add it here parser.read_string(lines) # we expect certain entries in the config file, or we will bail. There are no defaults parser = parser['top'] self.setConfig('ldaps_url', parser) self.setConfig('username', parser) self.setConfig('password', parser) self.setConfig('realm', parser) self.setConfig('service_password', parser) self.setConfig('base_dn', parser) def initLogging(self): self.logger = logging.getLogger('create-service-user') self.logger.setLevel( logging.DEBUG) # change to INFO or DEBUG for more output handler = logging.StreamHandler() handler.setLevel(logging.INFO) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) self.logger.addHandler(handler) def setConfig(self, key, parser): if key not in parser: self.logger.error(f"Cannot find {key} in config file. Aborting") sys.exit(2) self.__setattr__(key, parser[key]) self.logger.info(f"{key} : {parser[key]}") def connectLDAP(self): self.ldap = Connection(self.ldaps_url, user=self.username, password=self.password, auto_bind=True) self.logger.info(self.ldap) def archiveAndDeleteFiles(self, files): with zipfile.ZipFile(f"{self.owner}.zip", "w") as archive: for f in files: archive.write(f) for f in files: p = Path(f) p.unlink() def processHostFile(self): with open(self.hostFile) as f: content = f.read() # split into lines lines = content.split("\n") files = [] for line in lines: if line != "": entries = line.split(",") principal = entries[0] host = entries[1] print(f"{principal} --> {host}") (service_name, filename) = self.createServiceUser(principal, host) self.create_keytab(service_name, filename) files.append(filename) self.archiveAndDeleteFiles(files) def createServiceUser(self, principal, host): short_host = host.split('.')[0] cn = f"{principal} {short_host}" dn = f"CN={cn},{self.base_dn}" service_name = f"{principal}/{host}" user_principal_name = f"{service_name}@{self.realm}" user_attrs = {} user_attrs['objectClass'] = [ 'top', 'person', 'organizationalPerson', 'user' ] user_attrs['cn'] = cn user_attrs['accountExpires'] = '0' user_attrs['userPrincipalName'] = user_principal_name user_attrs['servicePrincipalName'] = service_name self.logger.info(user_attrs) self.ldap.add(dn, attributes=user_attrs) self.logger.info(self.ldap.result) # set the password self.ldap.extend.microsoft.modify_password(dn, self.service_password) self.logger.info(self.ldap.result) # set the account active and password non-expiring self.ldap.modify(dn, {"userAccountControl": [('MODIFY_REPLACE', 66048)]}) self.logger.info(self.ldap.result) filename = f"{principal}-{short_host}.keytab" return (service_name, filename) def create_keytab(self, service_name, filename): # expects ktutil to be installed in the path encryptions = ["aes256-cts", "aes128-cts", "rc4-hmac"] prompt = "ktutil: " child = pexpect.spawn("ktutil") for encryption in encryptions: cmd = f"addent -password -p {service_name} -k 1 -e {encryption}" child.expect(prompt) child.sendline(cmd) child.expect("Password for .*:") child.sendline(self.service_password) child.expect(prompt) child.sendline(f"write_kt {filename}") child.expect(prompt) child.sendline("q") def disconnectLDAP(self): self.ldap.unbind()