def __init__(self, app, conf): ''' Constructor ''' self.conf = conf self.app = app if 'attributeFile' in self.conf: self.confParser = AttributeConfigParser(self.conf['attributeFile']) else: self.confParser = AttributeConfigParser(ATT_CONFIG_FILE) self.identity = TenantController() self.users = UserController() self.role = RoleController() self.token = Manager() LOG.info('Starting keystone CVM_Engine middleware') LOG.info('Init CVM_Engine!')
def __init__(self, app, conf): """ Constructor """ self.conf = conf self.app = app if "attributeFile" in self.conf: self.confParser = AttributeConfigParser(self.conf["attributeFile"]) else: self.confParser = AttributeConfigParser(ATT_CONFIG_FILE) self.identity = TenantController() self.users = UserController() self.role = RoleController() self.token = Manager() LOG.info("Starting keystone CVM_Engine middleware") LOG.info("Init CVM_Engine!")
class CVM_Engine(object): """ classdocs """ def __init__(self, app, conf): """ Constructor """ self.conf = conf self.app = app if "attributeFile" in self.conf: self.confParser = AttributeConfigParser(self.conf["attributeFile"]) else: self.confParser = AttributeConfigParser(ATT_CONFIG_FILE) self.identity = TenantController() self.users = UserController() self.role = RoleController() self.token = Manager() LOG.info("Starting keystone CVM_Engine middleware") LOG.info("Init CVM_Engine!") @webob.dec.wsgify(RequestClass=Request) def __call__(self, req): """ def __call__(self, env, start_response): """ """Handle incoming request. This intercepts the request and handle it. """ LOG.debug("Request intercepted by CVM") LOG.debug("--------------------------") LOG.debug(req.environ) if not "HTTP_X_AUTHENTICATION_TYPE" in req.environ: return self.app(req) if not req.environ["HTTP_X_AUTHENTICATION_TYPE"] in ("federated"): return self.app(req) LOG.debug("Print env body") LOG.debug(req.body) LOG.debug("Print Conf --->") LOG.debug(self.conf) body = req.body data = simplejson.loads(body) attributesAssertion = {"permisRole": "staff", "uid": "userUID1234", "idp": "kent.ac.uk", "other": "blablabla"} return self.engine(data, attributesAssertion) # return self.response_list_tenants('jonny') return self.app(req) def engine(self, data, userAttributes): """ The engine method for the middleware. It Creates user and tenants. It linkes them together accoding to the user needs. userAttributes: set of validated attributes coming from the SAML Response from the IDP data: information coming with the request tenant_id: optional parameter where the tenant_id is already known """ realm = data["realm"] LOG.debug(" *** Engine On *** ") if userAttributes is None: """ !!! This is used only for developing tests """ userAttributes = { "uid": "userUID1234", "permisRole": "staff", "eduPersonTargettedID": "userUID1234", "idp": "kent.ac.uk", "other": "blablabla", } self.allAttributes = userAttributes user_name = self.get_userName(userAttributes, realm) if user_name is None: return self.response_Error() # create the user if it doen't exist self.me = self.create_user(user_name) LOG.debug("Logged User : "******"List available tenants : ") LOG.debug(tenants) unsToken = self.create_UnscopeToken() LOG.debug("UnscopedToken created : " + unsToken) return self.response_list_tenants(tenants, unsToken) def response_Error(self): resp = webob.Response(content_type="application/json") response = {"Error": {"code": "666", "message": "The user does not own enough attributes"}} resp.body = json.dumps(response) return resp def response_ErrorForToken(self): resp = webob.Response(content_type="application/json") response = {"Error": {"code": "666", "message": "The user is not authorised to use this token ID."}} resp.body = json.dumps(response) return resp def create_UnscopeToken(self,): context = self.get_context() token_id = uuid.uuid4().hex data = {"id": token_id, "user": self.me} data_ref = self.token.create_token(context, token_id, data) return data_ref["id"] def get_userName(self, userAttributes, realm): if not type(realm) == str: realm = realm["name"] pid = self.confParser.getPID(realm) if pid == None: pid = self.confParser.getPID("default") userAttributes = dict(userAttributes) if userAttributes.has_key(pid): return userAttributes[pid][0] + realm else: return None def create_user(self, user_name): user = {} context = self.get_context() try: ret = self.identity.identity_api.get_user_by_name(context, user_name) if ret is None: raise UserNotFound(user_id=user_name) user["name"] = ret["name"] user["id"] = ret["id"] except UserNotFound: ret = self.users.create_user(context, {"name": user_name}) user["name"] = ret["user"]["name"] user["id"] = ret["user"]["id"] return user def response_list_tenants(self, tenants, unscopeToken): resp = webob.Response(content_type="application/json") response = {} response["tenants"] = tenants response["unscopedToken"] = unscopeToken resp.body = json.dumps(response) return resp def link_user_to_tenant(self, tenant_id, user_id): context = self.get_context() user = self.users.get_user(context, user_id) user = user["user"] user["tenantId"] = tenant_id updatedUser = self.users.update_user_tenant(context, user_id, user) return updatedUser["user"] def is_linked(self, tenant_id, user_id): context = self.get_context() users = self.identity.get_tenant_users(context, tenant_id) for user in users["users"]: if user["id"] == user_id: return True return False def get_tenant_by_name(self, tenant_name): tenant = {} context = self.get_context() try: ret = self.identity.identity_api.get_tenant_by_name(context, tenant_name) if ret is None: raise TenantNotFound(tenant_id=tenant_name) except TenantNotFound: return None tenant["name"] = ret["name"] tenant["id"] = ret["id"] return tenant """ def get_list_tenants(self): LOG.debug('** get list tenants **') context = self.get_context() tenants_list = {} tenants = self.identity.get_all_tenants(context) for item in tenants['tenants']: LOG.debug(item['name']+" "+item['id']) tenants_list[item['name']]=item['id'] return True """ def get_valid_userAttribute(self, userAttributes): """ Return the concatenation of the user attributes according to the attributes configured in the config file. userAttributes: contains the attributes coming from the SAML Response !!! IMPORTANT: this method doen't support multiple attribute values. This is a TODO! """ confAtt = self.confParser.getSetsAndAtts() valid = {} for set in confAtt: str = "" count = 0 jok = confAtt[set] for att in jok: values = confAtt[set][att] if userAttributes.has_key(att): if values[0] is None or values[0] == userAttributes[att][0]: str += att + userAttributes[att][0] count = count + 1 if count == len(confAtt[set]): valid[set] = str return valid def is_permittedTenant(self, conf_attributes, tenant_id): user_id = self.me["id"] ca = dict(conf_attributes) context = self.get_context() ten = self.identity.get_tenant(context, tenant_id) LOG.info("tenant") LOG.info(ten) for attr, value in ca.iteritems(): if ten["tenant"]["name"] == value: return True return False def get_available_tenants(self, conf_attributes): filt_tenants = [] user_id = self.me["id"] LOG.info("get_available_tenants:") LOG.info(conf_attributes) ca = dict(conf_attributes) for attr, value in ca.iteritems(): ten = self.get_tenant_by_name(value) context = self.get_context() if ten is None: newTenant = self.identity.create_tenant(context, {"name": value}) ten = {} ten["name"] = newTenant["tenant"]["name"] ten["id"] = newTenant["tenant"]["id"] ten["friendlyName"] = attr if not self.is_linked(ten["id"], user_id): self.link_user_to_tenant(ten["id"], user_id) self.check_roles(user_id, ten["id"], ten["friendlyName"], conf_attributes) filt_tenants.append(ten) return filt_tenants def get_available_roles(self, fn, conf_attributes): conf_attributes = self.allAttributes LOG.info("Finding roles for tenant: " + fn) roles = self.confParser.getMappedAttributefForSet(fn) LOG.info("From COnf Roles") LOG.info(roles) res = [] roles = dict(roles) conf_attributes = dict(conf_attributes) for role, attr in roles.iteritems(): LOG.info("Role " + role) LOG.info(attr) count = 0 for role, attrib in attr.iteritems(): LOG.info(role) LOG.info(attrib) attType = attrib.keys()[0] value = attrib[attType] LOG.info(conf_attributes.keys()) if attType in conf_attributes.keys(): if value is None: count = count + 1 else: if not value is None and conf_attributes[name] == value: count = count + 1 if count == len(attr): res.append(role) return res def check_roles(self, user_id, tenant_id, fn, conf_attributes): roles = self.get_available_roles(fn, conf_attributes) LOG.info("Aval Roles") LOG.info(roles) context = self.get_context() for role in roles: if not self.check_user_roles(role, user_id, tenant_id): newRole = self.get_role(role) newRole = self.role.add_role_to_user(context, user_id, newRole["id"], tenant_id) r = newRole["role"] LOG.info("New Role Linked") LOG.info(r.name) def check_user_roles(self, roleName, user_id, tenant_id): context = self.get_context() roles = self.role.get_user_roles(context, user_id, tenant_id) for role in roles["roles"]: if role["name"] == roleName: return True return False def get_role(self, name): context = self.get_context() retRole = {} roles = self.role.get_roles(context) for role in roles["roles"]: if role["name"] == name: retRole["name"] = role["name"] retRole["id"] = role["id"] return retRole return self.role.create_role(context, {"name": name}) def get_context(self): context = {"query_string": {"limit": 100000, "Marker": 0}} context["is_admin"] = True return context
class CVM_Engine(object): ''' classdocs ''' def __init__(self, app, conf): ''' Constructor ''' self.conf = conf self.app = app if 'attributeFile' in self.conf: self.confParser = AttributeConfigParser(self.conf['attributeFile']) else: self.confParser = AttributeConfigParser(ATT_CONFIG_FILE) self.identity = TenantController() self.users = UserController() self.role = RoleController() self.token = Manager() LOG.info('Starting keystone CVM_Engine middleware') LOG.info('Init CVM_Engine!') @webob.dec.wsgify(RequestClass=Request) def __call__(self, req): ''' def __call__(self, env, start_response): ''' """Handle incoming request. This intercepts the request and handle it. """ LOG.debug('Request intercepted by CVM') LOG.debug('--------------------------') LOG.debug(req.environ) if not 'HTTP_X_AUTHENTICATION_TYPE' in req.environ: return self.app(req) if not req.environ['HTTP_X_AUTHENTICATION_TYPE'] in ('federated'): return self.app(req) LOG.debug('Print env body') LOG.debug(req.body) LOG.debug('Print Conf --->') LOG.debug(self.conf) body = req.body data = simplejson.loads(body) attributesAssertion = { 'permisRole': 'staff', 'uid': 'userUID1234', 'idp': 'kent.ac.uk', 'other': 'blablabla' } return self.engine(data, attributesAssertion) #return self.response_list_tenants('jonny') return self.app(req) def engine(self, data, userAttributes): ''' The engine method for the middleware. It Creates user and tenants. It linkes them together accoding to the user needs. userAttributes: set of validated attributes coming from the SAML Response from the IDP data: information coming with the request tenant_id: optional parameter where the tenant_id is already known ''' realm = data['realm'] LOG.debug(' *** Engine On *** ') if userAttributes is None: ''' !!! This is used only for developing tests ''' userAttributes = { 'uid': 'userUID1234', 'permisRole': 'staff', 'eduPersonTargettedID': 'userUID1234', 'idp': 'kent.ac.uk', 'other': 'blablabla' } self.allAttributes = userAttributes user_name = self.get_userName(userAttributes, realm) if user_name is None: return self.response_Error() # create the user if it doen't exist self.me = self.create_user(user_name) LOG.debug('Logged User : '******'List available tenants : ') LOG.debug(tenants) unsToken = self.create_UnscopeToken() LOG.debug('UnscopedToken created : ' + unsToken) return self.response_list_tenants(tenants, unsToken) def response_Error(self): resp = webob.Response(content_type='application/json') response = { 'Error': { 'code': '666', 'message': 'The user does not own enough attributes' } } resp.body = json.dumps(response) return resp def response_ErrorForToken(self): resp = webob.Response(content_type='application/json') response = { 'Error': { 'code': '666', 'message': 'The user is not authorised to use this token ID.' } } resp.body = json.dumps(response) return resp def create_UnscopeToken(self, ): context = self.get_context() token_id = uuid.uuid4().hex data = {'id': token_id, 'user': self.me} data_ref = self.token.create_token(context, token_id, data) return data_ref['id'] def get_userName(self, userAttributes, realm): if not type(realm) == str: realm = realm['name'] pid = self.confParser.getPID(realm) if pid == None: pid = self.confParser.getPID("default") userAttributes = dict(userAttributes) if userAttributes.has_key(pid): return userAttributes[pid][0] + realm else: return None def create_user(self, user_name): user = {} context = self.get_context() try: ret = self.identity.identity_api.get_user_by_name( context, user_name) if ret is None: raise UserNotFound(user_id=user_name) user['name'] = ret['name'] user['id'] = ret['id'] except UserNotFound: ret = self.users.create_user(context, {'name': user_name}) user['name'] = ret['user']['name'] user['id'] = ret['user']['id'] return user def response_list_tenants(self, tenants, unscopeToken): resp = webob.Response(content_type='application/json') response = {} response['tenants'] = tenants response['unscopedToken'] = unscopeToken resp.body = json.dumps(response) return resp def link_user_to_tenant(self, tenant_id, user_id): context = self.get_context() user = self.users.get_user(context, user_id) user = user['user'] user['tenantId'] = tenant_id updatedUser = self.users.update_user_tenant(context, user_id, user) return updatedUser['user'] def is_linked(self, tenant_id, user_id): context = self.get_context() users = self.identity.get_tenant_users(context, tenant_id) for user in users['users']: if user['id'] == user_id: return True return False def get_tenant_by_name(self, tenant_name): tenant = {} context = self.get_context() try: ret = self.identity.identity_api.get_tenant_by_name( context, tenant_name) if ret is None: raise TenantNotFound(tenant_id=tenant_name) except TenantNotFound: return None tenant['name'] = ret['name'] tenant['id'] = ret['id'] return tenant ''' def get_list_tenants(self): LOG.debug('** get list tenants **') context = self.get_context() tenants_list = {} tenants = self.identity.get_all_tenants(context) for item in tenants['tenants']: LOG.debug(item['name']+" "+item['id']) tenants_list[item['name']]=item['id'] return True ''' def get_valid_userAttribute(self, userAttributes): ''' Return the concatenation of the user attributes according to the attributes configured in the config file. userAttributes: contains the attributes coming from the SAML Response !!! IMPORTANT: this method doen't support multiple attribute values. This is a TODO! ''' confAtt = self.confParser.getSetsAndAtts() valid = {} for set in confAtt: str = '' count = 0 jok = confAtt[set] for att in jok: values = confAtt[set][att] if userAttributes.has_key(att): if values[0] is None or values[0] == userAttributes[att][0]: str += att + userAttributes[att][0] count = count + 1 if count == len(confAtt[set]): valid[set] = str return valid def is_permittedTenant(self, conf_attributes, tenant_id): user_id = self.me['id'] ca = dict(conf_attributes) context = self.get_context() ten = self.identity.get_tenant(context, tenant_id) LOG.info('tenant') LOG.info(ten) for attr, value in ca.iteritems(): if ten['tenant']['name'] == value: return True return False def get_available_tenants(self, conf_attributes): filt_tenants = [] user_id = self.me['id'] LOG.info('get_available_tenants:') LOG.info(conf_attributes) ca = dict(conf_attributes) for attr, value in ca.iteritems(): ten = self.get_tenant_by_name(value) context = self.get_context() if ten is None: newTenant = self.identity.create_tenant( context, {'name': value}) ten = {} ten['name'] = newTenant['tenant']['name'] ten['id'] = newTenant['tenant']['id'] ten['friendlyName'] = attr if not self.is_linked(ten['id'], user_id): self.link_user_to_tenant(ten['id'], user_id) self.check_roles(user_id, ten['id'], ten['friendlyName'], conf_attributes) filt_tenants.append(ten) return filt_tenants def get_available_roles(self, fn, conf_attributes): conf_attributes = self.allAttributes LOG.info("Finding roles for tenant: " + fn) roles = self.confParser.getMappedAttributefForSet(fn) LOG.info('From COnf Roles') LOG.info(roles) res = [] roles = dict(roles) conf_attributes = dict(conf_attributes) for role, attr in roles.iteritems(): LOG.info("Role " + role) LOG.info(attr) count = 0 for role, attrib in attr.iteritems(): LOG.info(role) LOG.info(attrib) attType = attrib.keys()[0] value = attrib[attType] LOG.info(conf_attributes.keys()) if attType in conf_attributes.keys(): if value is None: count = count + 1 else: if not value is None and conf_attributes[name] == value: count = count + 1 if count == len(attr): res.append(role) return res def check_roles(self, user_id, tenant_id, fn, conf_attributes): roles = self.get_available_roles(fn, conf_attributes) LOG.info('Aval Roles') LOG.info(roles) context = self.get_context() for role in roles: if not self.check_user_roles(role, user_id, tenant_id): newRole = self.get_role(role) newRole = self.role.add_role_to_user(context, user_id, newRole['id'], tenant_id) r = newRole['role'] LOG.info('New Role Linked') LOG.info(r.name) def check_user_roles(self, roleName, user_id, tenant_id): context = self.get_context() roles = self.role.get_user_roles(context, user_id, tenant_id) for role in roles['roles']: if role['name'] == roleName: return True return False def get_role(self, name): context = self.get_context() retRole = {} roles = self.role.get_roles(context) for role in roles['roles']: if role['name'] == name: retRole['name'] = role['name'] retRole['id'] = role['id'] return retRole return self.role.create_role(context, {'name': name}) def get_context(self): context = {'query_string': {'limit': 100000, 'Marker': 0}} context['is_admin'] = True return context