Ejemplo n.º 1
0
def get_users(user_info):
    try:
        # This method is just a proxy to the IDM for reading available users
        keyrock_client = KeyrockClient(IDM_URL, IDM_USER, IDM_PASSWD)
        return build_response(keyrock_client.get_users(), 200)
    except KeyrockError as e:
        return build_response({'error': str(e)}, 503)
Ejemplo n.º 2
0
def get_tenant(user_info, tenant_id):
    tenant_info = None
    try:
        database_controller = DatabaseController(host=MONGO_HOST,
                                                 port=MONGO_PORT)
        tenant_info = database_controller.get_tenant(tenant_id)

        if tenant_info is None:
            return build_response(
                {'error': 'Tenant {} does not exist'.format(tenant_id)}, 404)

        if tenant_info['owner_id'] != user_info['id'] and not is_member(
                user_info['id'], tenant_info):
            return build_response(
                {'error': 'You are not authorized to retrieve tenant info'},
                403)

        # Get tenant members from the IDM to keep the list
        # of members syncronized
        keyrock_client = KeyrockClient(IDM_URL, IDM_USER, IDM_PASSWD)
        members = keyrock_client.get_organization_members(
            tenant_info['tenant_organization'])
        tenant_info['users'] = [
            {
                'id': member['user_id'],
                'name': member['name'],
                'roles': _map_roles(member)
            } for member in members if member['user_id'] != IDM_USER_ID
        ]  # The admin user used to create the org is not a tenant member

        database_controller.update_tenant(tenant_id, tenant_info)
    except KeyrockError:
        return build_response(
            {'error': 'An error occurred reading tenant info from Keyrock'},
            503)

    if tenant_info['owner_id'] != user_info['id']:
        tenant_info['users'] = [
            user for user in tenant_info['users']
            if user['id'] == user_info['id']
        ]

    return build_response(tenant_info, 200)
Ejemplo n.º 3
0
    def wrapper(*args, **kwargs):
        if 'authorization' not in request.headers or \
                not request.headers.get('authorization').lower().startswith('bearer '):

            return build_response({
                'error': 'This request requires authentication'
            }, 401)

        keyrock_client = KeyrockClient(IDM_URL, IDM_USER, IDM_PASSWD)

        # Authorize user making the request
        token = request.headers.get('authorization').split(' ')[1]

        try:
            user_info = keyrock_client.authorize(token)
        except KeyrockError:
            return build_response({
                'error': 'This request requires authentication'
            }, 401)

        arguments = (user_info,) + args
        return funct(*arguments, **kwargs)
Ejemplo n.º 4
0
def delete_tenant(user_info, tenant_id):
    try:
        database_controller = DatabaseController(host=MONGO_HOST, port=MONGO_PORT)
        tenant_info = database_controller.get_tenant(tenant_id)

        if tenant_info is None:
            return build_response({
                'error': 'Tenant {} does not exist'.format(tenant_id)
            }, 404)

        if tenant_info['owner_id'] != user_info['id']:
            return build_response({
                'error': 'You are not authorized to delete tenant'
            }, 403)

        # Delete organization in the IDM
        keyrock_client = KeyrockClient(IDM_URL, IDM_USER, IDM_PASSWD)
        keyrock_client.delete_organization(tenant_info['tenant_organization'])

        # Delete policies in API Umbrella
        umbrella_client = UmbrellaClient(UMBRELLA_URL, UMBRELLA_TOKEN, UMBRELLA_KEY)
        broker_api = umbrella_client.get_api_from_app_id(BROKER_APP_ID)

        for broker_api_sg in broker_api:
            sub_settings = [setting for setting in broker_api_sg['sub_settings']
                            if not is_tenant_setting(setting, tenant_id)]

            broker_api_sg['sub_settings'] = sub_settings
            umbrella_client.update_api(broker_api_sg)

        # Delete tenant from database
        database_controller.delete_tenant(tenant_id)
    except (KeyrockError, UmbrellaError) as e:
        return build_response({
            'error': str(e)
        }, 503)

    return make_response('', 204)
Ejemplo n.º 5
0
def create(user_info):
    # Get tenant info for JSON request
    if 'name' not in request.json:
        return build_response({
            'error': 'Missing required field name'
        }, 422)

    if 'description' not in request.json:
        return build_response({
            'error': 'Missing required field description'
        }, 422)

    if 'users' in request.json:
        for user in request.json.get('users'):
            if 'name' not in user or 'roles' not in user:
                return build_response({
                    'error': 'Missing required field in user specification'
                }, 422)

    options = {}
    if 'options' in request.json:
        if not isinstance(request.json.get('options'), dict):
            return build_response({
                'error': 'Options field must be an object'
            }, 422)

        options = request.json.get('options')

    tenant_id = None
    try:
        # Build tenant-id
        tenant_id = URLify(request.json.get('name'))
        if not len(tenant_id):
            # All the provided characters were invalid
            return build_response({
                'error': 'It was not possible to generate a tenant ID as all the characters were invalid'
            }, 422)

        database_controller = DatabaseController(host=MONGO_HOST, port=MONGO_PORT)
        prev_t = database_controller.get_tenant(tenant_id)

        if prev_t is not None:
            return build_response({
                'error': 'The tenant {} is already registered'.format(tenant_id)
            }, 409)

        keyrock_client = KeyrockClient(IDM_URL, IDM_USER, IDM_PASSWD)
        org_id = keyrock_client.create_organization(
            request.json.get('name'), request.json.get('description'), user_info['id'])

        # Add context broker role
        keyrock_client.authorize_organization(org_id, BROKER_APP_ID, BROKER_ADMIN_ROLE, BROKER_CONSUMER_ROLE)

        # Add BAE roles
        keyrock_client.authorize_organization_role(org_id, BAE_APP_ID, BAE_SELLER_ROLE, 'owner')
        keyrock_client.authorize_organization_role(org_id, BAE_APP_ID, BAE_CUSTOMER_ROLE, 'owner')
        keyrock_client.authorize_organization_role(org_id, BAE_APP_ID, BAE_ADMIN_ROLE, 'owner')

        # Add tenant users if provided
        users = []
        for user in request.json.get('users', []):
            # User names are not used to identify users in Keyrock
            if 'id' not in user:
                user_id = keyrock_client.get_user_id(user['name'])
            else:
                user_id = user['id']

            user_obj = {
                'id': user_id,
                'name': user['name'],
                'roles': []
            }

            # Keyrock IDM only supports a single organization role
            user_obj['roles'].append(BROKER_CONSUMER_ROLE)

            if BROKER_ADMIN_ROLE in user['roles']:
                keyrock_client.grant_organization_role(org_id, user_id, 'owner')
                user_obj['roles'].append(BROKER_ADMIN_ROLE)
            else:
                keyrock_client.grant_organization_role(org_id, user_id, 'member')

            users.append(user_obj)

        _create_access_policies(tenant_id, org_id, user_info)

        database_controller.save_tenant(
            tenant_id, request.json.get('name'), request.json.get('description'), user_info['id'], users, org_id, options=options)

    except (KeyrockError, UmbrellaError) as e:
        return build_response({
            'error': str(e)
        }, 503)

    response = make_response('', 201)
    response.headers['Location'] = request.path + '/' + tenant_id

    return response
Ejemplo n.º 6
0
def update_tenant(user_info, tenant_id):
    try:
        database_controller = DatabaseController(host=MONGO_HOST, port=MONGO_PORT)
        tenant_info = database_controller.get_tenant(tenant_id)

        if tenant_info is None:
            return build_response({
                'error': 'Tenant {} does not exist'.format(tenant_id)
            }, 404)

        if tenant_info['owner_id'] != user_info['id'] and IDM_USER_ID != user_info['id']:
            return build_response({
                'error': 'You are not authorized to update tenant'
            }, 403)

        patch = jsonpatch.JsonPatch(request.json)

        # Apply JSON patch
        # Valid operations replace description, add user, remove user
        keyrock_client = KeyrockClient(IDM_URL, IDM_USER, IDM_PASSWD)
        tenant_update = patch.apply(tenant_info)

        if len(tenant_update) != len(tenant_info):
            raise ValueError('It is not allowed to add or remove fields from tenant')

        if tenant_update['id'] != tenant_id:
            raise ValueError('Tenant ID cannot be modified')

        if tenant_update['tenant_organization'] != tenant_info['tenant_organization']:
            raise ValueError('Tenant organization cannot be modified')

        if tenant_update['owner_id'] != tenant_info['owner_id']:
            raise ValueError('Tenant owner ID cannot be modified')

        if tenant_update['description'] != tenant_info['description'] \
                or tenant_update['name'] != tenant_info['name']:

            update = {}
            if tenant_update['description'] != tenant_info['description']:
                update['description'] = tenant_update['description']

            if tenant_update['name'] != tenant_info['name']:
                update['name'] = tenant_update['name']

            keyrock_client.update_organization(tenant_update['tenant_organization'], update)

        if tenant_update['users'] != tenant_info['users']:
            roles_update = {}
            to_add = process_users_diff(tenant_update['users'], tenant_info['users'], roles_update=roles_update)
            to_del = process_users_diff(tenant_info['users'], tenant_update['users'])

            for user in to_add:
                add_tenant_user(keyrock_client, tenant_info, user)

            for user in to_del:
                remove_tenant_user(keyrock_client, tenant_info, user)

            for user_id, roles in roles_update.items():
                update_tenant_roles(keyrock_client, tenant_info, user_id, roles['old'], roles['new'])

        # Normalize user information to prevent ewrong role info
        new_users = []
        for user in tenant_update['users']:
            roles = [BROKER_CONSUMER_ROLE]
            if BROKER_ADMIN_ROLE in user['roles']:
                roles.append(BROKER_ADMIN_ROLE)
            user['roles'] = roles

        database_controller.update_tenant(tenant_id, tenant_update)

    except ValueError as e:
        return build_response({
            'error': str(e)
        }, 422)
    except jsonpatch.JsonPatchTestFailed:
        return build_response({
            'error': 'Test operation not successful'
        }, 409)
    except jsonpatch.JsonPatchConflict:
        return build_response({
            'error': 'Conflict applying PATCH, verify indexes and keys'
        }, 409)
    except jsonpatch.InvalidJsonPatch as e:
        return build_response({
            'error': 'Invalid JSON PATCH format: ' + str(e)
        }, 400)
    except KeyrockError as e:
        return build_response({
            'error': str(e)
        }, 503)

    return make_response('', 200)