PEP8/pylint cleanup in bin and nova/auth.
This commit is contained in:
@@ -29,4 +29,4 @@ if __name__ == '__main__':
|
|||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
application = service.ComputeService.create()
|
application = service.ComputeService.create() # pylint: disable-msg=C0103
|
||||||
|
|||||||
@@ -40,29 +40,29 @@ from nova.network import service
|
|||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
|
|
||||||
def add_lease(_mac, ip, _hostname, _interface):
|
def add_lease(_mac, ip_address, _hostname, _interface):
|
||||||
"""Set the IP that was assigned by the DHCP server."""
|
"""Set the IP that was assigned by the DHCP server."""
|
||||||
if FLAGS.fake_rabbit:
|
if FLAGS.fake_rabbit:
|
||||||
service.VlanNetworkService().lease_ip(ip)
|
service.VlanNetworkService().lease_ip(ip_address)
|
||||||
else:
|
else:
|
||||||
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
|
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
|
||||||
{"method": "lease_ip",
|
{"method": "lease_ip",
|
||||||
"args": {"fixed_ip": ip}})
|
"args": {"fixed_ip": ip_address}})
|
||||||
|
|
||||||
|
|
||||||
def old_lease(_mac, _ip, _hostname, _interface):
|
def old_lease(_mac, _ip_address, _hostname, _interface):
|
||||||
"""Do nothing, just an old lease update."""
|
"""Do nothing, just an old lease update."""
|
||||||
logging.debug("Adopted old lease or got a change of mac/hostname")
|
logging.debug("Adopted old lease or got a change of mac/hostname")
|
||||||
|
|
||||||
|
|
||||||
def del_lease(_mac, ip, _hostname, _interface):
|
def del_lease(_mac, ip_address, _hostname, _interface):
|
||||||
"""Called when a lease expires."""
|
"""Called when a lease expires."""
|
||||||
if FLAGS.fake_rabbit:
|
if FLAGS.fake_rabbit:
|
||||||
service.VlanNetworkService().release_ip(ip)
|
service.VlanNetworkService().release_ip(ip_address)
|
||||||
else:
|
else:
|
||||||
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
|
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
|
||||||
{"method": "release_ip",
|
{"method": "release_ip",
|
||||||
"args": {"fixed_ip": ip}})
|
"args": {"fixed_ip": ip_address}})
|
||||||
|
|
||||||
|
|
||||||
def init_leases(interface):
|
def init_leases(interface):
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ from nova.objectstore import image
|
|||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
api_url = 'https://imagestore.canonical.com/api/dashboard'
|
API_URL = 'https://imagestore.canonical.com/api/dashboard'
|
||||||
|
|
||||||
|
|
||||||
def get_images():
|
def get_images():
|
||||||
"""Get a list of the images from the imagestore URL."""
|
"""Get a list of the images from the imagestore URL."""
|
||||||
images = json.load(urllib2.urlopen(api_url))['images']
|
images = json.load(urllib2.urlopen(API_URL))['images']
|
||||||
images = [img for img in images if img['title'].find('amd64') > -1]
|
images = [img for img in images if img['title'].find('amd64') > -1]
|
||||||
return images
|
return images
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,10 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
logging.warn('Starting instance monitor')
|
logging.warn('Starting instance monitor')
|
||||||
m = monitor.InstanceMonitor()
|
# pylint: disable-msg=C0103
|
||||||
|
monitor = monitor.InstanceMonitor()
|
||||||
|
|
||||||
# This is the parent service that twistd will be looking for when it
|
# This is the parent service that twistd will be looking for when it
|
||||||
# parses this file, return it so that we can get it into globals below
|
# parses this file, return it so that we can get it into globals below
|
||||||
application = service.Application('nova-instancemonitor')
|
application = service.Application('nova-instancemonitor')
|
||||||
m.setServiceParent(application)
|
monitor.setServiceParent(application)
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ class ProjectCommands(object):
|
|||||||
f.write(zip_file)
|
f.write(zip_file)
|
||||||
|
|
||||||
|
|
||||||
categories = [
|
CATEGORIES = [
|
||||||
('user', UserCommands),
|
('user', UserCommands),
|
||||||
('project', ProjectCommands),
|
('project', ProjectCommands),
|
||||||
('role', RoleCommands),
|
('role', RoleCommands),
|
||||||
@@ -258,11 +258,11 @@ def main():
|
|||||||
if len(argv) < 1:
|
if len(argv) < 1:
|
||||||
print script_name + " category action [<args>]"
|
print script_name + " category action [<args>]"
|
||||||
print "Available categories:"
|
print "Available categories:"
|
||||||
for k, _ in categories:
|
for k, _ in CATEGORIES:
|
||||||
print "\t%s" % k
|
print "\t%s" % k
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
category = argv.pop(0)
|
category = argv.pop(0)
|
||||||
matches = lazy_match(category, categories)
|
matches = lazy_match(category, CATEGORIES)
|
||||||
# instantiate the command group object
|
# instantiate the command group object
|
||||||
category, fn = matches[0]
|
category, fn = matches[0]
|
||||||
command_object = fn()
|
command_object = fn()
|
||||||
|
|||||||
@@ -33,4 +33,5 @@ if __name__ == '__main__':
|
|||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
|
# pylint: disable-msg=C0103
|
||||||
application = service.type_to_class(FLAGS.network_type).create()
|
application = service.type_to_class(FLAGS.network_type).create()
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
utils.default_flagfile()
|
utils.default_flagfile()
|
||||||
application = handler.get_application()
|
application = handler.get_application() # pylint: disable-msg=C0103
|
||||||
|
|||||||
@@ -29,4 +29,4 @@ if __name__ == '__main__':
|
|||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
application = service.VolumeService.create()
|
application = service.VolumeService.create() # pylint: disable-msg=C0103
|
||||||
|
|||||||
@@ -35,15 +35,18 @@ MOD_ADD = 0
|
|||||||
MOD_DELETE = 1
|
MOD_DELETE = 1
|
||||||
|
|
||||||
|
|
||||||
class NO_SUCH_OBJECT(Exception):
|
class NO_SUCH_OBJECT(Exception): # pylint: disable-msg=C0103
|
||||||
|
"""Duplicate exception class from real LDAP module."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class OBJECT_CLASS_VIOLATION(Exception):
|
class OBJECT_CLASS_VIOLATION(Exception): # pylint: disable-msg=C0103
|
||||||
|
"""Duplicate exception class from real LDAP module."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def initialize(uri):
|
def initialize(_uri):
|
||||||
|
"""Opens a fake connection with an LDAP server."""
|
||||||
return FakeLDAP()
|
return FakeLDAP()
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +71,7 @@ def _match_query(query, attrs):
|
|||||||
# cut off the ! and the nested parentheses
|
# cut off the ! and the nested parentheses
|
||||||
return not _match_query(query[2:-1], attrs)
|
return not _match_query(query[2:-1], attrs)
|
||||||
|
|
||||||
(k, sep, v) = inner.partition('=')
|
(k, _sep, v) = inner.partition('=')
|
||||||
return _match(k, v, attrs)
|
return _match(k, v, attrs)
|
||||||
|
|
||||||
|
|
||||||
@@ -85,20 +88,20 @@ def _paren_groups(source):
|
|||||||
if source[pos] == ')':
|
if source[pos] == ')':
|
||||||
count -= 1
|
count -= 1
|
||||||
if count == 0:
|
if count == 0:
|
||||||
result.append(source[start:pos+1])
|
result.append(source[start:pos + 1])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _match(k, v, attrs):
|
def _match(key, value, attrs):
|
||||||
"""Match a given key and value against an attribute list."""
|
"""Match a given key and value against an attribute list."""
|
||||||
if k not in attrs:
|
if key not in attrs:
|
||||||
return False
|
return False
|
||||||
if k != "objectclass":
|
if key != "objectclass":
|
||||||
return v in attrs[k]
|
return value in attrs[key]
|
||||||
# it is an objectclass check, so check subclasses
|
# it is an objectclass check, so check subclasses
|
||||||
values = _subs(v)
|
values = _subs(value)
|
||||||
for value in values:
|
for v in values:
|
||||||
if value in attrs[k]:
|
if v in attrs[key]:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -145,6 +148,7 @@ def _to_json(unencoded):
|
|||||||
class FakeLDAP(object):
|
class FakeLDAP(object):
|
||||||
#TODO(vish): refactor this class to use a wrapper instead of accessing
|
#TODO(vish): refactor this class to use a wrapper instead of accessing
|
||||||
# redis directly
|
# redis directly
|
||||||
|
"""Fake LDAP connection."""
|
||||||
|
|
||||||
def simple_bind_s(self, dn, password):
|
def simple_bind_s(self, dn, password):
|
||||||
"""This method is ignored, but provided for compatibility."""
|
"""This method is ignored, but provided for compatibility."""
|
||||||
@@ -207,6 +211,7 @@ class FakeLDAP(object):
|
|||||||
# get the attributes from redis
|
# get the attributes from redis
|
||||||
attrs = redis.hgetall(key)
|
attrs = redis.hgetall(key)
|
||||||
# turn the values from redis into lists
|
# turn the values from redis into lists
|
||||||
|
# pylint: disable-msg=E1103
|
||||||
attrs = dict([(k, _from_json(v))
|
attrs = dict([(k, _from_json(v))
|
||||||
for k, v in attrs.iteritems()])
|
for k, v in attrs.iteritems()])
|
||||||
# filter the objects by query
|
# filter the objects by query
|
||||||
@@ -215,12 +220,12 @@ class FakeLDAP(object):
|
|||||||
attrs = dict([(k, v) for k, v in attrs.iteritems()
|
attrs = dict([(k, v) for k, v in attrs.iteritems()
|
||||||
if not fields or k in fields])
|
if not fields or k in fields])
|
||||||
objects.append((key[len(self.__redis_prefix):], attrs))
|
objects.append((key[len(self.__redis_prefix):], attrs))
|
||||||
|
# pylint: enable-msg=E1103
|
||||||
if objects == []:
|
if objects == []:
|
||||||
raise NO_SUCH_OBJECT()
|
raise NO_SUCH_OBJECT()
|
||||||
return objects
|
return objects
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def __redis_prefix(self):
|
def __redis_prefix(self): # pylint: disable-msg=R0201
|
||||||
|
"""Get the prefix to use for all redis keys."""
|
||||||
return 'ldap:'
|
return 'ldap:'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -63,14 +63,18 @@ flags.DEFINE_string('ldap_developer',
|
|||||||
# to define a set interface for AuthDrivers. I'm delaying
|
# to define a set interface for AuthDrivers. I'm delaying
|
||||||
# creating this now because I'm expecting an auth refactor
|
# creating this now because I'm expecting an auth refactor
|
||||||
# in which we may want to change the interface a bit more.
|
# in which we may want to change the interface a bit more.
|
||||||
|
|
||||||
|
|
||||||
class LdapDriver(object):
|
class LdapDriver(object):
|
||||||
"""Ldap Auth driver
|
"""Ldap Auth driver
|
||||||
|
|
||||||
Defines enter and exit and therefore supports the with/as syntax.
|
Defines enter and exit and therefore supports the with/as syntax.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Imports the LDAP module"""
|
"""Imports the LDAP module"""
|
||||||
self.ldap = __import__('ldap')
|
self.ldap = __import__('ldap')
|
||||||
|
self.conn = None
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
"""Creates the connection to LDAP"""
|
"""Creates the connection to LDAP"""
|
||||||
@@ -78,7 +82,7 @@ class LdapDriver(object):
|
|||||||
self.conn.simple_bind_s(FLAGS.ldap_user_dn, FLAGS.ldap_password)
|
self.conn.simple_bind_s(FLAGS.ldap_user_dn, FLAGS.ldap_password)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
"""Destroys the connection to LDAP"""
|
"""Destroys the connection to LDAP"""
|
||||||
self.conn.unbind_s()
|
self.conn.unbind_s()
|
||||||
return False
|
return False
|
||||||
@@ -123,11 +127,11 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def get_projects(self, uid=None):
|
def get_projects(self, uid=None):
|
||||||
"""Retrieve list of projects"""
|
"""Retrieve list of projects"""
|
||||||
filter = '(objectclass=novaProject)'
|
pattern = '(objectclass=novaProject)'
|
||||||
if uid:
|
if uid:
|
||||||
filter = "(&%s(member=%s))" % (filter, self.__uid_to_dn(uid))
|
pattern = "(&%s(member=%s))" % (pattern, self.__uid_to_dn(uid))
|
||||||
attrs = self.__find_objects(FLAGS.ldap_project_subtree,
|
attrs = self.__find_objects(FLAGS.ldap_project_subtree,
|
||||||
filter)
|
pattern)
|
||||||
return [self.__to_project(attr) for attr in attrs]
|
return [self.__to_project(attr) for attr in attrs]
|
||||||
|
|
||||||
def create_user(self, name, access_key, secret_key, is_admin):
|
def create_user(self, name, access_key, secret_key, is_admin):
|
||||||
@@ -194,8 +198,7 @@ class LdapDriver(object):
|
|||||||
('cn', [name]),
|
('cn', [name]),
|
||||||
('description', [description]),
|
('description', [description]),
|
||||||
('projectManager', [manager_dn]),
|
('projectManager', [manager_dn]),
|
||||||
('member', members)
|
('member', members)]
|
||||||
]
|
|
||||||
self.conn.add_s('cn=%s,%s' % (name, FLAGS.ldap_project_subtree), attr)
|
self.conn.add_s('cn=%s,%s' % (name, FLAGS.ldap_project_subtree), attr)
|
||||||
return self.__to_project(dict(attr))
|
return self.__to_project(dict(attr))
|
||||||
|
|
||||||
@@ -287,7 +290,6 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def __key_pair_exists(self, uid, key_name):
|
def __key_pair_exists(self, uid, key_name):
|
||||||
"""Check if key pair exists"""
|
"""Check if key pair exists"""
|
||||||
return self.get_user(uid) != None
|
|
||||||
return self.get_key_pair(uid, key_name) != None
|
return self.get_key_pair(uid, key_name) != None
|
||||||
|
|
||||||
def __project_exists(self, project_id):
|
def __project_exists(self, project_id):
|
||||||
@@ -310,7 +312,7 @@ class LdapDriver(object):
|
|||||||
except self.ldap.NO_SUCH_OBJECT:
|
except self.ldap.NO_SUCH_OBJECT:
|
||||||
return []
|
return []
|
||||||
# just return the DNs
|
# just return the DNs
|
||||||
return [dn for dn, attributes in res]
|
return [dn for dn, _attributes in res]
|
||||||
|
|
||||||
def __find_objects(self, dn, query=None, scope=None):
|
def __find_objects(self, dn, query=None, scope=None):
|
||||||
"""Find objects by query"""
|
"""Find objects by query"""
|
||||||
@@ -346,7 +348,8 @@ class LdapDriver(object):
|
|||||||
for key in keys:
|
for key in keys:
|
||||||
self.delete_key_pair(uid, key['name'])
|
self.delete_key_pair(uid, key['name'])
|
||||||
|
|
||||||
def __role_to_dn(self, role, project_id=None):
|
@staticmethod
|
||||||
|
def __role_to_dn(role, project_id=None):
|
||||||
"""Convert role to corresponding dn"""
|
"""Convert role to corresponding dn"""
|
||||||
if project_id == None:
|
if project_id == None:
|
||||||
return FLAGS.__getitem__("ldap_%s" % role).value
|
return FLAGS.__getitem__("ldap_%s" % role).value
|
||||||
@@ -356,7 +359,7 @@ class LdapDriver(object):
|
|||||||
FLAGS.ldap_project_subtree)
|
FLAGS.ldap_project_subtree)
|
||||||
|
|
||||||
def __create_group(self, group_dn, name, uid,
|
def __create_group(self, group_dn, name, uid,
|
||||||
description, member_uids = None):
|
description, member_uids=None):
|
||||||
"""Create a group"""
|
"""Create a group"""
|
||||||
if self.__group_exists(group_dn):
|
if self.__group_exists(group_dn):
|
||||||
raise exception.Duplicate("Group can't be created because "
|
raise exception.Duplicate("Group can't be created because "
|
||||||
@@ -375,8 +378,7 @@ class LdapDriver(object):
|
|||||||
('objectclass', ['groupOfNames']),
|
('objectclass', ['groupOfNames']),
|
||||||
('cn', [name]),
|
('cn', [name]),
|
||||||
('description', [description]),
|
('description', [description]),
|
||||||
('member', members)
|
('member', members)]
|
||||||
]
|
|
||||||
self.conn.add_s(group_dn, attr)
|
self.conn.add_s(group_dn, attr)
|
||||||
|
|
||||||
def __is_in_group(self, uid, group_dn):
|
def __is_in_group(self, uid, group_dn):
|
||||||
@@ -402,9 +404,7 @@ class LdapDriver(object):
|
|||||||
if self.__is_in_group(uid, group_dn):
|
if self.__is_in_group(uid, group_dn):
|
||||||
raise exception.Duplicate("User %s is already a member of "
|
raise exception.Duplicate("User %s is already a member of "
|
||||||
"the group %s" % (uid, group_dn))
|
"the group %s" % (uid, group_dn))
|
||||||
attr = [
|
attr = [(self.ldap.MOD_ADD, 'member', self.__uid_to_dn(uid))]
|
||||||
(self.ldap.MOD_ADD, 'member', self.__uid_to_dn(uid))
|
|
||||||
]
|
|
||||||
self.conn.modify_s(group_dn, attr)
|
self.conn.modify_s(group_dn, attr)
|
||||||
|
|
||||||
def __remove_from_group(self, uid, group_dn):
|
def __remove_from_group(self, uid, group_dn):
|
||||||
@@ -432,7 +432,7 @@ class LdapDriver(object):
|
|||||||
self.conn.modify_s(group_dn, attr)
|
self.conn.modify_s(group_dn, attr)
|
||||||
except self.ldap.OBJECT_CLASS_VIOLATION:
|
except self.ldap.OBJECT_CLASS_VIOLATION:
|
||||||
logging.debug("Attempted to remove the last member of a group. "
|
logging.debug("Attempted to remove the last member of a group. "
|
||||||
"Deleting the group at %s instead." % group_dn )
|
"Deleting the group at %s instead.", group_dn)
|
||||||
self.__delete_group(group_dn)
|
self.__delete_group(group_dn)
|
||||||
|
|
||||||
def __remove_from_all(self, uid):
|
def __remove_from_all(self, uid):
|
||||||
@@ -440,7 +440,6 @@ class LdapDriver(object):
|
|||||||
if not self.__user_exists(uid):
|
if not self.__user_exists(uid):
|
||||||
raise exception.NotFound("User %s can't be removed from all "
|
raise exception.NotFound("User %s can't be removed from all "
|
||||||
"because the user doesn't exist" % (uid,))
|
"because the user doesn't exist" % (uid,))
|
||||||
dn = self.__uid_to_dn(uid)
|
|
||||||
role_dns = self.__find_group_dns_with_member(
|
role_dns = self.__find_group_dns_with_member(
|
||||||
FLAGS.role_project_subtree, uid)
|
FLAGS.role_project_subtree, uid)
|
||||||
for role_dn in role_dns:
|
for role_dn in role_dns:
|
||||||
@@ -448,7 +447,7 @@ class LdapDriver(object):
|
|||||||
project_dns = self.__find_group_dns_with_member(
|
project_dns = self.__find_group_dns_with_member(
|
||||||
FLAGS.ldap_project_subtree, uid)
|
FLAGS.ldap_project_subtree, uid)
|
||||||
for project_dn in project_dns:
|
for project_dn in project_dns:
|
||||||
self.__safe_remove_from_group(uid, role_dn)
|
self.__safe_remove_from_group(uid, project_dn)
|
||||||
|
|
||||||
def __delete_group(self, group_dn):
|
def __delete_group(self, group_dn):
|
||||||
"""Delete Group"""
|
"""Delete Group"""
|
||||||
@@ -461,7 +460,8 @@ class LdapDriver(object):
|
|||||||
for role_dn in self.__find_role_dns(project_dn):
|
for role_dn in self.__find_role_dns(project_dn):
|
||||||
self.__delete_group(role_dn)
|
self.__delete_group(role_dn)
|
||||||
|
|
||||||
def __to_user(self, attr):
|
@staticmethod
|
||||||
|
def __to_user(attr):
|
||||||
"""Convert ldap attributes to User object"""
|
"""Convert ldap attributes to User object"""
|
||||||
if attr == None:
|
if attr == None:
|
||||||
return None
|
return None
|
||||||
@@ -470,10 +470,10 @@ class LdapDriver(object):
|
|||||||
'name': attr['cn'][0],
|
'name': attr['cn'][0],
|
||||||
'access': attr['accessKey'][0],
|
'access': attr['accessKey'][0],
|
||||||
'secret': attr['secretKey'][0],
|
'secret': attr['secretKey'][0],
|
||||||
'admin': (attr['isAdmin'][0] == 'TRUE')
|
'admin': (attr['isAdmin'][0] == 'TRUE')}
|
||||||
}
|
|
||||||
|
|
||||||
def __to_key_pair(self, owner, attr):
|
@staticmethod
|
||||||
|
def __to_key_pair(owner, attr):
|
||||||
"""Convert ldap attributes to KeyPair object"""
|
"""Convert ldap attributes to KeyPair object"""
|
||||||
if attr == None:
|
if attr == None:
|
||||||
return None
|
return None
|
||||||
@@ -482,8 +482,7 @@ class LdapDriver(object):
|
|||||||
'name': attr['cn'][0],
|
'name': attr['cn'][0],
|
||||||
'owner_id': owner,
|
'owner_id': owner,
|
||||||
'public_key': attr['sshPublicKey'][0],
|
'public_key': attr['sshPublicKey'][0],
|
||||||
'fingerprint': attr['keyFingerprint'][0],
|
'fingerprint': attr['keyFingerprint'][0]}
|
||||||
}
|
|
||||||
|
|
||||||
def __to_project(self, attr):
|
def __to_project(self, attr):
|
||||||
"""Convert ldap attributes to Project object"""
|
"""Convert ldap attributes to Project object"""
|
||||||
@@ -495,21 +494,22 @@ class LdapDriver(object):
|
|||||||
'name': attr['cn'][0],
|
'name': attr['cn'][0],
|
||||||
'project_manager_id': self.__dn_to_uid(attr['projectManager'][0]),
|
'project_manager_id': self.__dn_to_uid(attr['projectManager'][0]),
|
||||||
'description': attr.get('description', [None])[0],
|
'description': attr.get('description', [None])[0],
|
||||||
'member_ids': [self.__dn_to_uid(x) for x in member_dns]
|
'member_ids': [self.__dn_to_uid(x) for x in member_dns]}
|
||||||
}
|
|
||||||
|
|
||||||
def __dn_to_uid(self, dn):
|
@staticmethod
|
||||||
|
def __dn_to_uid(dn):
|
||||||
"""Convert user dn to uid"""
|
"""Convert user dn to uid"""
|
||||||
return dn.split(',')[0].split('=')[1]
|
return dn.split(',')[0].split('=')[1]
|
||||||
|
|
||||||
def __uid_to_dn(self, dn):
|
@staticmethod
|
||||||
|
def __uid_to_dn(dn):
|
||||||
"""Convert uid to dn"""
|
"""Convert uid to dn"""
|
||||||
return 'uid=%s,%s' % (dn, FLAGS.ldap_user_subtree)
|
return 'uid=%s,%s' % (dn, FLAGS.ldap_user_subtree)
|
||||||
|
|
||||||
|
|
||||||
class FakeLdapDriver(LdapDriver):
|
class FakeLdapDriver(LdapDriver):
|
||||||
"""Fake Ldap Auth driver"""
|
"""Fake Ldap Auth driver"""
|
||||||
def __init__(self):
|
|
||||||
|
def __init__(self): # pylint: disable-msg=W0231
|
||||||
__import__('nova.auth.fakeldap')
|
__import__('nova.auth.fakeldap')
|
||||||
self.ldap = sys.modules['nova.auth.fakeldap']
|
self.ldap = sys.modules['nova.auth.fakeldap']
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ Nova authentication management
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
import string # pylint: disable-msg=W0402
|
||||||
import tempfile
|
import tempfile
|
||||||
import uuid
|
import uuid
|
||||||
import zipfile
|
import zipfile
|
||||||
@@ -194,12 +194,12 @@ class Project(AuthBase):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def vpn_ip(self):
|
def vpn_ip(self):
|
||||||
ip, port = AuthManager().get_project_vpn_data(self)
|
ip, _port = AuthManager().get_project_vpn_data(self)
|
||||||
return ip
|
return ip
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def vpn_port(self):
|
def vpn_port(self):
|
||||||
ip, port = AuthManager().get_project_vpn_data(self)
|
_ip, port = AuthManager().get_project_vpn_data(self)
|
||||||
return port
|
return port
|
||||||
|
|
||||||
def has_manager(self, user):
|
def has_manager(self, user):
|
||||||
@@ -221,10 +221,8 @@ class Project(AuthBase):
|
|||||||
return AuthManager().get_credentials(user, self)
|
return AuthManager().get_credentials(user, self)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Project('%s', '%s', '%s', '%s', %s)" % (self.id,
|
return "Project('%s', '%s', '%s', '%s', %s)" % \
|
||||||
self.name,
|
(self.id, self.name, self.project_manager_id, self.description,
|
||||||
self.project_manager_id,
|
|
||||||
self.description,
|
|
||||||
self.member_ids)
|
self.member_ids)
|
||||||
|
|
||||||
|
|
||||||
@@ -297,7 +295,7 @@ class AuthManager(object):
|
|||||||
@return: User and project that the request represents.
|
@return: User and project that the request represents.
|
||||||
"""
|
"""
|
||||||
# TODO(vish): check for valid timestamp
|
# TODO(vish): check for valid timestamp
|
||||||
(access_key, sep, project_id) = access.partition(':')
|
(access_key, _sep, project_id) = access.partition(':')
|
||||||
|
|
||||||
logging.info('Looking up user: %r', access_key)
|
logging.info('Looking up user: %r', access_key)
|
||||||
user = self.get_user_from_access_key(access_key)
|
user = self.get_user_from_access_key(access_key)
|
||||||
@@ -320,7 +318,8 @@ class AuthManager(object):
|
|||||||
raise exception.NotFound('User %s is not a member of project %s' %
|
raise exception.NotFound('User %s is not a member of project %s' %
|
||||||
(user.id, project.id))
|
(user.id, project.id))
|
||||||
if check_type == 's3':
|
if check_type == 's3':
|
||||||
expected_signature = signer.Signer(user.secret.encode()).s3_authorization(headers, verb, path)
|
sign = signer.Signer(user.secret.encode())
|
||||||
|
expected_signature = sign.s3_authorization(headers, verb, path)
|
||||||
logging.debug('user.secret: %s', user.secret)
|
logging.debug('user.secret: %s', user.secret)
|
||||||
logging.debug('expected_signature: %s', expected_signature)
|
logging.debug('expected_signature: %s', expected_signature)
|
||||||
logging.debug('signature: %s', signature)
|
logging.debug('signature: %s', signature)
|
||||||
@@ -465,7 +464,8 @@ class AuthManager(object):
|
|||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
drv.remove_role(User.safe_id(user), role, Project.safe_id(project))
|
drv.remove_role(User.safe_id(user), role, Project.safe_id(project))
|
||||||
|
|
||||||
def get_roles(self, project_roles=True):
|
@staticmethod
|
||||||
|
def get_roles(project_roles=True):
|
||||||
"""Get list of allowed roles"""
|
"""Get list of allowed roles"""
|
||||||
if project_roles:
|
if project_roles:
|
||||||
return list(set(FLAGS.allowed_roles) - set(FLAGS.global_roles))
|
return list(set(FLAGS.allowed_roles) - set(FLAGS.global_roles))
|
||||||
@@ -549,7 +549,8 @@ class AuthManager(object):
|
|||||||
return drv.remove_from_project(User.safe_id(user),
|
return drv.remove_from_project(User.safe_id(user),
|
||||||
Project.safe_id(project))
|
Project.safe_id(project))
|
||||||
|
|
||||||
def get_project_vpn_data(self, project):
|
@staticmethod
|
||||||
|
def get_project_vpn_data(project):
|
||||||
"""Gets vpn ip and port for project
|
"""Gets vpn ip and port for project
|
||||||
|
|
||||||
@type project: Project or project_id
|
@type project: Project or project_id
|
||||||
@@ -613,8 +614,10 @@ class AuthManager(object):
|
|||||||
@rtype: User
|
@rtype: User
|
||||||
@return: The new user.
|
@return: The new user.
|
||||||
"""
|
"""
|
||||||
if access == None: access = str(uuid.uuid4())
|
if access == None:
|
||||||
if secret == None: secret = str(uuid.uuid4())
|
access = str(uuid.uuid4())
|
||||||
|
if secret == None:
|
||||||
|
secret = str(uuid.uuid4())
|
||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
user_dict = drv.create_user(name, access, secret, admin)
|
user_dict = drv.create_user(name, access, secret, admin)
|
||||||
if user_dict:
|
if user_dict:
|
||||||
@@ -702,7 +705,7 @@ class AuthManager(object):
|
|||||||
|
|
||||||
network_data = vpn.NetworkData.lookup(pid)
|
network_data = vpn.NetworkData.lookup(pid)
|
||||||
if network_data:
|
if network_data:
|
||||||
configfile = open(FLAGS.vpn_client_template,"r")
|
configfile = open(FLAGS.vpn_client_template, "r")
|
||||||
s = string.Template(configfile.read())
|
s = string.Template(configfile.read())
|
||||||
configfile.close()
|
configfile.close()
|
||||||
config = s.substitute(keyfile=FLAGS.credential_key_file,
|
config = s.substitute(keyfile=FLAGS.credential_key_file,
|
||||||
@@ -717,10 +720,10 @@ class AuthManager(object):
|
|||||||
zippy.writestr(FLAGS.ca_file, crypto.fetch_ca(user.id))
|
zippy.writestr(FLAGS.ca_file, crypto.fetch_ca(user.id))
|
||||||
zippy.close()
|
zippy.close()
|
||||||
with open(zf, 'rb') as f:
|
with open(zf, 'rb') as f:
|
||||||
buffer = f.read()
|
read_buffer = f.read()
|
||||||
|
|
||||||
shutil.rmtree(tmpdir)
|
shutil.rmtree(tmpdir)
|
||||||
return buffer
|
return read_buffer
|
||||||
|
|
||||||
def get_environment_rc(self, user, project=None):
|
def get_environment_rc(self, user, project=None):
|
||||||
"""Get credential zip for user in project"""
|
"""Get credential zip for user in project"""
|
||||||
@@ -731,18 +734,18 @@ class AuthManager(object):
|
|||||||
pid = Project.safe_id(project)
|
pid = Project.safe_id(project)
|
||||||
return self.__generate_rc(user.access, user.secret, pid)
|
return self.__generate_rc(user.access, user.secret, pid)
|
||||||
|
|
||||||
def __generate_rc(self, access, secret, pid):
|
@staticmethod
|
||||||
|
def __generate_rc(access, secret, pid):
|
||||||
"""Generate rc file for user"""
|
"""Generate rc file for user"""
|
||||||
rc = open(FLAGS.credentials_template).read()
|
rc = open(FLAGS.credentials_template).read()
|
||||||
rc = rc % { 'access': access,
|
rc = rc % {'access': access,
|
||||||
'project': pid,
|
'project': pid,
|
||||||
'secret': secret,
|
'secret': secret,
|
||||||
'ec2': FLAGS.ec2_url,
|
'ec2': FLAGS.ec2_url,
|
||||||
's3': 'http://%s:%s' % (FLAGS.s3_host, FLAGS.s3_port),
|
's3': 'http://%s:%s' % (FLAGS.s3_host, FLAGS.s3_port),
|
||||||
'nova': FLAGS.ca_file,
|
'nova': FLAGS.ca_file,
|
||||||
'cert': FLAGS.credential_cert_file,
|
'cert': FLAGS.credential_cert_file,
|
||||||
'key': FLAGS.credential_key_file,
|
'key': FLAGS.credential_key_file}
|
||||||
}
|
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
def _generate_x509_cert(self, uid, pid):
|
def _generate_x509_cert(self, uid, pid):
|
||||||
@@ -753,6 +756,7 @@ class AuthManager(object):
|
|||||||
signed_cert = crypto.sign_csr(csr, pid)
|
signed_cert = crypto.sign_csr(csr, pid)
|
||||||
return (private_key, signed_cert)
|
return (private_key, signed_cert)
|
||||||
|
|
||||||
def __cert_subject(self, uid):
|
@staticmethod
|
||||||
|
def __cert_subject(uid):
|
||||||
"""Helper to generate cert subject"""
|
"""Helper to generate cert subject"""
|
||||||
return FLAGS.credential_cert_subject % (uid, utils.isotime())
|
return FLAGS.credential_cert_subject % (uid, utils.isotime())
|
||||||
|
|||||||
@@ -16,40 +16,54 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
"""Role-based access control decorators to use fpr wrapping other
|
||||||
|
methods with."""
|
||||||
|
|
||||||
from nova import exception
|
from nova import exception
|
||||||
from nova.auth import manager
|
|
||||||
|
|
||||||
|
|
||||||
def allow(*roles):
|
def allow(*roles):
|
||||||
def wrap(f):
|
"""Allow the given roles access the wrapped function."""
|
||||||
def wrapped_f(self, context, *args, **kwargs):
|
|
||||||
|
def wrap(func): # pylint: disable-msg=C0111
|
||||||
|
|
||||||
|
def wrapped_func(self, context, *args,
|
||||||
|
**kwargs): # pylint: disable-msg=C0111
|
||||||
if context.user.is_superuser():
|
if context.user.is_superuser():
|
||||||
return f(self, context, *args, **kwargs)
|
return func(self, context, *args, **kwargs)
|
||||||
for role in roles:
|
for role in roles:
|
||||||
if __matches_role(context, role):
|
if __matches_role(context, role):
|
||||||
return f(self, context, *args, **kwargs)
|
return func(self, context, *args, **kwargs)
|
||||||
raise exception.NotAuthorized()
|
raise exception.NotAuthorized()
|
||||||
return wrapped_f
|
|
||||||
|
return wrapped_func
|
||||||
|
|
||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
def deny(*roles):
|
def deny(*roles):
|
||||||
def wrap(f):
|
"""Deny the given roles access the wrapped function."""
|
||||||
def wrapped_f(self, context, *args, **kwargs):
|
|
||||||
|
def wrap(func): # pylint: disable-msg=C0111
|
||||||
|
|
||||||
|
def wrapped_func(self, context, *args,
|
||||||
|
**kwargs): # pylint: disable-msg=C0111
|
||||||
if context.user.is_superuser():
|
if context.user.is_superuser():
|
||||||
return f(self, context, *args, **kwargs)
|
return func(self, context, *args, **kwargs)
|
||||||
for role in roles:
|
for role in roles:
|
||||||
if __matches_role(context, role):
|
if __matches_role(context, role):
|
||||||
raise exception.NotAuthorized()
|
raise exception.NotAuthorized()
|
||||||
return f(self, context, *args, **kwargs)
|
return func(self, context, *args, **kwargs)
|
||||||
return wrapped_f
|
|
||||||
|
return wrapped_func
|
||||||
|
|
||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
def __matches_role(context, role):
|
def __matches_role(context, role):
|
||||||
|
"""Check if a role is allowed."""
|
||||||
if role == 'all':
|
if role == 'all':
|
||||||
return True
|
return True
|
||||||
if role == 'none':
|
if role == 'none':
|
||||||
return False
|
return False
|
||||||
return context.project.has_role(context.user.id, role)
|
return context.project.has_role(context.user.id, role)
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ from nova.exception import Error
|
|||||||
|
|
||||||
|
|
||||||
class Signer(object):
|
class Signer(object):
|
||||||
""" hacked up code from boto/connection.py """
|
"""Hacked up code from boto/connection.py"""
|
||||||
|
|
||||||
def __init__(self, secret_key):
|
def __init__(self, secret_key):
|
||||||
self.hmac = hmac.new(secret_key, digestmod=hashlib.sha1)
|
self.hmac = hmac.new(secret_key, digestmod=hashlib.sha1)
|
||||||
@@ -66,22 +66,27 @@ class Signer(object):
|
|||||||
self.hmac_256 = hmac.new(secret_key, digestmod=hashlib.sha256)
|
self.hmac_256 = hmac.new(secret_key, digestmod=hashlib.sha256)
|
||||||
|
|
||||||
def s3_authorization(self, headers, verb, path):
|
def s3_authorization(self, headers, verb, path):
|
||||||
|
"""Generate S3 authorization string."""
|
||||||
c_string = boto.utils.canonical_string(verb, path, headers)
|
c_string = boto.utils.canonical_string(verb, path, headers)
|
||||||
hmac = self.hmac.copy()
|
hmac_copy = self.hmac.copy()
|
||||||
hmac.update(c_string)
|
hmac_copy.update(c_string)
|
||||||
b64_hmac = base64.encodestring(hmac.digest()).strip()
|
b64_hmac = base64.encodestring(hmac_copy.digest()).strip()
|
||||||
return b64_hmac
|
return b64_hmac
|
||||||
|
|
||||||
def generate(self, params, verb, server_string, path):
|
def generate(self, params, verb, server_string, path):
|
||||||
|
"""Generate auth string according to what SignatureVersion is given."""
|
||||||
if params['SignatureVersion'] == '0':
|
if params['SignatureVersion'] == '0':
|
||||||
return self._calc_signature_0(params)
|
return self._calc_signature_0(params)
|
||||||
if params['SignatureVersion'] == '1':
|
if params['SignatureVersion'] == '1':
|
||||||
return self._calc_signature_1(params)
|
return self._calc_signature_1(params)
|
||||||
if params['SignatureVersion'] == '2':
|
if params['SignatureVersion'] == '2':
|
||||||
return self._calc_signature_2(params, verb, server_string, path)
|
return self._calc_signature_2(params, verb, server_string, path)
|
||||||
raise Error('Unknown Signature Version: %s' % self.SignatureVersion)
|
raise Error('Unknown Signature Version: %s' %
|
||||||
|
params['SignatureVersion'])
|
||||||
|
|
||||||
def _get_utf8_value(self, value):
|
@staticmethod
|
||||||
|
def _get_utf8_value(value):
|
||||||
|
"""Get the UTF8-encoded version of a value."""
|
||||||
if not isinstance(value, str) and not isinstance(value, unicode):
|
if not isinstance(value, str) and not isinstance(value, unicode):
|
||||||
value = str(value)
|
value = str(value)
|
||||||
if isinstance(value, unicode):
|
if isinstance(value, unicode):
|
||||||
@@ -90,10 +95,11 @@ class Signer(object):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
def _calc_signature_0(self, params):
|
def _calc_signature_0(self, params):
|
||||||
|
"""Generate AWS signature version 0 string."""
|
||||||
s = params['Action'] + params['Timestamp']
|
s = params['Action'] + params['Timestamp']
|
||||||
self.hmac.update(s)
|
self.hmac.update(s)
|
||||||
keys = params.keys()
|
keys = params.keys()
|
||||||
keys.sort(cmp = lambda x, y: cmp(x.lower(), y.lower()))
|
keys.sort(cmp=lambda x, y: cmp(x.lower(), y.lower()))
|
||||||
pairs = []
|
pairs = []
|
||||||
for key in keys:
|
for key in keys:
|
||||||
val = self._get_utf8_value(params[key])
|
val = self._get_utf8_value(params[key])
|
||||||
@@ -101,8 +107,9 @@ class Signer(object):
|
|||||||
return base64.b64encode(self.hmac.digest())
|
return base64.b64encode(self.hmac.digest())
|
||||||
|
|
||||||
def _calc_signature_1(self, params):
|
def _calc_signature_1(self, params):
|
||||||
|
"""Generate AWS signature version 1 string."""
|
||||||
keys = params.keys()
|
keys = params.keys()
|
||||||
keys.sort(cmp = lambda x, y: cmp(x.lower(), y.lower()))
|
keys.sort(cmp=lambda x, y: cmp(x.lower(), y.lower()))
|
||||||
pairs = []
|
pairs = []
|
||||||
for key in keys:
|
for key in keys:
|
||||||
self.hmac.update(key)
|
self.hmac.update(key)
|
||||||
@@ -112,30 +119,34 @@ class Signer(object):
|
|||||||
return base64.b64encode(self.hmac.digest())
|
return base64.b64encode(self.hmac.digest())
|
||||||
|
|
||||||
def _calc_signature_2(self, params, verb, server_string, path):
|
def _calc_signature_2(self, params, verb, server_string, path):
|
||||||
|
"""Generate AWS signature version 2 string."""
|
||||||
logging.debug('using _calc_signature_2')
|
logging.debug('using _calc_signature_2')
|
||||||
string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path)
|
string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path)
|
||||||
if self.hmac_256:
|
if self.hmac_256:
|
||||||
hmac = self.hmac_256
|
current_hmac = self.hmac_256
|
||||||
params['SignatureMethod'] = 'HmacSHA256'
|
params['SignatureMethod'] = 'HmacSHA256'
|
||||||
else:
|
else:
|
||||||
hmac = self.hmac
|
current_hmac = self.hmac
|
||||||
params['SignatureMethod'] = 'HmacSHA1'
|
params['SignatureMethod'] = 'HmacSHA1'
|
||||||
keys = params.keys()
|
keys = params.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
pairs = []
|
pairs = []
|
||||||
for key in keys:
|
for key in keys:
|
||||||
val = self._get_utf8_value(params[key])
|
val = self._get_utf8_value(params[key])
|
||||||
pairs.append(urllib.quote(key, safe='') + '=' + urllib.quote(val, safe='-_~'))
|
val = urllib.quote(val, safe='-_~')
|
||||||
|
pairs.append(urllib.quote(key, safe='') + '=' + val)
|
||||||
qs = '&'.join(pairs)
|
qs = '&'.join(pairs)
|
||||||
logging.debug('query string: %s' % qs)
|
logging.debug('query string: %s', qs)
|
||||||
string_to_sign += qs
|
string_to_sign += qs
|
||||||
logging.debug('string_to_sign: %s' % string_to_sign)
|
logging.debug('string_to_sign: %s', string_to_sign)
|
||||||
hmac.update(string_to_sign)
|
current_hmac.update(string_to_sign)
|
||||||
b64 = base64.b64encode(hmac.digest())
|
b64 = base64.b64encode(current_hmac.digest())
|
||||||
logging.debug('len(b64)=%d' % len(b64))
|
logging.debug('len(b64)=%d', len(b64))
|
||||||
logging.debug('base64 encoded digest: %s' % b64)
|
logging.debug('base64 encoded digest: %s', b64)
|
||||||
return b64
|
return b64
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print Signer('foo').generate({"SignatureMethod": 'HmacSHA256', 'SignatureVersion': '2'}, "get", "server", "/foo")
|
print Signer('foo').generate({'SignatureMethod': 'HmacSHA256',
|
||||||
|
'SignatureVersion': '2'},
|
||||||
|
'get', 'server', '/foo')
|
||||||
|
|||||||
Reference in New Issue
Block a user