labs-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a..@apache.org
Subject svn commit: r1522628 - in /labs/panopticon: requirements.txt src/asf/data/ldap.py tests/test_ldap.py
Date Thu, 12 Sep 2013 15:38:23 GMT
Author: adc
Date: Thu Sep 12 15:38:22 2013
New Revision: 1522628

URL: http://svn.apache.org/r1522628
Log:
Handy LDAP data

Added:
    labs/panopticon/src/asf/data/ldap.py
    labs/panopticon/tests/test_ldap.py
Modified:
    labs/panopticon/requirements.txt

Modified: labs/panopticon/requirements.txt
URL: http://svn.apache.org/viewvc/labs/panopticon/requirements.txt?rev=1522628&r1=1522627&r2=1522628&view=diff
==============================================================================
--- labs/panopticon/requirements.txt (original)
+++ labs/panopticon/requirements.txt Thu Sep 12 15:38:22 2013
@@ -3,4 +3,5 @@ brownie
 keyring==1.6.1
 mock
 nose
+python-ldap
 restkit

Added: labs/panopticon/src/asf/data/ldap.py
URL: http://svn.apache.org/viewvc/labs/panopticon/src/asf/data/ldap.py?rev=1522628&view=auto
==============================================================================
--- labs/panopticon/src/asf/data/ldap.py (added)
+++ labs/panopticon/src/asf/data/ldap.py Thu Sep 12 15:38:22 2013
@@ -0,0 +1,172 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+"""
+  LDAP Access
+"""
+
+from __future__ import absolute_import
+from logging import getLogger
+import os
+
+import ldap
+
+
+LDAP_URL = 'ldaps://ldap-tunnel.apache.org:6636'
+LDAP_TLS_CACERTFILE = '/etc/openldap/asf-ldap-client.pem'
+LDAP_BASE = 'ou=people,dc=apache,dc=org'
+
+log = getLogger(__name__)
+
+
+class LDAP(object):
+    """
+      Read-only LDAP access to ASF's Active Directory Server.
+
+      Example::
+
+        ldap = asf.data.ldap.LDAP()
+
+        res  = ldap.find_by_common_name('Alan Cabrera')
+        res  = ldap.find_by_username('adc')
+
+        if ldap.is_valid_account('adc'):
+          # Ok!
+          ...
+    """
+
+    def __init__(self, LDAP_URL=None, TLS_CA_cert_file=None):
+        """
+          Connect to ASF Active Directory Server.
+
+          :param LDAP_URL: LDAP URL to use to connect to ASF Active Directory Server
+          :param TLS_CA_cert_file: TLS CA certificate file to use to connect to ASF Active
Directory Server
+        """
+        self.base = LDAP_BASE
+        self.ldap = _ldap_cnx(LDAP_URL, TLS_CA_cert_file)
+        self.ldap.simple_bind_s()
+
+
+    def search(self, search_filter, attributes=None):
+        """
+          Perform a search against the LDAP server.
+
+          :param search_filter: An LDAP search filter.
+          :param attributes: LDAP attributes to return. Defaults to all ('*').
+
+          :return: Returns a list of dicts or None if no results were found.
+        """
+
+        if isinstance(attributes, str):
+            attributes = [attributes]
+
+        if attributes is None:
+            attributes = ['*']
+
+        # With a little help for my friends..
+        if not search_filter.startswith('(') and not search_filter.endswith(')'):
+            search_filter = '(%s)' % search_filter
+
+        res = self.ldap.search_s(self.base, ldap.SCOPE_ONELEVEL, search_filter, attributes)
+
+        if res == []:
+            return None
+
+        if res[0][0] is None:
+            return None
+
+        return res
+
+    def search_first(self, search_filter, attributes=None):
+        """
+          Perform a search against the LDAP server & return the first result or None.
+
+          :param search_filter: An LDAP search filter.
+          :param attributes: LDAP attributes to return. Defaults to all ('*').
+        """
+
+        res = self.search(search_filter, attributes=attributes)
+
+        if res is None:
+            return None
+
+        if attributes and isinstance(attributes, str):
+            return res[0][1][attributes][0]
+
+        return res[0][1]
+
+    def find_by_common_name(self, name, attributes=None):
+        """
+          Find an LDAP entry by a user's "common" (full) name.
+
+          :param name: The user's full name.
+          :param attributes: LDAP attributes to return. Defaults to all ('*').
+        """
+
+        return self.search_first('(cn=%s)' % name, attributes)
+
+    def find_by_username(self, username, attributes=None):
+        """
+          Find an LDAP entry by a user's login name.
+
+          :param username: The user's full name.
+          :param attributes: LDAP attributes to return. Defaults to all ('*').
+        """
+
+        return self.search_first('(uid=%s)' % username, attributes)
+
+    def is_valid_account(self, username):
+        """ Check if the username is valid in the directory. Returns `True` or `False`. """
+        res = self.search_first('(uid=%s)' % username, 'uid')
+
+        if res and res == username:
+            return True
+
+        return False
+
+
+def cacert_file():
+    """ Return the path to the CA Cert file to validate the TLS connection. """
+    tls_cacert_file = os.environ.get('PANOPTICON_LDAP_TLS_CACERTFILE', LDAP_TLS_CACERTFILE)
+
+    log.debug('Obtained %s for LDAP TLS certificate file', tls_cacert_file)
+
+    return tls_cacert_file
+
+
+def ldap_url():
+    """ Return the path to the CA Cert file to validate the TLS connection. """
+    url = os.environ.get('PANOPTICON_LDAP_URL', LDAP_URL)
+
+    log.debug('Obtained %s for LDAP URL', url)
+
+    return url
+
+
+def _ldap_cnx(LDAP_URL=None, TLS_CA_cert_file=None):
+    """ Gets an LDAP connection and makes sure the cert file option is set. """
+    TLS_CA_cert_file = TLS_CA_cert_file or cacert_file()
+    ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, TLS_CA_cert_file)
+
+    LDAP_URL = LDAP_URL or ldap_url()
+
+    cnx = ldap.initialize(LDAP_URL)
+    cnx.set_option(ldap.OPT_REFERRALS, 0)
+
+    return cnx

Added: labs/panopticon/tests/test_ldap.py
URL: http://svn.apache.org/viewvc/labs/panopticon/tests/test_ldap.py?rev=1522628&view=auto
==============================================================================
--- labs/panopticon/tests/test_ldap.py (added)
+++ labs/panopticon/tests/test_ldap.py Thu Sep 12 15:38:22 2013
@@ -0,0 +1,56 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from nose.tools import assert_equals, assert_raises
+
+from asf.data.ldap import LDAP
+
+
+def test_find_by_username():
+    ldap = LDAP()
+
+    result = ldap.find_by_username('adc')
+
+    for k, v in result.iteritems():
+        print k, v
+
+    assert_equals(['adc'], result['uid'])
+    assert_equals(['Alan Cabrera'], result['cn'])
+
+    assert ldap.is_valid_account('adc')
+
+
+def test_is_valid_account():
+    ldap = LDAP()
+
+    assert ldap.is_valid_account('adc')
+
+
+def test_find_by_common_name():
+    ldap = LDAP()
+
+    result = ldap.find_by_common_name('Alan Cabrera')
+
+    for k, v in result.iteritems():
+        print k, v
+
+    assert_equals(['adc'], result['uid'])
+    assert_equals(['Alan Cabrera'], result['cn'])
+
+    assert ldap.is_valid_account('adc')



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org


Mime
View raw message