Beispiel #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)
Beispiel #2
0
def check_client_accpets_application_json():
    accept_header = request.headers.get('accept', '*/*')
    best_response_mimetype = mimeparse.best_match(('application/json', ),
                                                  accept_header)
    if best_response_mimetype == '':
        msg = "The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request"
        details = {'supported_mime_types': ['application/json']}
        return build_response({'error': msg, 'details': details}, 406)
Beispiel #3
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)
def get(user_info):
    response_data = []

    database_controller = DatabaseController(host=MONGO_HOST, port=MONGO_PORT)
    response_data = database_controller.read_tenants(user_info['id'])

    # Filter tenant members if user making the request is not the tenant owner
    for tenant in response_data:
        if tenant['owner_id'] != user_info['id']:
            tenant['users'] = [user for user in tenant['users'] if user['id'] == user_info['id']]

    return build_response(response_data, 200)
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)
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
def internal_server_error(e):
    return build_response({
        'error': 'Internal server error'
    }, 500)
def not_found(e):
    return build_response({
        'error': 'API endpoint not found'
    }, 404)
def bad_request(e):
    return build_response({
        'error': e.description
    }, 400)
Beispiel #10
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)