def main():
    """sync AD and WX Teams team membership"""
    with open(CONFIG_FILE, 'r') as config_file:
        config_params = yaml.full_load(config_file)

    wx_config = config_params['wxteams']
    wx_token = wx_config['auth_token']

    ldap_config = config_params['ldap']
    ldap_host = ldap_config['server']
    ldap_user = ldap_config['user']
    ldap_password = ldap_config['password']
    ldap_basedn = ldap_config['basedn']
    ldap_basedn_groups = ldap_config['basedn_groups']

    ldap_basedn_len = len(ldap_basedn)

    wx_teamquery = input('Please enter name of the team to examine: ')

    print('\nBuilding Webex Teams team list, please wait...', end='')
    api = WebexTeamsAPI(access_token=wx_token)
    wx_team_fulllist = list(api.teams.list(type='group'))
    print_done()

    # Populate list of query matches from full list, case insensitive
    wx_team_matchlist = [{'name': wx_team.name, 'id': wx_team.id}
                         for wx_team in wx_team_fulllist
                         if wx_teamquery.upper() in wx_team.name.upper()]


    if not wx_team_matchlist:
        bad_choice()

    # Finalize team list
    elif len(wx_team_matchlist) > 1:
        # multiple matches found, present user with choice
        for count, wx_team in enumerate(wx_team_matchlist, 1):
            print(f'{count}: {wx_team["name"]}')

        try:
            team_number = int(input('\nPlease enter number of team to compare: '))
        except ValueError:
            bad_choice()

        if team_number >= 0 and team_number < len(wx_team_matchlist)+1:
            team_number -= 1
        else:
            bad_choice()

    else:
        # one match found, use it
        team_number = 0

    # team selected
    if team_number >= 0:
        wx_team_match = {'name': wx_team_matchlist[team_number]['name'],
                         'id': wx_team_matchlist[team_number]['id']}

    else:
        bad_choice()

    # Catalogue team members
    if confirmed(f'Webex Teams \"{wx_team_match["name"]}\" team selected, are you sure?'):
        print(f'Gathering details on \"{wx_team_match["name"]}\" team...', end='')
        wx_team_members = list(api.team_memberships.list(teamId=wx_team_match['id']))
        print_done()
    else:
        bad_choice()


    ad_dl_query = input_with_default('Please enter name of AD DL to compare against: ',
                                     wx_teamquery)

    # Open LDAP connection to Active Directory
    print(f'Connecting to AD...', end='')
    server = ldap3.Server(ldap_host, use_ssl=True)
    connection = ldap3.Connection(server,
                                  user=ldap_user,
                                  password=ldap_password,
                                  authentication=ldap3.NTLM,
                                  auto_bind=True)
    print_done()

    # set up OU search
    query_parameters = {'search_base': ldap_basedn_groups,
                        'search_filter': f'(&({LDAPFILTER_GROUP})(displayName=*{ad_dl_query}*))',
                        'paged_size': LDAP_PAGE_SIZE,
                        'attributes': LDAP_GROUP_ATTRIBUTES}

    print(f'Querying AD groups...', end='')
    connection.search(**query_parameters)
    print_done()

    ad_dl_matchlist = [{'dn': entry.entry_dn, **entry.entry_attributes_as_dict}
                       for entry in connection.entries]

    if not ad_dl_matchlist:
        bad_choice()

    elif len(ad_dl_matchlist) > 1:
        # multiple matches found, present user with choice
        for count, ad_dl in enumerate(ad_dl_matchlist, 1):
            print(f'{count}: {ad_dl["displayName"][0]} ({ad_dl["dn"]})')

        try:
            dl_number = int(input('\nPlease enter number of DL to compare: '))
        except ValueError:
            bad_choice()

        if dl_number >= 0 and dl_number < len(ad_dl_matchlist)+1:
            dl_number -= 1
        else:
            bad_choice()

    else:
        # one match found, use it
        dl_number = 0

    # DL selected
    if dl_number >= 0:
        ad_dl_match = {'dn': ad_dl_matchlist[dl_number]['dn'],
                       'displayName': ad_dl_matchlist[dl_number]['displayName'][0]}
    else:
        bad_choice()

    if confirmed(f'AD group \"{ad_dl_match["displayName"]}\" selected, are you sure?'):
        ad_dl_userlist = list()
        query_parameters = {'search_base': ad_dl_match['dn'],
                            'search_filter': f'({LDAPFILTER_GROUP})',
                            'paged_size': LDAP_PAGE_SIZE,
                            'attributes': ['member']}
        print(f'Querying AD group membership...', end='')
        connection.search(**query_parameters)
        print_done()

        for member in connection.entries[0].member.values:
            print_status(f'Gathering details on {member[:(len(member)-ldap_basedn_len-1)]}')
            query_parameters = {'search_base': member,
                                'search_filter': LDAPFILTER_USER,
                                'paged_size': LDAP_PAGE_SIZE,
                                'attributes': LDAP_USER_ATTRIBUTES}
            connection.search(**query_parameters)
            if connection.entries:
                attributes = connection.entries[0]
                created = attributes.whenCreated.values[0]
                ad_dl_userlist.append({'name': attributes.displayName.values[0],
                                       'email': attributes.mail.values[0].lower(),
                                       'created': f'{created.year}-{created.month}-{created.day}'})

        print_status(' done.')

    else:
        bad_choice()

    # Buid list of AD user to add to team
    wx_team_additions = list()
    for ad_user in ad_dl_userlist:
        if not any(wx_user.personEmail.lower() == ad_user["email"] for wx_user in wx_team_members):
            if confirmed(f'AD user \"{ad_user["name"]}\" ({ad_user["created"]}) ' +
                         f'not in \"{wx_team_match["name"]}\" team, add?'):
                wx_team_additions.append(ad_user["email"])

    # Add users selected to team
    if wx_team_additions:
        for addition in wx_team_additions:
            api.team_memberships.create(wx_team_match['id'], personEmail=addition)
    else:
        print('### No users selected to add to team!')

    print('\n')

    # Notify if space includes users not in AD
    for wx_user in wx_team_members:
        if not any(ad_user['email'] == wx_user.personEmail.lower() for ad_user in ad_dl_userlist):
            print(f'\"{wx_user["name"]}\" not in {ad_dl_match["displayName"]} AD group!')

    print('\nComplete.')
示例#2
0
# Check host alive
def check_host_alive(hostname):
    try:
        urllib2.urlopen(hostname, timeout=1)
        return 1  # OK
    except urllib2.URLError as err:
        return 0  # Error


print "Starting ..."
print "-" * 45
# AD connect
ad_connect = ldap3.Connection(server=ad_host,
                              user=ad_user,
                              password=ad_pass,
                              version=3,
                              authentication='SIMPLE')
if not ad_connect.bind():
    print("ERROR: not connect to AD server")
    sys.exit()
else:
    print "=> Connect to " + ad_host + " is success."

# Get data from AD, generate contacts list and URL list
total_entries = 0
ad_connect.search(search_base=ad_basedn,
                  search_filter='(objectclass=person)',
                  attributes=ad_attr)
total_entries += len(ad_connect.response)
if total_entries > 0:
示例#3
0
# TLS configuration fort the LDAP connection
#tls_configuration = ldap3.Tls(
#  validate=ssl.CERT_NONE,
#  version=ssl.PROTOCOL_TLSv1
#  )

# The LDAP server
ldap_server = ldap3.Server(config.get("ldap", "url"),
                           #tls=tls_configuration,
                           #port=389
                           )

# Connect to the LDAP server
ldap_connection = ldap3.Connection(ldap_server,
                                   config.get("ldap", "user_dn"),
                                   config.get("ldap", "user_pass"),
                                   auto_bind=False)

ldap_connection.open()
ldap_connection.start_tls()
ldap_connection.bind()

# Get the group from LDAP
ldap_connection.search(config.get("ldap", "group_dn"),
                       "(objectClass=*)",
                       search_scope=ldap3.BASE,
                       attributes=['*'])

# Must have a single group
assert len(ldap_connection.entries) == 1, "No of matching groups must be 1"
示例#4
0
文件: ldap.py 项目: vmarreros/hpc
def synchronize():
    from src.application.security.models import LDAPUser
    import logging
    logging.basicConfig(filename='/service_django/error.log',
                        level=logging.DEBUG)
    from ldap3.utils.log import set_library_log_detail_level, set_library_log_hide_sensitive_data, EXTENDED

    set_library_log_detail_level(EXTENDED)
    set_library_log_hide_sensitive_data(False)
    server = ldap3.Server(host=settings.LDAP_SERVER_HOST,
                          port=settings.LDAP_SERVER_PORT,
                          use_ssl=False,
                          get_info=ldap3.ALL)
    # define the connection
    connection = ldap3.Connection(server=server,
                                  user=settings.LDAP_SERVER_USER,
                                  password=settings.LDAP_SERVER_PASSWORD,
                                  auto_bind='NONE',
                                  version=3,
                                  authentication='SIMPLE',
                                  client_strategy='SYNC',
                                  auto_referrals=True,
                                  check_names=True,
                                  read_only=False,
                                  lazy=False,
                                  raise_exceptions=False)
    instance = LDAPUser.objects.get(pk=11)
    if connection.bind():
        attributes = {
            'uid':
            instance.identifier,
            'uidNumber':
            '%s' % (100000 + instance.pk),
            'gidNumber':
            settings.LDAP_SERVER_GROUPS_GROUP_GIDNUMBER,
            'cn':
            instance.__str__(),
            'givenName':
            (instance.first_name if instance.first_name != '' else '-'),
            'sn': (instance.last_name if instance.last_name != '' else '-'),
            'mail':
            instance.email,
            'userPassword':
            instance.password,
            'description':
            instance.detail,
            'homeDirectory':
            '%s%s/%s' % (
                settings.LDAP_SERVER_USERS_HOMEDIRECTORY,
                settings.LDAP_SERVER_GROUPS_GROUP_CN,
                instance.identifier,
            ),
            'loginShell':
            '/bin/bash',
            #
            'institute':
            instance.institute,
            'researchField':
            instance.researchField,
            'researchGroup':
            instance.researchGroup,
            'serviceType':
            'serviceType',
            'userProfile':
            instance.userProfile,
        }
        if instance.tutorInstitution:
            attributes.update({'tutorInstitution': instance.tutorInstitution})
        if instance.tutorMail:
            attributes.update({'tutorMail': instance.tutorMail})
        if instance.tutorName:
            attributes.update({'tutorName': instance.tutorName})
        boolean___is_add = connection.add(dn='uid=%s,ou=%s,%s' % (
            instance.identifier,
            settings.LDAP_SERVER_GROUPS_GROUP_CN,
            settings.LDAP_SERVER_USERS_SEARCH_BASE,
        ),
                                          object_class=[
                                              'inetOrgPerson', 'posixAccount',
                                              'top', 'hpcCubaUser'
                                          ],
                                          attributes=attributes)
        print(attributes)
        print(boolean___is_add)
    else:
        print("not bind")
    connection.unbind()
示例#5
0
    "deakinArea": [],
    "faculty": [],
    "institute": []
}

server = ldap3.Server(ldap_uri)

for i in range(len(res_support)):
    name = res_support.iloc[i, 3]  # extract user's name
    if pd.notnull(name):
        search_filter = "(cn=" + name + ")"  # construct search query
    else:
        continue
    try:
        with ldap3.Connection(
                server,
                auto_bind=True) as conn:  # estab connection and perform query
            conn.search(search_base, search_filter, attributes=attrs)
            pprint(conn.entries)
        query = conn.entries[0]
        email = query.mail  # save the email from the user
        deakinArea = query.deakinArea  # save deakinArea/school
        faculty = query.deakinFacultyDivision  # save facilty
        institute = query.o
        contact_dict["name"].append(name)  # append to contacts
        contact_dict["email"].append(email)
        contact_dict["deakinArea"].append(deakinArea)
        contact_dict["faculty"].append(faculty)
        contact_dict["institute"].append(institute)

    except:
示例#6
0
    def _create_ldap_connection(self,
                                queried_domain=str(),
                                ads_path=str(),
                                ads_prefix=str()):
        if not self._domain:
            self._domain = self._get_netfqdn()

        if not queried_domain:
            queried_domain = self._get_netfqdn()
        self._queried_domain = queried_domain

        base_dn = str()

        if ads_prefix:
            self._ads_prefix = ads_prefix
            base_dn = '{},'.format(self._ads_prefix)

        if ads_path:
            # TODO: manage ADS path starting with 'GC://'
            if ads_path.upper().startswith('LDAP://'):
                ads_path = ads_path[7:]
            self._ads_path = ads_path
            base_dn += self._ads_path
        else:
            base_dn += ','.join('dc={}'.format(x)
                                for x in self._queried_domain.split('.'))

        # base_dn is no longer used within `_create_ldap_connection()`, but I don't want to break
        # the function call. So we store it in an attriute and use it in `_ldap_search()`
        self._base_dn = base_dn

        # Format the username and the domain
        # ldap3 seems not compatible with USER@DOMAIN format
        user = '******'.format(self._domain, self._user)

        # Choose between password or pth
        if self._lmhash and self._nthash:
            lm_nt_hash = '{}:{}'.format(self._lmhash, self._nthash)

            ldap_server = ldap3.Server('ldap://{}'.format(
                self._domain_controller))
            ldap_connection = ldap3.Connection(ldap_server,
                                               user,
                                               lm_nt_hash,
                                               authentication=ldap3.NTLM,
                                               raise_exceptions=True)

            try:
                ldap_connection.bind()
            except ldap3.core.exceptions.LDAPStrongerAuthRequiredResult:
                # We need to try SSL (pth version)
                ldap_server = ldap3.Server('ldaps://{}'.format(
                    self._domain_controller))
                ldap_connection = ldap3.Connection(ldap_server,
                                                   user,
                                                   lm_nt_hash,
                                                   authentication=ldap3.NTLM,
                                                   raise_exceptions=True)

                ldap_connection.bind()

        else:
            ldap_server = ldap3.Server('ldap://{}'.format(
                self._domain_controller))
            ldap_connection = ldap3.Connection(ldap_server,
                                               user,
                                               self._password,
                                               authentication=ldap3.NTLM,
                                               raise_exceptions=True)

            try:
                ldap_connection.bind()
            except ldap3.core.exceptions.LDAPStrongerAuthRequiredResult:
                # We nedd to try SSL (password version)
                ldap_server = ldap3.Server('ldaps://{}'.format(
                    self._domain_controller))
                ldap_connection = ldap3.Connection(ldap_server,
                                                   user,
                                                   self._password,
                                                   authentication=ldap3.NTLM,
                                                   raise_exceptions=True)

                ldap_connection.bind()

        self._ldap_connection = ldap_connection
示例#7
0
    def create_connection(authtype=None, server=None, user=None,
                          password=None, auto_bind=False,
                          client_strategy=ldap3.SYNC,
                          check_names=True,
                          auto_referrals=False,
                          receive_timeout=5):
        """
        Create a connection to the LDAP server.

        :param authtype:
        :param server:
        :param user:
        :param password:
        :param auto_bind:
        :param client_strategy:
        :param check_names:
        :param auto_referrals:
        :param receive_timeout: At the moment we do not use this,
            since receive_timeout is not supported by ldap3 < 2.
        :return:
        """

        authentication = None
        if not user:
            authentication = ldap3.ANONYMOUS

        if authtype == AUTHTYPE.SIMPLE:
            if not authentication:
                authentication = ldap3.SIMPLE
            l = ldap3.Connection(server, user=user,
                                 password=to_utf8(password),
                                 auto_bind=auto_bind,
                                 client_strategy=client_strategy,
                                 authentication=authentication,
                                 check_names=check_names,
                                 # receive_timeout=receive_timeout,
                                 auto_referrals=auto_referrals)
        elif authtype == AUTHTYPE.NTLM:  # pragma: no cover
            if not authentication:
                authentication = ldap3.NTLM
            l = ldap3.Connection(server,
                                 user=user,
                                 password=to_utf8(password),
                                 auto_bind=auto_bind,
                                 client_strategy=client_strategy,
                                 authentication=authentication,
                                 check_names=check_names,
                                 # receive_timeout=receive_timeout,
                                 auto_referrals=auto_referrals)
        elif authtype == AUTHTYPE.SASL_DIGEST_MD5:  # pragma: no cover
            if not authentication:
                authentication = ldap3.SASL
            sasl_credentials = (str(user), str(password))
            l = ldap3.Connection(server,
                                 sasl_mechanism="DIGEST-MD5",
                                 sasl_credentials=sasl_credentials,
                                 auto_bind=auto_bind,
                                 client_strategy=client_strategy,
                                 authentication=authentication,
                                 check_names=check_names,
                                 # receive_timeout=receive_timeout,
                                 auto_referrals=auto_referrals)
        else:
            raise Exception("Authtype {0!s} not supported".format(authtype))

        return l
示例#8
0
    def test_multiple_instances(self):
        servers = {}
        for sid in (1, 2):
            domain = 'example{0}'.format(sid)
            servers[sid] = LdapServer({
                'port':
                10389 + (sid * 1000),
                'bind_dn':
                'cn=admin,dc={0},dc=com'.format(domain),
                'base': {
                    'objectclass': ['domain'],
                    'dn': 'dc={0},dc=com'.format(domain),
                    'attributes': {
                        'dc': domain
                    }
                },
            })
            servers[sid].start()

        search_filter = '(objectclass=domain)'
        attrs = ['dc']

        # server1
        dn = servers[1].config['bind_dn']
        pw = servers[1].config['password']
        base_dn = servers[1].config['base']['dn']
        port = servers[1].config['port']

        srv = ldap3.Server('localhost', port=port)
        conn = ldap3.Connection(srv, user=dn, password=pw, auto_bind=True)
        conn.search(base_dn, search_filter, attributes=attrs)

        self.assertEqual(conn.response, [{
            'dn': 'dc=example1,dc=com',
            'raw_attributes': {
                'dc': [b'example1']
            },
            'attributes': {
                'dc': ['example1']
            },
            'type': 'searchResEntry'
        }])

        conn.unbind()

        # server2
        dn = servers[2].config['bind_dn']
        pw = servers[2].config['password']
        base_dn = servers[2].config['base']['dn']
        port = servers[2].config['port']

        srv = ldap3.Server('localhost', port=port)
        conn = ldap3.Connection(srv, user=dn, password=pw, auto_bind=True)
        conn.search(base_dn, search_filter, attributes=attrs)

        self.assertEqual(conn.response, [{
            'dn': 'dc=example2,dc=com',
            'raw_attributes': {
                'dc': [b'example2']
            },
            'attributes': {
                'dc': ['example2']
            },
            'type': 'searchResEntry'
        }])

        conn.unbind()

        for server in servers.values():
            server.stop()
示例#9
0
                # so take off successive elements from end of split path list
                p = "/".join(split_path[:-i])

            if p in self.path_list:
                for endpoint in self.auth_dict["endpoints"]:
                    if strip_end(strip_end(prefix, "/") + endpoint["endpoint_path"], "/") == p:
                        return {"path": p, "auth_info": endpoint}
            i += 1


# Initialize a global instance of the authlist class, to be used inside the isallowed() function
myauthjson = _AuthJSON()

# initialise LDAP server outside of isallowed so to reduce set-up/tear-down costs
s = ldap3.Server(myauthjson.auth_dict["server"])
c = ldap3.Connection(s, client_strategy=ldap3.RESTARTABLE)
c.open()
c.start_tls()

# ldap details remain in cache for 30 mins
cache = TTLCache(maxsize=256, ttl=1800)


# given a authorisation condition and the user info, does the user satisfy the condition?
# return true or false based on condition
def process_condition(condition, user_info):
    # empty list = don't check any attributes, so auto match
    if len(condition) == 0:
        return True
    if "attribute" in condition:
        # only one attribute to check
示例#10
0
def consume_auth_request():

    # Kill any existing session
    session.clear()

    saml_request = request.args.get('SAMLRequest', None)
    relay_state = request.args.get('RelayState', None)
    signature = request.args.get('Signature', None)
    signature_alg = request.args.get('SigAlg', None)

    if not all([saml_request, relay_state, signature, signature_alg]):
        msg = ("Received malformed HTTP-Redirect request, missing at least "
               "one of these query parameters: SAMLRequest, RelayState, "
               "Signature, SigAlg.")
        logger.error(msg)
        abort(400)

    logger.debug("SAMLRequest is {}".format(saml_request))
    logger.debug("RelayState is {}".format(relay_state))
    logger.debug("Signature is {}".format(signature))
    logger.debug("SigAlg is {}".format(signature_alg))

    idp_config = current_app.config['IDP_CONFIG']
    idp_config_object = IdPConfig().load(copy.deepcopy(idp_config),
                                         metadata_construction=False)
    idp = Server(config=idp_config_object)

    # TODO
    # Need to check signature here or does the parse below do that?
    # What about replay?
    # What about time skew?

    try:
        parsed_request = idp.parse_authn_request(saml_request,
                                                 BINDING_HTTP_REDIRECT)
    except Exception as e:
        msg = "Caught exception while parsing SAMLRequest: {}".format(e)
        logger.error(msg)
        abort(400)

    if not isinstance(parsed_request, Request):
        msg = "Received invalid SAMLRequest"
        logger.error(msg)
        abort(400)

    authn_request = parsed_request.message
    msg = "Parsed SAML request is \n{}"
    msg = msg.format(
        minidom.parseString(str(authn_request)).toprettyxml(indent=' '))
    logger.debug(msg)

    subject = authn_request.subject
    name_id = subject.name_id.text if subject else None

    if not name_id:
        msg = "Unable to obtain NameID from SAMLRequest"
        logger.error(msg)
        abort(400)

    logger.info("NameID is {}".format(name_id))

    # Use the name ID to query LDAP

    ldap_config = current_app.config['IDP_CONFIG']['ldap']
    url = ldap_config['server_url']
    bind_dn = ldap_config['bind_dn']
    bind_password = ldap_config['bind_password']
    search_base = ldap_config['search_base']
    search_filter_template = ldap_config['search_filter_template']

    ldap_server = ldap3.Server(url)

    args = {
        'server': ldap_server,
        'user': bind_dn,
        'password': bind_password,
        'auto_bind': True
    }
    ldap_connection = ldap3.Connection(**args)

    args = {
        'search_base': search_base,
        'search_filter': search_filter_template.format(name_id),
        'search_scope': ldap3.SUBTREE,
        'attributes': ldap3.ALL_ATTRIBUTES
    }

    ldap_connection.search(**args)

    ldap_response = ldap_connection.response

    # TODO Should send back a SAML error.
    if len(ldap_response) == 0:
        msg = "LDAP query with search filter {} returned zero results"
        msg = msg.format(args['search_filter'])
        logger.error(msg)
        abort(400)

    # TODO Should send back a SAML error.
    if len(ldap_response) > 1:
        msg = "LDAP query with search filter {} returned multiple results"
        msg = msg.format(args['search_filter'])
        logger.error(msg)
        abort(400)

    logger.debug(ldap_response[0])

    privacyidea_config = current_app.config['IDP_CONFIG']['privacyidea']
    privacyidea_url = privacyidea_config['server_url']
    privacyidea_admin_token = privacyidea_config['admin_token']

    headers = {
        'Authorization': privacyidea_admin_token,
        'Accept': 'application/json'
    }

    url = privacyidea_url + '/token/?user={}'.format(name_id)

    # TODO Catch exceptions
    resp = requests.get(url, headers=headers)
    token_response = resp.json()

    logger.debug(token_response)

    if token_response['jsonrpc'] != '2.0':
        msg = "Invalid JSON RPC version number"
        logger.error(msg)
        abort(400)

    # User cannot be found
    # TODO Should send back a SAML error.
    result = token_response['result']
    if 'error' in result and result['error']['code'] == 904:
        err_msg = result['error']['message']
        msg = "Token query for user {} generated error: {}"
        msg = msg.format(name_id, err_msg)
        logger.error(msg)
        abort(400)

    # TODO Should send back a SAML error.
    if not token_response['result']['status']:
        msg = "Token query for user {} response status not True"
        msg = msg.format(name_id)
        logger.error(msg)
        abort(400)

    # TODO Need to do better here, handling case where the user is found but
    # for example has no tokens enabled.

    actionable_mfa_tokens = []

    for token in result['value']['tokens']:
        if token['tokentype'] == 'totp':
            actionable_mfa_tokens.append(token)

    if not actionable_mfa_tokens:
        # TODO Should send back SAML error.
        msg = "Could not find actionable MFA token for user {}".format(name_id)
        logger.error(msg)
        abort(400)

    # User is in LDAP and we have found at least one token we can work with
    # so start a session.
    session['name_id'] = name_id
    session['saml_authn_request_id'] = authn_request.id
    session['saml_sp_entity_id'] = authn_request.issuer.text
    session['saml_sp_acs'] = authn_request.assertion_consumer_service_url
    session['saml_relay_state'] = relay_state

    return redirect(url_for('token.token_index'))
    def _ldap_bind(self, action_result=None):
        """
        returns phantom.APP_SUCCESS if connection succeeded,
        else phantom.APP_ERROR.

        If an action_result is passed in, method will
        appropriately use it. Otherwise just return
        APP_SUCCESS/APP_ERROR
        """
        if self._ldap_connection and \
                self._ldap_connection.bound and \
                not self._ldap_connection.closed:
            return True
        elif self._ldap_connection is not None:
            self._ldap_connection.unbind()

        try:
            if self._validate_ssl_cert:
                tls = Tls(validate=ssl.CERT_REQUIRED)
            else:
                tls = Tls(validate=ssl.CERT_NONE)

            server_param = {
                "use_ssl": self._ssl,
                "port": self._ssl_port,
                "host": self._server,
                "get_info": ldap3.ALL,
                "tls": tls
            }

            self._ldap_server = ldap3.Server(**server_param)
            self.save_progress("configured server {}...".format(self._server))
            self._ldap_connection = ldap3.Connection(self._ldap_server,
                                                     user=self._username,
                                                     password=self._password,
                                                     raise_exceptions=True)
            self.save_progress("binding to directory...")

            if not self._ldap_connection.bind():
                if action_result:
                    return action_result.set_status(
                        phantom.APP_ERROR,
                        self._ldap_connection.result['description']
                    )
                else:
                    return phantom.APP_ERROR

            if action_result:
                return action_result.set_status(phantom.APP_SUCCESS)
            else:
                return phantom.APP_SUCCESS

        except Exception as e:
            self.debug_print("[DEBUG] ldap_bind, e = {}".format(e))
            if action_result:
                return action_result.set_status(
                    phantom.APP_ERROR,
                    status_message=e,
                    exception=e
                )
            else:
                return phantom.APP_ERROR
示例#12
0
 def __init__(self):
     """Initialise the plugin and underlying LDAP connection."""
     self._server = ldap3.Server("ldap://xldap.cern.ch")
     self._connection = ldap3.Connection(self._server,
                                         client_strategy=ldap3.SAFE_SYNC,
                                         auto_bind=True)
示例#13
0
 def authenticate(self, user=None, password=None, **kwargs):
     # Validate username
     if not self.check_user(user):
         self.logger.error("Invalid username: %s", user)
         raise self.LoginError("Invalid username")
     # Get domain
     domain, user = self.split_user_domain(user)
     if domain:
         ldap_domain = AuthLDAPDomain.get_by_name(domain)
         if not ldap_domain:
             self.logger.error("LDAP Auth domain '%s' is not configured",
                               domain)
             raise self.LoginError("Invalid LDAP domain '%s'" % domain)
     else:
         ldap_domain = AuthLDAPDomain.get_default_domain()
         if not ldap_domain:
             self.logger.error("Default LDAP Auth domain is not configured")
             raise self.LoginError("Default LDAP domain is not configured")
     if not ldap_domain.is_active:
         self.logger.error("LDAP Auth domain '%s' is disabled", domain)
         raise self.LoginError("LDAP Auth domain '%s' is disabled" % domain)
     # Get servers
     server_pool = self.get_server_pool(ldap_domain)
     if not server_pool:
         self.logger.error("No active servers configured for domain '%s'",
                           domain)
         raise self.LoginError(
             "No active servers configured for domain '%s'" % domain)
     # Connect and bind
     connect_kwargs = self.get_connection_kwargs(ldap_domain, user,
                                                 password)
     dkw = connect_kwargs.copy()
     if "password" in dkw:
         dkw["password"] = "******"
     self.logger.debug("Connect to ldap: %s",
                       ", ".join("%s='%s'" % (kk, dkw[kk]) for kk in dkw))
     connect = ldap3.Connection(server_pool, **connect_kwargs)
     try:
         self.logger.debug("Bind to ldap")
         if not connect.bind():
             raise self.LoginError("Failed to bind to LDAP: %s" %
                                   connect.result)
     except (LDAPCommunicationError, LDAPServerPoolExhaustedError) as e:
         self.logger.error("Failed to bind to LDAP: connect failed by %s" %
                           e.message)
         raise self.LoginError(
             "Failed to bind to LDAP: connect failed by %s" % e.message)
     # Rebind as privileged user
     if ldap_domain.bind_user:
         # Rebind as privileged user
         connect = ldap3.Connection(
             server_pool,
             **self.get_connection_kwargs(ldap_domain,
                                          ldap_domain.bind_user,
                                          ldap_domain.bind_password))
         if not connect.bind():
             self.logger.error("Cannot bind as %s to search groups",
                               ldap_domain.bind_user)
             connect = None
     # Get user information
     user_info = self.get_user_info(connect, ldap_domain, user)
     user_info["user"] = user
     user_info["domain"] = domain
     user_info["is_active"] = True
     # Get user groups
     user_groups = set(
         g.lower()
         for g in self.get_user_groups(connect, ldap_domain, user_info))
     if ldap_domain.require_any_group and not user_groups:
         self.logger.error(
             "User %s in not a member of any mapped groups. Deny access",
             user)
         raise self.LoginError("No groups")
     if ldap_domain.require_group and ldap_domain.require_group.lower(
     ) not in user_groups:
         self.logger.error(
             "User %s is not a member of required group %s but member of %s",
             user,
             ldap_domain.require_group,
             user_groups,
         )
         raise self.LoginError("Login is not permitted")
     if ldap_domain.deny_group and ldap_domain.deny_group.lower(
     ) in user_groups:
         self.logger.error("User %s is a member of deny group %s", user,
                           ldap_domain.deny_group)
         user_info["is_active"] = False
     # Synchronize user
     user = ldap_domain.clean_username(user)
     u = self.ensure_user(user, **user_info)
     # Get group mappings
     group_mappings = ldap_domain.get_group_mappings()
     # Apply groups
     ug = []
     for group in group_mappings:
         if group_mappings[group] & user_groups:
             self.logger.debug("%s: Ensure group %s", u.username,
                               group.name)
             self.ensure_group(u, group)
             ug += [group.name]
         else:
             self.logger.debug("%s: Deny group %s", u.username, group.name)
             self.deny_group(u, group)
     # Final check
     if not user_info["is_active"]:
         raise self.LoginError("Access denied")
     self.logger.info("Authenticated as %s. Groups: %s", u.username,
                      ", ".join(ug))
     return u.username
示例#14
0
#!/usr/bin/python

import ldap3

CUSER_DN = 'cn=Directory Manager'
PEOPLE_DN = 'ou=people,dc=prorail,dc=nl'
cuser_password = '******'
local_ldap = 'ldap1.home.org'
install = 'allard'
password = '******'

s = ldap3.Server(local_ldap)
c = ldap3.Connection(s, user=CUSER_DN, password=cuser_password)
c.open()
c.start_tls()
c.bind()
install_dn = 'uid=%s,%s' % (install, PEOPLE_DN)
c.modify(
    install_dn, {
        'passwordexpirationtime': [(ldap3.MODIFY_REPLACE, ['20170402170000Z'])
                                   ],
        'nsroledn': [(ldap3.MODIFY_REPLACE, [])]
    })
print c.result
c.unbind()
示例#15
0
def ldap_server(unused_port, docker, request):
    docker.pull('minkwe/389ds:latest')

    ssl_directory = os.path.join(os.path.dirname(__file__), 'resources', 'ssl')
    ca_file = os.path.join(ssl_directory, 'ca.pem')

    ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    ctx.check_hostname = False
    ctx.load_verify_locations(cafile=ca_file)

    host = "127.0.0.1"
    host_port = unused_port()
    server_params = {
        'host': host,
        'port': host_port,
        'base_dn': 'dc=example,dc=com',
        'user': '******',
        'password': '******',
        'test_ou1': 'ou=test1,dc=example,dc=com',
        'test_ou2': 'ou=test2,dc=example,dc=com',
        'test_ou3': 'ou=test3,dc=example,dc=com',
        'whoami': 'dn: cn=directory manager',
        'ctx': ctx
    }

    container_args = {
        'image':
        'minkwe/389ds:latest',
        'name':
        'aioldap-test-server-{0}'.format(session_id()),
        'ports': [389],
        'detach':
        True,
        'hostname':
        'ldap.example.com',
        'environment': {
            'DIR_HOSTNAME': 'ldap.example.com',
            'DIR_MANAGER_PASSWORD': server_params['password'],
            'DIR_SUFFIX': server_params['base_dn']
        },
        'host_config':
        docker.create_host_config(port_bindings={389: (host, host_port)},
                                  binds={
                                      ssl_directory: {
                                          'bind': '/certs',
                                          'ro': False
                                      },
                                  }),
        'volumes': ['/certs']
    }

    container = docker.create_container(**container_args)

    try:
        docker.start(container=container['Id'])
        delay = 0.001

        # 389 takes at least 15 to come up, go down, come up with SSL
        time.sleep(15)

        for i in range(100):
            try:
                server = ldap3.Server(host=host, port=host_port, get_info=None)
                conn = ldap3.Connection(server,
                                        user='******',
                                        password=server_params['password'])
                conn.bind()

                whoami = conn.extend.standard.who_am_i()
                assert whoami == 'dn: cn=directory manager', "Unexpected bind user"

                # Create an OU to throw some stuff
                res = conn.add(server_params['test_ou1'],
                               object_class='organizationalUnit')
                assert res, "Failed to create ou=test1"
                res = conn.add(server_params['test_ou2'],
                               object_class='organizationalUnit')
                assert res, "Failed to create ou=test2"
                res = conn.add(server_params['test_ou3'],
                               object_class='organizationalUnit')
                assert res, "Failed to create ou=test3"

                break
            except AssertionError as err:
                pytest.fail(str(err))
            except Exception as err:
                if delay > 40:
                    pytest.fail('container startup took too long')

                time.sleep(delay)
                delay *= 2
        else:
            pytest.fail("Cannot start LDAP server")

        container['host'] = host
        container['port'] = host_port
        container['ldap_params'] = server_params

        yield container
    finally:
        docker.kill(container=container['Id'])
        docker.remove_container(container['Id'])
示例#16
0
##----------LOAD CONFIG-----------------------------------##
import yaml

with open('./config.yml', 'r') as f:
    cfg = yaml.load(f)

##-----------------CONNECT TO AD----------------------------##
import ldap3
import json
from tqdm import tqdm

server = ldap3.Server(cfg['host'], get_info=ldap3.ALL)

conn = ldap3.Connection(server,
                        user=cfg['user'],
                        password=cfg['pwd'],
                        authentication=ldap3.NTLM,
                        auto_bind=True)

conn.start_tls()

#Searching personal account of user MODULARIZE THIS SEGEMENT
emailID = "*****@*****.**"
conn.search(' ou=Users-AAD,dc=lux,dc=intra,dc=lighting,dc=com',
            '(mail=' + emailID + ')',
            attributes=ldap3.ALL_ATTRIBUTES)
personal_entry_user = [
    json.loads(e.entry_to_json()) for e in tqdm(conn.entries)
]

#splicing out the LUX Id of the manager Refer "seeAlso" attribute for user, All LUX IDs do not have uniform number of elements
示例#17
0
    def ldap_link(self, username, password, mode='LOGIN'):

        # If no password provided, we will not try to authenticate
        if password:

            # Prepare LDAP connection details
            nt4_domain = settings.AD_NT4_DOMAIN.upper()
            dns_name = getattr(settings, "AD_DNS_NAME", nt4_domain).upper()
            use_ssl = getattr(settings, "AD_SSL", False)
            if use_ssl:
                default_port = 636
                proto = 'ldaps'
            else:
                default_port = 389
                proto = 'ldap'
            port = getattr(settings, 'AD_LDAP_PORT', default_port)
            ldap_url = '{}://{}:{}'.format(proto, dns_name, port)
            self.debug('ldap.initialize :: url: {}'.format(ldap_url))

            # Prepare library
            ser = {}
            ser['allowed_referral_hosts'] = [("*", True)]
            con = {}
            con['user'] = "******".format(nt4_domain, username)
            con['password'] = password
            con['raise_exceptions'] = True
            con['authentication'] = ldap3.NTLM
            if use_ssl:
                certfile = settings.AD_CERT_FILE
                self.debug(
                    'ldap.ssl :: Activated - Cert file: {}'.format(certfile))
                con['auto_bind'] = ldap3.AUTO_BIND_TLS_BEFORE_BIND
                ser['use_ssl'] = True
                ser['tls'] = ldap3.Tls(validate=ssl.CERT_REQUIRED,
                                       version=ssl.PROTOCOL_TLSv1)
            else:
                con['auto_bind'] = ldap3.AUTO_BIND_NO_TLS
            try:
                #self.debug('ldap.server params :: {}'.format(ser))
                server = ldap3.Server(ldap_url, **ser)
                self.debug('ldap.server :: {}'.format(server))
                #self.debug('ldap.connection params :: {}'.format(con))
                answer = ldap3.Connection(server, **con)
                self.debug('ldap.connection :: {}'.format(answer))
                #answer.open()
                #answer.bind()
                self.debug('ldap.connected :: Authorized')
            except LDAPSocketOpenError as e:
                # The access for this user has been denied, Debug it if required
                self.debug(
                    "LDAP connect failed 'SocketOpenError' for url '{}' with error '{}'"
                    .format(ldap_url, e))
                answer = False
            except LDAPException as e:
                # The access for this user has been denied, Debug it if required
                self.debug(
                    "LDAP connect failed 'LDAPException' for user '{}' with error '{}'"
                    .format(username, e))
                answer = False

        else:
            # The access for this user has been denied, Debug it if required
            self.debug("No password provided for user '{}'".format(username))
            answer = False

        # Return the final result
        return answer
示例#18
0
print(c.bind())
# perform the Bind operation
if not c.bind():
    print('error in bind', c.result)

#_____________
#
import ldap3
ldapServer = 'ldap://172.17.17.201:389'
domain = 'd1'
userName = '******'
domainUserName = domain + '\\' + userName
password = '******'
conn = ldap3.__version__
print(conn)
conn = ldap3.Connection(ldapServer)
conn.open(domainUserName, password)

from ldap3 import Server, Connection, ALL

# define the server
s = Server(
    'ldap://172.17.17.201', get_info=ALL
)  # define an unsecure LDAP server, requesting info on DSE and schema

# define the connection
c = Connection(s, user='******', password='******')
print(c.bind())
# perform the Bind operation
if not c.bind():
    print('error in bind', c.result)
示例#19
0
    def POST(self, id):
        # Get configuration
        settings = self.user_manager.get_auth_method(id).get_settings()
        login_data = flask.request.form
        login = login_data["login"].strip().lower()
        password = login_data["password"]

        # do not send empty password to the LDAP
        if password.rstrip() == "":
            return self.template_helper.render(
                "custom_auth_form.html",
                template_folder="frontend/plugins/auth",
                settings=settings,
                error=_("Empty password"))

        try:
            # Connect to the ldap
            logger.debug('Connecting to ' + settings['host'] + ", port " +
                         str(settings['port']))
            if "bind_dn" in settings:
                bind_dn = {
                    "user": settings["bind_dn"].format(login),
                    "password": password
                }
            else:
                bind_dn = {}

            auto_bind = settings.get("auto_bind", True)
            conn = ldap3.Connection(ldap3.Server(
                settings['host'],
                port=settings['port'],
                use_ssl=settings["encryption"] == 'ssl',
                get_info=ldap3.ALL),
                                    auto_bind=auto_bind,
                                    **bind_dn)
            logger.debug('Connected to ' + settings['host'] + ", port " +
                         str(settings['port']))
        except LDAPException as e:
            logger.exception("Can't initialze connection to " +
                             settings['host'] + ': ' + str(e))
            return self.template_helper.render(
                "custom_auth_form.html",
                template_folder="frontend/plugins/auth",
                settings=settings,
                error=_("Cannot contact host"))

        attr_cn = settings.get("cn", "cn")
        attr_mail = settings.get("mail", "mail")
        try:
            ldap_request = settings["request"].format(login)
            conn.search(settings["base_dn"],
                        ldap_request,
                        attributes=[attr_cn, attr_mail])
            user_data = conn.response[0]
        except (LDAPException, IndexError) as ex:
            logger.exception("Can't get user data : " + str(ex))
            conn.unbind()
            return self.template_helper.render(
                "custom_auth_form.html",
                template_folder="frontend/plugins/auth",
                settings=settings,
                error=_("Unknown user"))

        if conn.rebind(user_data['dn'], password=password):
            try:
                email = user_data['attributes'][attr_mail]
                if isinstance(email, list):
                    email = email[0]
                username = login
                realname = user_data["attributes"][attr_cn]
                if isinstance(realname, list):
                    realname = realname[0]

            except KeyError as e:
                logger.exception("Can't get field " + str(e) +
                                 " from your LDAP server")
                return self.template_helper.render(
                    "custom_auth_form.html",
                    template_folder="frontend/plugins/auth",
                    settings=settings,
                    error=_("Can't get field {} from your LDAP server").format(
                        str(e)))
            except LDAPException as e:
                logger.exception("Can't get some user fields")
                return self.template_helper.render(
                    "custom_auth_form.html",
                    template_folder="frontend/plugins/auth",
                    settings=settings,
                    error=_("Can't get some user fields"))
            finally:
                conn.unbind()

            if not self.user_manager.bind_user(
                    id, (username, realname, email, {})):
                return redirect("/signin?binderror")

            auth_storage = self.user_manager.session_auth_storage().setdefault(
                id, {})
            return redirect(auth_storage.get("redir_url", "/"))
        else:
            logger.debug('Auth Failed')
            conn.unbind()
            return self.template_helper.render(
                "custom_auth_form.html",
                base_template_folder="frontend/plugins/auth",
                settings=settings,
                error=_("Incorrect password"))
def main(arguments):

    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('user')
    parser.add_argument('--cert-file',
                        default=getenv('LDAP_CERT_FILE'),
                        help="""Path to TLS certificate used for encrypting the
        connection to the LDAP server. Uses value of LDAP_CERT_FILE if
        defined.""")
    parser.add_argument('--host',
                        default=getenv('LDAP_HOST'),
                        help="""Name of the LDAP host. Uses value of LDAP_HOST
        by default.""")
    parser.add_argument(
        '--user-dn',
        default=getenv('LDAP_USER_DN'),
        help="""Base DN for user search in LDAP directory, including a
        placeholder for USER (will look something like
        "CN=%%s,CN=Users,DC=MyDomain,DC=com"). Uses value of
        LDAP_USER_DN by default.""")
    parser.add_argument(
        '--timeout',
        type=int,
        default=3,
        help='Timeout for LDAP server connection in seconds [%(default)s].')

    args = parser.parse_args(arguments)

    if not sys.stdin.isatty():  # stdin has content
        password = sys.stdin.read().strip()
    else:
        password = getpass.getpass()

    conn = ldap3.Connection(
        ldap3.Server(
            args.host,
            port=636,
            use_ssl=True,
            tls=ldap3.Tls(
                ca_certs_file=args.cert_file,
                # validate=ssl.CERT_NONE,
                validate=ssl.CERT_REQUIRED,
            ),
            get_info=ldap3.NONE,
            connect_timeout=args.timeout,
        ),
        auto_bind=False,
        client_strategy=ldap3.SYNC,
        user=args.user_dn % args.user,
        password=password,
        raise_exceptions=True,
        check_names=True)

    conn.start_tls()

    try:
        conn.bind()
    except LDAPInvalidCredentialsResult as err:
        print(err)
        status = 1
    else:
        print('Success')
        status = 0
    finally:
        conn.unbind()
        sys.exit(status)
示例#21
0
def main():
    argparser = argparse.ArgumentParser()
    argparser.add_argument('--ldapconfig',
                           help='Path to YAML LDAP config file',
                           default='/etc/ldap.yaml')
    argparser.add_argument(
        '--infrastructure-users',
        help=('Path to CSV file with infrastructure users config'
              ' (tokenauth format)'),
        default='/etc/kubernetes/infrastructure-users.csv')
    argparser.add_argument('--debug',
                           help='Turn on debug logging',
                           action='store_true')
    argparser.add_argument('--project',
                           help='Project name to fetch LDAP users from',
                           default='tools')
    argparser.add_argument('--interval',
                           help='Seconds between between runs',
                           default=60)
    argparser.add_argument('--once',
                           help='Run once and exit',
                           action='store_true')
    argparser.add_argument('kube_master_url',
                           help='Full URL of Kubernetes Master')
    argparser.add_argument('tokenauth_output_path',
                           help='Path to output tokenauth CSV file')
    argparser.add_argument('abac_output_path',
                           help='Path to output abac JSONL file')

    args = argparser.parse_args()

    loglvl = logging.DEBUG if args.debug else logging.INFO
    logging.basicConfig(format='%(message)s', level=loglvl)

    with open(args.ldapconfig, encoding='utf-8') as f:
        ldapconfig = yaml.safe_load(f)

    cur_users = get_users_from_csv(args.tokenauth_output_path)

    infra_users = get_users_from_csv(args.infrastructure_users)

    while True:
        logging.info('starting a run')
        servers = ldap3.ServerPool([
            ldap3.Server(s, connect_timeout=1) for s in ldapconfig['servers']
        ],
                                   ldap3.POOLING_STRATEGY_ROUND_ROBIN,
                                   active=True,
                                   exhaust=True)
        with ldap3.Connection(
                servers,
                read_only=True,
                user=ldapconfig['user'],
                auto_bind=True,
                password=ldapconfig['password'],
                raise_exceptions=True,
        ) as conn:
            tools = get_tools_from_ldap(conn, args.project)

        new_tools = set(tools).union(set(infra_users)) - set(cur_users)
        if new_tools:
            # There are at least some new tools, so we have to:
            #  1. Regenerate the entire tokenauth file
            #  2. Regenerate entire ABAC file
            #  3. Write out kubeconfig files for all the new tools
            #  4. Restart the apiserver
            for uid in new_tools:
                if uid in tools:
                    tools[uid].token = generate_pass(64)
                    create_homedir(tools[uid])
                    write_kubeconfig(tools[uid], args.kube_master_url)
                    create_namespace(tools[uid])
                    cur_users[uid] = tools[uid]
                    logging.info('Provisioned creds for tool %s',
                                 tools[uid].name)
                elif uid in infra_users:
                    cur_users[uid] = infra_users[uid]
                    logging.info('Provisioned creds for infra user %s',
                                 infra_users[uid].name)
            write_tokenauth(cur_users.values(), args.tokenauth_output_path)
            write_abac(cur_users.values(), args.abac_output_path)
            subprocess.check_call(
                ['/bin/systemctl', 'restart', 'kube-apiserver'])
        logging.info('finished run, wrote %s new accounts', len(new_tools))

        if args.once:
            break

        time.sleep(args.interval)
gluu_ldap_prop_fn = '/etc/jans/conf/jans-ldap.properties'

for l in open(gluu_ldap_prop_fn):
    if l.startswith('bindPassword'):
        n = l.find(':')
        passwd_enc = l[n + 1:].strip()
        ldap_admin_pw = os.popen('/opt/jans/bin/encode.py -D ' +
                                 passwd_enc).read().strip()
        break
else:
    print("Can't find ldap admin password")

server = ldap3.Server("ldaps://localhost:1636", use_ssl=True)
conn = ldap3.Connection(server,
                        user="******",
                        password=ldap_admin_pw)
conn.bind()

app_base_dn = 'ou={},ou=configuration,o=jans'.format(argsp.l)
conn.search(search_base=app_base_dn,
            search_scope=ldap3.BASE,
            search_filter='(objectclass=*)',
            attributes=['jansConfDyn'])

if conn.response and 'jansConfDyn' in conn.response[0]['attributes']:
    jansConfDyn = json.loads(conn.response[0]['attributes']['jansConfDyn'][0],
                             object_pairs_hook=OrderedDict)
else:
    print("Can't load jansConfDyn")
    sys.exit()
示例#23
0
    def create_connection(authtype=None,
                          server=None,
                          user=None,
                          password=None,
                          auto_bind=False,
                          client_strategy=ldap3.SYNC,
                          check_names=True,
                          auto_referrals=False,
                          receive_timeout=5,
                          start_tls=False):
        """
        Create a connection to the LDAP server.

        :param authtype:
        :param server:
        :param user:
        :param password:
        :param auto_bind:
        :param client_strategy:
        :param check_names:
        :param auto_referrals:
        :param receive_timeout: At the moment we do not use this,
            since receive_timeout is not supported by ldap3 < 2.
        :return:
        """

        authentication = None
        if not user:
            authentication = ldap3.ANONYMOUS

        if authtype == AUTHTYPE.SIMPLE:
            if not authentication:
                authentication = ldap3.SIMPLE
            # SIMPLE works with passwords as UTF8 and unicode
            l = ldap3.Connection(
                server,
                user=user,
                password=password,
                auto_bind=auto_bind,
                client_strategy=client_strategy,
                authentication=authentication,
                check_names=check_names,
                # receive_timeout=receive_timeout,
                auto_referrals=auto_referrals)
        elif authtype == AUTHTYPE.NTLM:  # pragma: no cover
            if not authentication:
                authentication = ldap3.NTLM
            # NTLM requires the password to be unicode
            l = ldap3.Connection(
                server,
                user=user,
                password=password,
                auto_bind=auto_bind,
                client_strategy=client_strategy,
                authentication=authentication,
                check_names=check_names,
                # receive_timeout=receive_timeout,
                auto_referrals=auto_referrals)
        elif authtype == AUTHTYPE.SASL_DIGEST_MD5:  # pragma: no cover
            if not authentication:
                authentication = ldap3.SASL
            password = to_utf8(password)
            sasl_credentials = (str(user), str(password))
            l = ldap3.Connection(
                server,
                sasl_mechanism="DIGEST-MD5",
                sasl_credentials=sasl_credentials,
                auto_bind=auto_bind,
                client_strategy=client_strategy,
                authentication=authentication,
                check_names=check_names,
                # receive_timeout=receive_timeout,
                auto_referrals=auto_referrals)
        else:
            raise Exception("Authtype {0!s} not supported".format(authtype))

        if start_tls:
            l.open(read_server_info=False)
            log.debug("Doing start_tls")
            r = l.start_tls(read_server_info=False)

        return l
示例#24
0
def connection(**kwargs):
    """
    Creates and returns a connection to the LDAP server.

    The user identifier, if given, should be keyword arguments matching the fields
    in settings.LDAP_AUTH_USER_LOOKUP_FIELDS, plus a `password` argument.
    """
    # Format the DN for the username.
    format_username = import_func(settings.LDAP_AUTH_FORMAT_USERNAME)
    kwargs = {key: value for key, value in kwargs.items() if value}
    username = None
    password = None
    domain = None
    if kwargs:
        password = kwargs.pop("password")
        domain = kwargs.get("domain")
        username = format_username(kwargs)
    # Configure the connection.
    if settings.LDAP_AUTH_USE_TLS:
        auto_bind = ldap3.AUTO_BIND_TLS_BEFORE_BIND
    else:
        auto_bind = ldap3.AUTO_BIND_NO_TLS
    # Connect.
    if domain is not None:
        auth_url = settings.LDAP_AUTH_MULTIDOMAIN_URL.get(domain)
    else:
        auth_url = settings.LDAP_AUTH_URL
    try:
        c = ldap3.Connection(
            ldap3.Server(
                auth_url,
                allowed_referral_hosts=[("*", True)],
                get_info=ldap3.NONE,
                connect_timeout=settings.LDAP_AUTH_CONNECT_TIMEOUT,
            ),
            user=username,
            password=password,
            auto_bind=auto_bind,
            raise_exceptions=True,
            receive_timeout=settings.LDAP_AUTH_RECEIVE_TIMEOUT,
        )
    except LDAPException as ex:
        logger.warning("LDAP connect failed: {ex}".format(ex=ex))
        yield None
        return
    # If the settings specify an alternative username and password for querying, rebind as that.
    if ((settings.LDAP_AUTH_CONNECTION_USERNAME
         or settings.LDAP_AUTH_CONNECTION_PASSWORD)
            and (settings.LDAP_AUTH_CONNECTION_USERNAME != username
                 or settings.LDAP_AUTH_CONNECTION_PASSWORD != password)):
        User = get_user_model()
        try:
            c.rebind(
                user=format_username({
                    User.USERNAME_FIELD:
                    settings.LDAP_AUTH_CONNECTION_USERNAME
                }),
                password=settings.LDAP_AUTH_CONNECTION_PASSWORD,
            )
        except LDAPException as ex:
            logger.warning("LDAP rebind failed: {ex}".format(ex=ex))
            yield None
            return
    # Return the connection.
    logger.info("LDAP connect succeeded")
    try:
        yield Connection(c)
    finally:
        c.unbind()
    def __init__(self,
                 url,
                 dn=None,
                 secret=None,
                 base="",
                 debug=False,
                 paged_size=1000,
                 size_limit=None,
                 time_limit=None):
        """If you do not specify credentials (dn and secret) it will try to load them from ~/.netrc file.

        @param server: url of LDAP Server
        @param dn: username of the service account
        @param secret: password of the servce account
        """
        self.filter = ''
        self.scope = ldap3.SEARCH_SCOPE_WHOLE_SUBTREE
        self.paged_size = paged_size
        if not size_limit:
            self.size_limit = Integer0ToMax(0)
        else:
            self.size_limit = size_limit

        if not time_limit:
            self.time_limit = Integer0ToMax(0)
        else:
            self.time_limit = time_limit

        self.attrs = '*'

        self.logger = logging.getLogger('ldap')
        if debug:
            self.logger.setLevel(logging.DEBUG)
        else:
            self.logger.setLevel(logging.INFO)
        self.url = url

        self.dn = dn
        self.secret = secret

        u = urlparse(url)

        if base:
            self.base = base
        else:
            self.base = u.path[1:]

        if u.scheme == 'ldaps':
            use_ssl = True
        else:
            use_ssl = False

        if ":" in u.hostname:
            u.hostname = u.hostname.split(":")[0]
        if dn is None:
            import netrc
            try:
                netrc_config = netrc.netrc()
                for h in netrc_config.hosts:
                    if h.lower() == u.hostname.lower():
                        dn, account, secret = netrc_config.authenticators(h)
                        break
            except Exception as e:
                logging.warning("~/.netrc ignored due to: %s" % e)

        self.server = ldap3.Server(host=u.hostname,
                                   port=u.port,
                                   use_ssl=use_ssl)
        self.conn = ldap3.Connection(
            self.server,
            auto_bind=True,
            # client_strategy=ldap3.STRATEGY_REUSABLE_THREADED, # .STRATEGY_SYNC,
            client_strategy=ldap3.STRATEGY_SYNC,
            user=dn,
            password=secret,
            authentication=ldap3.AUTH_SIMPLE)
        try:
            ret = self.conn.bind()
        except Exception as e:
            self.logger.error(e)
        else:
            self._connected = True
示例#26
0
def findUser(user,group,conn,base,search):
    ret=conn.search(base,search,search_scope=ldap3.SUBTREE,attributes=['member'])
    entry=conn.entries[0]
    members=json.loads(entry.entry_to_json())['attributes']['member']
#    print(members)
    for member in members:
#        print(member)
        if "User" in member:
            r=record(member)
            print(r.CN)
            user.append(r.CN)

        if "Groups" in member:
            print("Recurssion")
            r=record(member)
            search='(&(objectCategory=GROUP)(cn=%s))'%r.CN
            user=findUser(user,r.CN,conn,base,search)
#            print(users,r.CN,conn,base,search)
    return user
if __name__ == "__main__":
    server=ldap3.Server('adserver.com')
	conn=ldap3.Connection(server,auto_bind=True)
    grp='ADGroupWithRecursiveGroup'
    base='dc=ad,dc='<domainname/CompanyName>",dc=com'
    search='(&(objectCategory=GROUP)(cn=%s))'%grp
    users=[]

    users=findUser(users,grp,conn,base,search)
    print(set(users))
    conn.unbind()
示例#27
0
def handle_ec2_change(event, context):
    # Filter out missleading events
    if not event['detail']['state'] in ['pending', 'terminated'] :
        return json.dumps({'status': 'error'})

    # Initial print
    print("Working on instance {} - {}".format(get_instance_id(event), event['detail']['state']))

    # Populate common variables
    directory_id = get_directory_id()
    desc = collect_ds_information(directory_id)    
    if not desc:
        print('There is no such a directory {}'.format(directory_id))
        return

    basedn = get_basedn()
    print("* Dealing with {}".format(basedn))
    domain_name = desc['Name']
    dns_servers = desc['DnsIpAddrs']

    # Open connection Active Directory
    server = ldap3.Server('{}://{}'.format(get_proto(), get_ldap_host(domain_name)))
    conn = ldap3.Connection(server, **get_directory_credentials(directory_id, domain_name))
    if not conn.bind():
        print('error in bind', conn.result)

    # Search for EC2 instances
    searchState = conn.search(basedn,"(description={})".format(get_instance_id(event)))
    print("* LDAP search status {}: {}".format(searchState, len(conn.entries)))

    # * Pending
    # Validate whether EC2 is in AD already
    # Register trigger SSM document against server
    if event['detail']['state'] == 'pending':
        # Describe instance to find all tags

        # No instance were found
        if not searchState or len(conn.entries) == 0:
            # Validate the server should be joined
            print("* Describing EC2 instance {}".format(get_instance_id(event)))
            ec2 = boto3.client('ec2', region_name=event['region'])
            ds = ec2.describe_instances(
                InstanceIds = [
                    get_instance_id(event)
                ]
            )
            instances = [item for sublist in ds.get('Reservations', []) for item in sublist['Instances']]
            fins = [x for x in instances if x['InstanceId'] == get_instance_id(event)]
            if len(fins) <= 0:
                return json.dumps({'status': 'no such instances'})
            tags = {x['Key'].strip().lower(): x['Value'].strip() for x in fins[0].get('Tags', []) if tags_prefix.lower() in x['Key'].lower()}

            # Determine whether to join or not
            join_domain = tags.get('domain:join', 'false').lower() in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh']

            # 
            print("* Server is designated for joining to domain: {}".format(join_domain))
            if not join_domain:
                return json.dumps({'status': 'ok'})
            
            # Run SSM Document
            print('* Initiating join {} for instance {}'.format(get_join_document(), get_instance_id(event)))
            ssm = boto3.client('ssm', region_name=event['region'])
            ass = ssm.create_association(
                Name = get_join_document(),
                Targets = [
                    {
                        'Key': 'InstanceIds',
                        'Values': [ get_instance_id(event) ]
                    }
                ],
                Parameters = {
                    'directoryId': [directory_id],
                    'directoryName': [domain_name],
                    'directoryOU': [basedn],
                    'dnsIpAddresses': [ ' '.join(dns_servers) ]
                }
            )
            print(ass)

    # * Termination
    # Remove from AD
    # Remove from Monitoring
    if event['detail']['state'] == 'terminated':

        # Delete From Active directory
        if searchState or len(conn.entries) > 0:
            print('Dropping following DNs:')
            for r in list(conn.entries):
                print(r.entry_dn)
                
                # Delete entry from LDAP
                delete_from_ldap(conn, basedn, r, get_instance_id(event))

    # Dummy return
    return json.dumps({'status': 'ok'})
示例#28
0
def main():
    argparser = argparse.ArgumentParser()
    group1 = argparser.add_mutually_exclusive_group()
    group2 = argparser.add_mutually_exclusive_group()
    argparser.add_argument(
        "--ldapconfig",
        help="Path to YAML LDAP config file",
        default="/etc/ldap.yaml",
    )
    argparser.add_argument("--debug",
                           help="Turn on debug logging",
                           action="store_true")
    argparser.add_argument(
        "--project",
        help="Project name to fetch LDAP users from",
        default="tools",
    )
    argparser.add_argument(
        "--admins-only",
        "-a",
        help="Only manage admin accounts for this project",
        default=False,
        action="store_true",
    )
    group1.add_argument("--interval",
                        help="Seconds between between runs",
                        default=60)
    group1.add_argument("--once",
                        help="Run once and exit",
                        action="store_true")
    argparser.add_argument(
        "--local",
        help="Specifies this is not running in Kubernetes (for debugging)",
        action="store_true",
    )
    group2.add_argument(
        "--force-migrate",
        help=(
            "For full Kubernetes cluster change: switches every account ",
            "to use the toolforge context. Requires the --once option",
        ),
        action="store_true",
    )
    group2.add_argument(
        "--gentle-mode",
        help=("Before general release, keep current context set to default "
              "while the new Kubernetes cluster is considered opt-in"),
        action="store_true",
    )

    args = argparser.parse_args()
    if args.force_migrate and not args.once:
        argparser.error("--once is required when --force-migrate is set")

    loglvl = logging.DEBUG if args.debug else logging.INFO
    logging.basicConfig(format="%(message)s", level=loglvl)

    with open(args.ldapconfig, encoding="utf-8") as f:
        ldapconfig = yaml.safe_load(f)

    if args.local:
        k_config.load_kube_config()
    else:
        k_config.load_incluster_config()

    k8s_api = K8sAPI()
    api_server, ca_data = k8s_api.get_cluster_info()

    while True:
        logging.info("starting a run")
        # Touch a temp file for a Kubernetes liveness check to prevent hangs
        Path("/tmp/run.check").touch()
        cur_users, expiring_users = k8s_api.get_current_users(args.admins_only)
        servers = ldap3.ServerPool(
            [
                ldap3.Server(s, connect_timeout=1)
                for s in ldapconfig["servers"]
            ],
            ldap3.ROUND_ROBIN,
            active=True,
            exhaust=True,
        )
        with ldap3.Connection(
                servers,
                read_only=True,
                user=ldapconfig["user"],
                auto_bind=True,
                password=ldapconfig["password"],
                raise_exceptions=True,
                receive_timeout=60,
        ) as conn:
            tools = []
            if not args.admins_only:
                tools = get_tools_from_ldap(conn, args.project)

            admins = get_admins_from_ldap(conn, args.project)

        # If this is just migrating all remaining users (--force-migrate)
        # we should short-circuit the while True loop as soon as possible to
        # reduce all the churn.
        if args.force_migrate:
            for tool_name in cur_users["tools"]:
                tools[tool_name].switch_context()

            break

        if tools:
            new_tools = process_new_users(tools, cur_users["tools"], k8s_api,
                                          args.gentle_mode)
            if expiring_users["tools"]:
                for tool_name in expiring_users["tools"]:
                    tools[tool_name].pk = generate_pk()
                    k8s_api.generate_csr(tools[tool_name].pk, tool_name)
                    tools[tool_name].cert = k8s_api.approve_cert(tool_name)
                    tools[tool_name].create_homedir()
                    tools[tool_name].write_kubeconfig(api_server, ca_data,
                                                      args.gentle_mode)
                    k8s_api.update_expired_ns(tools[tool_name])
                    logging.info("Renewed creds for tool %s", tool_name)

        if admins:
            new_admins = process_new_users(admins, cur_users["admins"],
                                           k8s_api, args.gentle_mode)
            if expiring_users["admins"]:
                for admin_name in expiring_users["admins"]:
                    admins[admin_name].pk = generate_pk()
                    k8s_api.generate_csr(admins[admin_name].pk, admin_name)
                    admins[admin_name].cert = k8s_api.approve_cert(admin_name)
                    admins[admin_name].create_homedir()
                    admins[admin_name].write_kubeconfig(
                        api_server, ca_data, args.gentle_mode)
                    k8s_api.update_expired_ns(admins[admin_name])
                    logging.info("Renewed creds for admin user %s", admin_name)

        logging.info("finished run, wrote %s new accounts",
                     new_tools + new_admins)

        if args.once:
            break

        time.sleep(args.interval)
示例#29
0
def renew_license():

    ldap_properties_fn = '/etc/jans/conf/jans-ldap.properties'
    salt_fn = '/etc/jans/conf/salt'
    encode_fn = '/opt/jans/bin/encode.py'

    for fn in (ldap_properties_fn, salt_fn, encode_fn):
        if not os.path.exists(fn):
            print("Not found:", fn)
            return

    prop = {'bindDN': '', 'bindPassword': '', 'servers': ''}
    content = open(ldap_properties_fn).readlines()
    for l in content:
        ls = l.strip()
        if ls and not ls[0] == '#':
            for p in prop:
                if ls.startswith(p):
                    v = ls[len(p):].strip()[1:].strip()
                    v = v.replace('\\=', '=')
                    v = v.replace("\\'", "'")
                    v = v.replace('\\"', '"')
                    prop[p] = v

    cmd = encode_fn + ' -D ' + prop['bindPassword']
    encoded_password = os.popen(cmd).read().strip()
    if not encoded_password:
        print("Password can't be encoded")
        return

    ldap_server = prop['servers'].split(',')[0].strip()
    ldap_host, ldap_port = ldap_server.split(':')

    server = ldap3.Server(ldap_host, port=int(ldap_port), use_ssl=True)
    ldap_conn = ldap3.Connection(server,
                                 user=prop['bindDN'],
                                 password=encoded_password)
    try:
        ldap_conn.bind()
    except:
        print("Can't connect to ldap server")
        return

    scr_dn = 'inum=92F0-BF9E,ou=scripts,o=jans'

    ldap_conn.search(search_base=scr_dn,
                     search_scope=ldap3.BASE,
                     search_filter='(objectClass=*)',
                     attributes=['jansConfProperty'])

    result = ldap_conn.response

    if not result:
        print("Can't find Super Gluu script with dn {} in ldap".format(scr_dn))
        return

    for oxprop_s in result[0]['attributes']['jansConfProperty']:
        oxprop = json.loads(oxprop_s)
        if oxprop['value1'] == 'license_file':
            license_fn = oxprop['value2']
            break
    else:
        print("Super gluu license file not found in ldap")
        return

    if not os.path.exists(license_fn):
        print("Super gluu license file {} does not exist".format(license_fn))
        return

    with open(license_fn) as f:
        license_js = json.load(f)

    licenseId = license_js.get('licenseId')

    if not licenseId:
        print(license_fn, " does not include licenseId")
        return

    url_metadata = 'https://license.gluu.org/oxLicense/rest/metadata?licenseId=' + licenseId

    try:
        url_metadata_fd = urllib.urlopen(url_metadata)
        metadata_s = url_metadata_fd.read()

    except:
        print("Can't read from", url_metadata)
        return

    try:
        metadata = json.loads(metadata_s)
    except:
        print("Can't load json from", metadata_s)
        return

    if 'expiration_date' in metadata:
        expiration_date = metadata['expiration_date']
    else:
        print("Can't get expiration_date from json", metadata)
        return

    seconds_left = int(expiration_date / 1000) - time.time()
    a_day = 24 * 60 * 60

    if seconds_left >= a_day:
        print(int(seconds_left / a_day),
              "days left to expire. No need to renew")
        return

    url = 'https://license.gluu.org/oxLicense/rest/generate?licenseId=' + licenseId
    try:
        url_fd = urllib.urlopen(url)
        data_s = url_fd.read()

    except:
        print("Can't read from", url)
        return

    try:
        data = json.loads(data_s)
    except:
        print("Can't load json from", data)
        return

    if data and data[0].get('license', '').startswith('rO'):
        license_js['license'] = data[0]['license']
        shutil.copyfile(license_fn,
                        license_fn + '.back_' + time.ctime().replace(' ', '_'))
        with open(license_fn, 'w') as w:
            json.dump(license_js, w, indent=2)

    else:
        print("Data read from", url, "does not contain valid license")
        return

    print("Super Gluu license was renewed successfully")
示例#30
0
def get_ldap_connection(host, user, password):
    """ Returns a connection to the LDAP host
    """
    server = ldap3.Server(host)
    conn = ldap3.Connection(server, user, password, auto_bind=True)
    return conn