Exemple #1
0
            def inner_wrapper(*args, **kwargs):
                try:
                    with Yosai.context(self._yosai):
                        # Context Manager functions
                        try:
                            try:
                                identity = self.authenticate(request_proxy)
                                if not identity.username:
                                    raise UnauthenticatedError('Authentication Required')
                            except:
                                raise UnauthenticatedError('Authentication Required')

                            ApiRequestContextProxy.set_identity(identity)

                            if self._check_account(identity.user_account, identity.user_account_type, with_names, with_types):
                                return f(*args, **kwargs)
                        finally:
                            # Teardown the request context
                            ApiRequestContextProxy.set_identity(None)

                except UnauthorizedAccountError as ex:
                    return make_response_error(str(ex), in_httpcode=403), 403
                except UnauthenticatedError as ex:
                    return Response(response='Unauthorized', status=401, headers=[('WWW-Authenticate', 'basic realm="Authentication required"')])
                except Exception as ex:
                    logger.exception('Unexpected exception: {}'.format(ex))
                    return make_response_error('Internal error', in_httpcode=500), 500
def get_analysis_archive_rule(rule_id):
    """
    GET /archives/rules/{rule_id}

    :param rule_id:
    :return:
    """
    try:
        with session_scope() as session:
            rule = (
                session.query(ArchiveTransitionRule)
                .filter_by(account=ApiRequestContextProxy.namespace(), rule_id=rule_id)
                .one_or_none()
            )
            if rule is None:
                # Allow users to get the system global rules
                rule = (
                    session.query(ArchiveTransitionRule)
                    .filter_by(rule_id=rule_id, system_global=True)
                    .one_or_none()
                )
                if rule is None:
                    return make_response_error("Rule not found", in_httpcode=404), 404

            return transition_rule_db_to_json(rule), 200
    except Exception as ex:
        return make_response_error(ex, in_httpcode=500), 500
Exemple #3
0
def archive_image_analysis(imageReferences):
    """
    POST /archives/images

    body = [digest1, digest2, ... ]

    """

    try:
        if not imageReferences or len(imageReferences) > 100:
            return make_response_error('Bad Request. Must include a list of digests between 1 and 100 entries long', in_httpcode=400), 400

        results = []

        for digest in imageReferences:
            try:
                # Do synchronous part to start the state transition
                task = ArchiveImageTask(account=ApiRequestContextProxy.namespace(), image_digest=digest)
                result_status, result_detail = task.run()
                results.append({'digest': task.image_digest, 'status': result_status, 'detail': result_detail})
            except Exception as ex:
                logger.exception('Unexpected an uncaught exception from the archive task execution')
                results.append({'digest': digest, 'status': 'error', 'detail': str(ex)})

        return results, 200
    except Exception as err:
        logger.exception('Error processing image add')
        return make_response_error(err, in_httpcode=500), 500
Exemple #4
0
def delete_archived_analysis(imageDigest, force=False):
    """
    DELETE /archives/images/{digest}

    :param imageDigest: image digest to delete the archive for
    :return:
    """

    # # Read the archive manifest, and delete or restore the artifacts
    try:
        if force:
            start_statuses = ['archiving', 'archived', 'deleting', 'deleted']
        else:
            start_statuses = ['archived', 'deleting']

        with session_scope() as session:
            resp = db_archived_images.update_image_status(session, ApiRequestContextProxy.namespace(), imageDigest, start_statuses, 'deleting')

        if resp is None:
            return make_response_error('Not found in archive', in_httpcode=404), 404
    except Exception as ex:
        logger.exception("Error deleting archive for image {}/{}".format(ApiRequestContextProxy.namespace(), imageDigest))
        return make_response_error('Invalid object state: {}'.format(ex), in_httpcode=400), 400

    try:
        task = DeleteArchivedImageTask(account=ApiRequestContextProxy.namespace(), image_digest=imageDigest)
        task.run()
        resp = None
        return resp, 200
    except Exception as ex:
        logger.exception('Failed deleting archived image')
        return make_response_error('Error deleting image archive: {}'.format(ex), in_httpcode=500), 500
Exemple #5
0
def sync_feeds(sync=True, force_flush=False):
    """
    POST /feeds?sync=True&force_flush=True

    :param sync: Boolean. If true, do a sync. If false, don't sync.
    :param force_flush: Boolean. If true, remove all previous data and replace with data from upstream source
    :return:
    """

    result = []
    if sync:
        try:
            result = FeedsUpdateTask.run_feeds_update(force_flush=force_flush)
        except (LeaseAcquisitionFailedError, LeaseUnavailableError) as e:
            log.exception(
                'Could not acquire lock on feed sync, likely another sync already in progress'
            )
            return make_response_error(
                'Feed sync lock already held',
                in_httpcode=409,
                details={
                    'error_codes':
                    [AnchoreError.FEED_SYNC_ALREADY_IN_PROGRESS.name],
                    'message':
                    AnchoreError.FEED_SYNC_ALREADY_IN_PROGRESS.value
                }), 409
        except Exception as e:
            log.exception('Error executing feed update task')
            return jsonify(make_response_error(e, in_httpcode=500)), 500

    return jsonify(result), 200
Exemple #6
0
def list_users(accountname):
    """
    GET /accounts/{accountname}/users

    :param account:
    :return:
    """

    try:

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)

            users = mgr.list_users(accountname)
            if users is None:
                return make_response_error("No such account",
                                           in_httpcode=404), 404

            response = list(map(user_db_to_msg, users))
            return response, 200
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as e:
        logger.exception("API Error")
        return make_response_error("Error listing account users",
                                   in_httpcode=500), 500
Exemple #7
0
def create_user(accountname, user):
    """
    POST /accounts/{accountname}/users

    :param accountname:
    :param user:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)
            usr = mgr.create_user(
                account_name=accountname,
                username=user['username'],
                creator_name=ApiRequestContextProxy.identity().username,
                password=user['password'])
            return user_db_to_msg(usr), 200
    except UserAlreadyExistsError as ex:
        return make_response_error('User already exists', in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error(
            'Internal error deleting account {}'.format(accountname)), 500
Exemple #8
0
def delete_user(accountname, username):
    """
    DELETE /accounts/{accountname}/users/{username}

    :param accountname:
    :param username: the user to delete
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_user(username, accountname, mgr)

            if ApiRequestContextProxy.identity().username == username:
                return make_response_error(
                    'Cannot delete credential used for authentication of the request',
                    in_httpcode=400), 400

            if mgr.delete_user(username):
                return None, 204
            else:
                return make_response_error(
                    'Failed to delete user: {}'.format(username),
                    in_httpcode=500), 500
    except (UserNotFoundError, AccountNotFoundError):
        return make_response_error('User not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error(
            'Internal error deleting user {}'.format(username),
            in_httpcode=500), 500
def delete_group(feed, group):
    session = db.get_session()
    try:
        f = db.lookup_feed_group(db_session=session, feed_name=feed, group_name=group)
        if not f:
            raise ResourceNotFound(group, detail={})
        elif f.enabled:
            raise ConflictingRequest(message='Cannot delete an enabled feed group. Disable the feed group first', detail={})
    except AnchoreApiError:
        raise
    except Exception as e:
        return jsonify(make_response_error(e, in_httpcode=500)), 500
    finally:
        session.rollback()

    try:
        g = sync.DataFeeds.delete_feed_group(feed_name=feed, group_name=group)
        log.info('Flushed group records {}'.format(g))
        if g:
            return jsonify(_marshall_group_response(g)), 200
        else:
            raise ResourceNotFound(group, detail={})
    except KeyError as e:
        raise ResourceNotFound(resource=str(e), detail={'feed': feed, 'group': group})
    except AnchoreApiError:
        raise
    except Exception as e:
        log.error('Could not flush feed group {}/{}'.format(feed, group))
        return jsonify(make_response_error(e, in_httpcode=500)), 500
Exemple #10
0
def activate_account(accountname):
    """
    POST /accounts/{accountname}/activate

    idempotently activate an account

    :param accountname: str account name to activate
    :return: account json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)

            result = mgr.activate_account(accountname)
            if result:
                return account_db_to_status_msg(result), 200
            else:
                return make_response_error('Error updating account state'), 500
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error('Error activating account',
                                   in_httpcode=500), 500
Exemple #11
0
def create_account(account):
    """
    POST /accounts

    :param account:
    :return:
    """

    try:
        if account.get('type') != AccountTypes.user.value:
            return make_response_error(
                'Invalid account type: {}. Only valid value is "user"'.format(
                    account.get('type')),
                in_httpcode=400), 400

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            resp = mgr.create_account(
                account_name=account['name'],
                account_type=account.get('type', AccountTypes.user.value),
                email=account.get('email'),
                creator=ApiRequestContextProxy.identity().username)
        return account_db_to_msg(resp), 200
    except AccountAlreadyExistsError as ex:
        return make_response_error(errmsg='Account already exists',
                                   in_httpcode=400), 400
    except Exception as ex:
        logger.exception('Unexpected Error creating account')
        return make_response_error('Error creating account',
                                   in_httpcode=500), 500
Exemple #12
0
def add_credential(credential):
    """
    POST /user/credentials

    The same logic as /users/{userId}/credentials, but gets the userId from the auth context rather than path.
    This is for use by regular (non-admin) users to update their own credentials.
    :param credential:
    :return: credential json object

    """

    try:
        if credential['type'] != UserAccessCredentialTypes.password.value:
            return make_response_error('Invalid credential type',
                                       in_httpcode=400), 400
        else:
            cred_type = UserAccessCredentialTypes(credential['type'])

        with session_scope() as session:
            mgr = identities.manager_factory.for_session(session)
            user = ApiRequestContextProxy.identity().username
            result = mgr.add_user_credential(username=user,
                                             credential_type=cred_type,
                                             value=credential['value'])
            return credential_db_to_msg(result), 200
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex), in_httpcode=500), 500
def content_upload(operation_id, content_type, request):
    """
    Generic handler for multiple types of content uploads. Still operates at the API layer

    :param operation_id:
    :param content_type:
    :param request:
    :return:
    """
    try:
        client = internal_client_for(
            CatalogClient, userId=ApiRequestContextProxy.namespace()
        )
        return (
            client.upload_image_import_content(
                operation_id, content_type, request.data
            ),
            200,
        )
    except api_exceptions.AnchoreApiError as ex:
        return (
            make_response_error(ex, in_httpcode=ex.__response_code__),
            ex.__response_code__,
        )
    except Exception as ex:
        logger.exception("Unexpected error in api processing")
        return make_response_error(ex, in_httpcode=500), 500
Exemple #14
0
def delete_user(accountname, username):
    """
    DELETE /accounts/{accountname}/users/{username}

    :param accountname:
    :param username: the user to delete
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = verify_user(username, accountname, mgr)
            if not can_delete_user(usr):
                return make_response_error('User not allowed to be deleted due to system constraints', in_httpcode=400), 400
            elif ApiRequestContextProxy.identity().username == username:
                return make_response_error('Cannot delete credential used for authentication of the request', in_httpcode=400), 400
            else:
                if mgr.delete_user(username):
                    # Flush from authz system if necessary, will rollback if this fails, but rely on the db state checks first to gate this
                    authorizer.notify(NotificationTypes.principal_deleted, username)

                    return None, 204
                else:
                    return make_response_error('Failed to delete user: {}'.format(username), in_httpcode=500), 500
    except (UserNotFoundError, AccountNotFoundError):
        return make_response_error('User not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error('Internal error deleting user {}'.format(username), in_httpcode=500), 500
Exemple #15
0
def delete_feed(feed):
    session = db.get_session()
    try:
        f = db.lookup_feed(db_session=session, feed_name=feed)
        if not f:
            raise ResourceNotFound(resource=feed, detail={})
        elif f.enabled:
            raise ConflictingRequest(
                message="Cannot delete an enabled feed. Disable the feed first",
                detail={},
            )
    except AnchoreApiError:
        raise
    except Exception as e:
        return jsonify(make_response_error(e, in_httpcode=500)), 500
    finally:
        session.rollback()

    try:
        f = sync.DataFeeds.delete_feed(feed)
        if f:
            return jsonify(_marshall_feed_response(f).to_json()), 200
        else:
            raise ResourceNotFound(feed, detail={})
    except KeyError as e:
        raise ResourceNotFound(resource=str(e), detail={"feed": feed})
    except AnchoreApiError:
        raise
    except Exception as e:
        return jsonify(make_response_error(e, in_httpcode=500)), 500
Exemple #16
0
def update_account_state(accountname, desired_state):
    """
    POST /accounts/{accountname}/state

    Body: {"state": "enabled"|"disabled"}

    :param accountname: str account name to update
    :param desired_state: json object for desired state to set
    :return: account json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)
            result = mgr.update_account_state(
                accountname, AccountStates(desired_state.get("state")))
            if result:
                return account_db_to_status_msg(result), 200
            else:
                return make_response_error("Error updating account state"), 500
    except (InvalidStateError, DisableAdminAccountError) as ex:
        return make_response_error(str(ex), in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as e:
        logger.exception("API Error")
        return make_response_error("Error updating account state",
                                   in_httpcode=500), 500
Exemple #17
0
def list_user_credentials(accountname, username):
    """
    GET /accounts/{accountname}/users/{username}/credentials

    :param username:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = verify_user(username, accountname, mgr)
            cred = usr["credentials"].get(UserAccessCredentialTypes.password)
            if cred is None:
                return [], 200
            else:
                cred = credential_db_to_msg(cred)
                return [cred], 200
    except UserNotFoundError as ex:
        return make_response_error("User not found", in_httpcode=404), 404
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as ex:
        logger.exception("Api Error")
        return make_response_error(errmsg=str(ex), in_httpcode=500), 500
Exemple #18
0
def create_user(accountname, user):
    """
    POST /accounts/{accountname}/users

    :param accountname:
    :param user:
    :return:
    """

    try:

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)

            try:
                usr = mgr.create_user(account_name=accountname,
                                      username=user['username'],
                                      password=user['password'])
            except ValueError as ex:
                return make_response_error('Validation failed: {}'.format(ex),
                                           in_httpcode=400), 400

            # Flush from authz system if necessary, will rollback if this fails, but rely on the db state checks first to gate this
            authorizer.notify(NotificationTypes.principal_created,
                              usr['username'])

            return user_db_to_msg(usr), 200
    except UserAlreadyExistsError as ex:
        return make_response_error('User already exists', in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error('Internal error adding user'), 500
Exemple #19
0
def list_accounts(state=None):
    """
    GET /accounts

    :param active:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            if state is not None:
                try:
                    state = AccountStates(state)
                except:
                    return (
                        make_response_error(
                            "Bad Request: state {} not a valid value",
                            in_httpcode=400),
                        400,
                    )

            response = mgr.list_accounts(with_state=state)

            return list(map(account_db_to_msg, response)), 200
    except Exception as ex:
        logger.exception("API Error")
        return make_response_error("Error listing accounts",
                                   in_httpcode=500), 500
Exemple #20
0
def delete_user(accountname, username):
    """
    DELETE /accounts/{accountname}/users/{username}

    :param accountname:
    :param username: the user to delete
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            if request.authorization.accountname == accountname:
                return make_response_error('Cannot delete credential used for authentication of the request'), 400

            user = mgr.get_user(username)
            if user['account_name'] != accountname:
                return make_response_error('username {} not valid for account {}'.format(username, accountname)), 404

            if mgr.delete_user(username):
                return '', 200
            else:
                return make_response_error('Failed to delete credential: {}'.format(accountname)), 500
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Exemple #21
0
def create_user_credential(accountname, username, credential):
    """
    POST /accounts/{accountname}/users/{username}/credentials
    :param accountname: str account id for account account record
    :param username: str username
    :param credential: json object of the credential type
    :return: credential json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = mgr.get_user(username)
            if not usr or usr['account_name'] != accountname:
                return make_response_error('Username not found in account'), 404

            # For now, only support passwords via the api
            if credential['type'] != 'password':
                return make_response_error('Invalid credential type'), 400

            if not credential.get('value'):
                return make_response_error('Invalid credential value, must be non-null and non-empty'), 400

            try:
                cred_type = UserAccessCredentialTypes(credential['type'])
            except:
                return make_response_error(errmsg='Invalid credential type'), 400

            cred = mgr.add_user_credential(session, creator_name=ApiRequestContextProxy.user(), username=username, credential_type=cred_type, value=credential['value'])

            return credential_db_to_msg(cred), 200
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Exemple #22
0
def sync_feeds(sync=True, force_flush=False):
    """
    POST /feeds?sync=True&force_flush=True

    :param sync: Boolean. If true, do a sync. If false, don't sync.
    :param force_flush: Boolean. If true, remove all previous data and replace with data from upstream source
    :return:
    """

    result = []
    if sync:
        try:
            result = FeedsUpdateTask.run_feeds_update(force_flush=force_flush)
        except LeaseAcquisitionFailedError as e:
            log.exception(
                'Could not acquire lock on feed sync, likely another sync already in progress'
            )
            return make_response_error(
                'Failed to execute feed sync',
                in_httpcode=409,
                detail=
                'Could not acquire lock on feed sync, likely another sync already in progress'
            ), 409
        except Exception as e:
            log.exception('Error executing feed update task')
            return make_response_error(
                'Failed to execute feed sync due to an internal error',
                in_httpcode=500), 500

    return jsonify(['{}/{}'.format(x[0], x[1]) for x in result]), 200
Exemple #23
0
            def inner_wrapper(*args, **kwargs):
                try:
                    with Yosai.context(self._yosai):
                        # Context Manager functions
                        try:
                            try:
                                identity = self.authenticate(request_proxy)
                                if not identity.username:
                                    raise UnauthenticatedError('Authentication Required')
                            except:
                                raise UnauthenticatedError('Authentication Required')

                            ApiRequestContextProxy.set_identity(identity)
                            permissions_final = []

                            # Bind all the permissions as needed
                            for perm in permission_s:
                                domain = perm.domain if perm.domain else '*'
                                action = perm.action if perm.action else '*'
                                target = perm.target if perm.target else '*'

                                if hasattr(domain, 'bind'):
                                    domain.bind(operation=f, kwargs=kwargs)
                                    domain = domain.value

                                if hasattr(action, 'bind'):
                                    action.bind(operation=f, kwargs=kwargs)
                                    action = action.value

                                if hasattr(target, 'bind'):
                                    target.bind(operation=f, kwargs=kwargs)
                                    target = target.value

                                #permissions_final.append(':'.join([domain, action, target]))
                                permissions_final.append(Permission(domain, action, target))

                            # Do the authz on the bound permissions
                            try:
                                self.authorize(ApiRequestContextProxy().identity(), permissions_final)
                            except UnauthorizedError as ex:
                                raise ex
                            except Exception as e:
                                logger.exception('Error doing authz: {}'.format(e))
                                raise UnauthorizedError(permissions_final)

                            return f(*args, **kwargs)
                        finally:
                            # Teardown the request context
                            ApiRequestContextProxy.set_identity(None)

                except UnauthorizedError as ex:
                    return make_response_error(str(ex), in_httpcode=403), 403
                except UnauthenticatedError as ex:
                    return Response(response='Unauthorized', status=401, headers=[('WWW-Authenticate', 'basic realm="Authentication required"')])
                except AnchoreApiError:
                    raise
                except Exception as ex:
                    logger.exception('Unexpected exception: {}'.format(ex))
                    return make_response_error('Internal error', in_httpcode=500), 500
Exemple #24
0
    def inline_authz(self, permission_s: list, authc_token: AuthenticationToken=None):
        """
        Non-decorator impl of the @requires() decorator for isolated and inline invocation.
        Returns authenticated user identity on success or raises an exception

        :param permission_s: list of Permission objects
        :param authc_token: optional authc token to use for the authc portion, if omitted or None, the flask request context is used
        :return: IdentityContext object
        """
        try:
            with Yosai.context(self._yosai):
                # Context Manager functions
                try:
                    try:
                        if not authc_token:
                            identity = self.authenticate(request_proxy)
                        else:
                            identity = self.authenticate_token(authc_token)

                        if not identity.username:
                            raise UnauthenticatedError('Authentication Required')

                    except:
                        raise UnauthenticatedError('Authentication Required')

                    ApiRequestContextProxy.set_identity(identity)
                    permissions_final = []

                    # Bind all the permissions as needed
                    for perm in permission_s:
                        domain = perm.domain if perm.domain else '*'
                        action = perm.action if perm.action else '*'
                        target = perm.target if perm.target else '*'
                        permissions_final.append(Permission(domain, action, target))

                    # Do the authz on the bound permissions
                    try:
                        self.authorize(ApiRequestContextProxy.identity(), permissions_final)
                    except UnauthorizedError as ex:
                        raise ex
                    except Exception as e:
                        logger.exception('Error doing authz: {}'.format(e))
                        raise UnauthorizedError(permissions_final)

                    return ApiRequestContextProxy.identity()
                finally:
                    # Teardown the request context
                    ApiRequestContextProxy.set_identity(None)
        except UnauthorizedError as ex:
            return make_response_error(str(ex), in_httpcode=403), 403
        except UnauthenticatedError as ex:
            return Response(response='Unauthorized', status=401,
                            headers=[('WWW-Authenticate', 'basic realm="Authentication required"')])
        except AnchoreApiError:
            raise
        except Exception as ex:
            logger.exception('Unexpected exception: {}'.format(ex))
            return make_response_error('Internal error', in_httpcode=500), 500
Exemple #25
0
def handle_proxy_response(resp):
    if issubclass(Exception, resp.__class__):
        if hasattr(resp, 'httpcode'):
            return make_response_error(
                resp, in_httpcode=resp.httpcode), resp.httpcode
        else:
            return make_response_error(resp, in_httpcode=500), 500
    else:
        return resp, 200
Exemple #26
0
    def inline_authz(self, permission_s: list):
        """
        Non-decorator impl of the @requires() decorator for isolated and inline invocation.
        Returns None on success or raises an exception

        :param permission_s:
        :return:
        """
        try:
            with Yosai.context(self._yosai):
                # Context Manager functions
                try:
                    try:
                        identity = self.authenticate(request_proxy)
                        if not identity.username:
                            raise UnauthenticatedError(
                                'Authentication Required')
                    except:
                        raise UnauthenticatedError('Authentication Required')

                    ApiRequestContextProxy.set_identity(identity)
                    permissions_final = []

                    # Bind all the permissions as needed
                    for perm in permission_s:
                        domain = perm.domain if perm.domain else '*'
                        action = perm.action if perm.action else '*'
                        target = perm.target if perm.target else '*'

                        permissions_final.append(':'.join(
                            [domain, action, target]))

                    # Do the authz on the bound permissions
                    try:
                        self.authorize(identity, permissions_final)
                    except UnauthorizedError as ex:
                        raise ex
                    except Exception as e:
                        logger.exception('Error doing authz: {}'.format(e))
                        raise UnauthorizedError(permissions_final)

                    return None
                finally:
                    # Teardown the request context
                    ApiRequestContextProxy.set_identity(None)
        except UnauthorizedError as ex:
            return make_response_error(str(ex), in_httpcode=403), 403
        except UnauthenticatedError as ex:
            return Response(response='Unauthorized',
                            status=401,
                            headers=[('WWW-Authenticate',
                                      'basic realm="Authentication required"')
                                     ])
        except Exception as ex:
            logger.exception('Unexpected exception: {}'.format(ex))
            return make_response_error('Internal error', in_httpcode=500), 500
Exemple #27
0
def content_upload(operation_id, content_type, request):
    """
    Generic handler for multiple types of content uploads. Still operates at the API layer

    :param operation_id:
    :param content_type:
    :param request:
    :return:
    """
    try:
        with session_scope() as db_session:
            record = (db_session.query(ImageImportOperation).filter_by(
                account=ApiRequestContextProxy.namespace(),
                uuid=operation_id).one_or_none())
            if not record:
                raise api_exceptions.ResourceNotFound(resource=operation_id,
                                                      detail={})

            if not record.status.is_active():
                raise api_exceptions.ConflictingRequest(
                    message="import operation status does not allow uploads",
                    detail={"status": record.status},
                )

            if not request.content_length:
                raise api_exceptions.BadRequest(
                    message="Request must contain content-length header",
                    detail={})
            elif request.content_length > MAX_UPLOAD_SIZE:
                raise api_exceptions.BadRequest(
                    message=
                    "too large. Max size of 100MB supported for content",
                    detail={"content-length": request.content_length},
                )

            digest, created_at = save_import_content(db_session, operation_id,
                                                     request.data,
                                                     content_type)

        resp = {
            "digest": digest,
            "created_at": datetime_to_rfc3339(created_at)
        }

        return resp, 200
    except api_exceptions.AnchoreApiError as ex:
        return (
            make_response_error(ex, in_httpcode=ex.__response_code__),
            ex.__response_code__,
        )
    except Exception as ex:
        logger.exception("Unexpected error in api processing")
        return make_response_error(ex, in_httpcode=500), 500
Exemple #28
0
def create_account(account):
    """
    POST /accounts

    :param account:
    :return:
    """

    try:
        try:
            can_create_account(account)
        except ValueError as ex:
            return make_response_error('Invalid account request: {}'.format(
                ex.args[0]),
                                       in_httpcode=400), 400
        except Exception as ex:
            logger.exception('Unexpected exception in account validation')
            return make_response_error('Invalid account request',
                                       in_httpcode=400), 400

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            try:
                resp = mgr.create_account(account_name=account['name'],
                                          account_type=account.get(
                                              'type', AccountTypes.user.value),
                                          email=account.get('email'))
            except ValueError as ex:
                return make_response_error('Validation failed: {}'.format(ex),
                                           in_httpcode=400), 400

            authorizer.notify(NotificationTypes.domain_created,
                              account['name'])

            # Initialize account stuff
            try:
                _init_policy(account['name'], config=get_config())
            except Exception:
                logger.exception(
                    'Could not initialize policy bundle for new account: {}'.
                    format(account['name']))
                raise

        return account_db_to_msg(resp), 200
    except AccountAlreadyExistsError as ex:
        return make_response_error(errmsg='Account already exists',
                                   in_httpcode=400), 400
    except Exception as ex:
        logger.exception('Unexpected Error creating account')
        return make_response_error('Error creating account',
                                   in_httpcode=500), 500
def list_artifacts(user_id, image_id, artifact_type):
    db = get_session()
    try:
        log.info("Getting retrieved files from image {}/{}".format(user_id, image_id))
        img = db.query(Image).get((image_id, user_id))
        if img:
            handlers = artifact_handlers.get(artifact_type)
            if not handlers:
                # Bad request
                return (
                    make_response_error(
                        "Invalid artifact type {}".format(artifact_type),
                        in_httpcode=400,
                    ),
                    400,
                )

            if not handlers.get("filter") or not handlers.get("mapper"):
                raise Exception(
                    "incomplete artifact handler definition for {}".format(
                        artifact_type
                    )
                )

            filter_fn = handlers["filter"]
            artifact_items = filter_fn(img).all()
            map_fn = handlers["mapper"]

            artifact_listing = [map_fn(x) for x in artifact_items]
            return artifact_listing, 200
        else:
            return None, 404
    except HTTPException:
        raise
    except Exception as e:
        log.exception(
            "Error processing GET request for artifacts on image {}/{}".format(
                user_id, image_id
            )
        )
        return (
            make_response_error(
                "Error getting artifacts from image {}/{}: {}".format(
                    user_id, image_id, e
                ),
                in_httpcode=500,
            ),
            500,
        )
    finally:
        db.rollback()
Exemple #30
0
def delete_account(accountname):
    """
    DELETE /account/{accountname}

    :param accountname:
    :return:
    """

    try:

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            account = verify_account(accountname, mgr)
            if not can_delete_account(account):
                return (
                    make_response_error("Account cannot be deleted",
                                        in_httpcode=400),
                    400,
                )
            else:
                account = mgr.update_account_state(accountname,
                                                   AccountStates.deleting)

                # Flush from authz system if necessary
                authorizer.notify(NotificationTypes.domain_deleted,
                                  accountname)

                users = mgr.list_users(accountname)
                for user in users:
                    # Flush users
                    logger.debug(
                        "Deleting account user {} on authz system if using plugin"
                        .format(user["username"]))
                    authorizer.notify(NotificationTypes.principal_deleted,
                                      user["username"])

                    logger.debug("Deleting account user: {}".format(
                        user["username"]))
                    mgr.delete_user(user["username"])

            return account_db_to_status_msg(account), 200
    except InvalidStateError as ex:
        return make_response_error(str(ex), in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as e:
        logger.exception("API Error")
        return make_response_error("Error deleting account",
                                   in_httpcode=500), 500