Beispiel #1
0
    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!")
Beispiel #2
0
    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!')
Beispiel #3
0
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
Beispiel #4
0
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