summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuriy Taraday <yorik.sar@gmail.com>2011-07-29 15:28:09 +0400
committerDolph Mathews <dolph.mathews@rackspace.com>2011-08-10 11:51:55 -0500
commit5e78bb42c8af5c014f5fc942b94fa8ab06f2f88e (patch)
tree38e585b18392fb00f6aa77870f1cd5a49b3659cf
parentd24c0108d684b8e9b79b3bbaeddd1f6e9032cea3 (diff)
downloadkeystone-5e78bb42c8af5c014f5fc942b94fa8ab06f2f88e.tar.gz
keystone-5e78bb42c8af5c014f5fc942b94fa8ab06f2f88e.tar.xz
keystone-5e78bb42c8af5c014f5fc942b94fa8ab06f2f88e.zip
Add wrapper for real LDAP connection with logging and type converting.
Also includes PEP8 fixes. Change-Id: I03f38f1e99a62f665276fff718669a5481d0725e
-rwxr-xr-xkeystone/backends/api.py4
-rw-r--r--keystone/backends/ldap/api/__init__.py91
-rwxr-xr-xkeystone/test/unit/test_ec2_authn.py8
3 files changed, 94 insertions, 9 deletions
diff --git a/keystone/backends/api.py b/keystone/backends/api.py
index c29f9db9..8f022d46 100755
--- a/keystone/backends/api.py
+++ b/keystone/backends/api.py
@@ -299,10 +299,10 @@ class BaseServiceAPI:
class BaseCredentialsAPI(object):
def create(self, values):
raise NotImplementedError
-
+
def delete(self, id):
raise NotImplementedError
-
+
def get(self, id):
raise NotImplementedError
diff --git a/keystone/backends/ldap/api/__init__.py b/keystone/backends/ldap/api/__init__.py
index d0f6dd18..615fc6ee 100644
--- a/keystone/backends/ldap/api/__init__.py
+++ b/keystone/backends/ldap/api/__init__.py
@@ -1,10 +1,91 @@
import ldap
+import logging
from .. import fakeldap
from .tenant import TenantAPI
from .user import UserAPI
from .role import RoleAPI
+LOG = logging.getLogger('keystone.backends.ldap.api')
+
+
+def py2ldap(val):
+ if isinstance(val, str):
+ return val
+ elif isinstance(val, bool):
+ return 'TRUE' if val else 'FALSE'
+ else:
+ return str(val)
+
+LDAP_VALUES = {
+ 'TRUE': True,
+ 'FALSE': False,
+}
+
+
+def ldap2py(val):
+ try:
+ return LDAP_VALUES[val]
+ except KeyError:
+ pass
+ try:
+ return int(val)
+ except ValueError:
+ pass
+ return val
+
+
+def safe_iter(attrs):
+ if attrs is None:
+ return
+ elif isinstance(attrs, list):
+ for e in attrs:
+ yield e
+ else:
+ yield attrs
+
+
+class LDAPWrapper(object):
+ def __init__(self, url):
+ LOG.debug("LDAP init: url=%s", url)
+ self.conn = ldap.initialize(url)
+
+ def simple_bind_s(self, user, password):
+ LOG.debug("LDAP bind: dn=%s", user)
+ return self.conn.simple_bind_s(user, password)
+
+ def add_s(self, dn, attrs):
+ ldap_attrs = [(typ, map(py2ldap, safe_iter(values)))
+ for typ, values in attrs]
+ if LOG.isEnabledFor(logging.DEBUG):
+ sane_attrs = [(typ, values if typ != 'userPassword' else ['****'])
+ for typ, values in ldap_attrs]
+ LOG.debug("LDAP add: dn=%s, attrs=%s", dn, sane_attrs)
+ return self.conn.add_s(dn, ldap_attrs)
+
+ def search_s(self, dn, scope, query):
+ if LOG.isEnabledFor(logging.DEBUG):
+ LOG.debug("LDAP search: dn=%s, scope=%s, query=%s", dn,
+ fakeldap.scope_names[scope], query)
+ res = self.conn.search_s(dn, scope, query)
+ return [(dn, dict([(typ, map(ldap2py, values))
+ for typ, values in attrs.iteritems()]))
+ for dn, attrs in res]
+
+ def modify_s(self, dn, modlist):
+ ldap_modlist = [(op, typ, None if values is None else
+ map(py2ldap, safe_iter(values)))
+ for op, typ, values in modlist]
+ if LOG.isEnabledFor(logging.DEBUG):
+ sane_modlist = [(op, typ, values if typ != 'userPassword'
+ else ['****']) for op, typ, values in ldap_modlist]
+ LOG.debug("LDAP modify: dn=%s, modlist=%s", dn, sane_modlist)
+ return self.conn.modify_s(dn, ldap_modlist)
+
+ def delete_s(self, dn):
+ LOG.debug("LDAP delete: dn=%s", dn)
+ return self.conn.delete_s(dn)
+
class API(object):
apis = ['tenant', 'user', 'role']
@@ -17,10 +98,14 @@ class API(object):
self.user = UserAPI(self, options)
self.role = RoleAPI(self, options)
- def get_connection(self):
+ def get_connection(self, user=None, password=None):
if self.LDAP_URL.startswith('fake://'):
conn = fakeldap.initialize(self.LDAP_URL)
else:
- conn = ldap.initialize(self.LDAP_URL)
- conn.simple_bind_s(self.LDAP_USER, self.LDAP_PASSWORD)
+ conn = LDAPWrapper(self.LDAP_URL)
+ if user is None:
+ user = self.LDAP_USER
+ if password is None:
+ password = self.LDAP_PASSWORD
+ conn.simple_bind_s(user, password)
return conn
diff --git a/keystone/test/unit/test_ec2_authn.py b/keystone/test/unit/test_ec2_authn.py
index 34d36066..716ec701 100755
--- a/keystone/test/unit/test_ec2_authn.py
+++ b/keystone/test/unit/test_ec2_authn.py
@@ -62,7 +62,7 @@ class EC2AuthnMethods(base.ServiceAPITest):
obj_creds = auth.Ec2Credentials(**credentials)
credentials['signature'] = sign.generate(obj_creds)
body = {
- "ec2Credentials": credentials
+ "ec2Credentials": credentials,
}
req.body = json.dumps(body)
self.get_response()
@@ -72,7 +72,7 @@ class EC2AuthnMethods(base.ServiceAPITest):
u'serviceCatalog': {},
u'token': {
u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"),
- u'id': self.auth_token_id
+ u'id': self.auth_token_id,
}
}
}
@@ -113,7 +113,7 @@ class EC2AuthnMethods(base.ServiceAPITest):
obj_creds = auth.Ec2Credentials(**credentials)
credentials['signature'] = sign.generate(obj_creds)
body = {
- "ec2Credentials": credentials
+ "ec2Credentials": credentials,
}
req.body = json.dumps(body)
self.get_response()
@@ -161,7 +161,7 @@ class EC2AuthnMethods(base.ServiceAPITest):
obj_creds = auth.Ec2Credentials(**credentials)
credentials['signature'] = sign.generate(obj_creds)
body = {
- "ec2Credentials": credentials
+ "ec2Credentials": credentials,
}
req.body = json.dumps(body)
self.get_response()