def validate_request(req, path_pattern, path_params, spec, url):
    print('Validating URL: {}'.format(url))
    counters['requests'] += 1
    openapi_request = RequestsOpenAPIRequest(req, path_pattern, path_params)
    validator = RequestValidator(spec)
    result = validator.validate(openapi_request)
    request_errors = result.errors

    r = req.prepare()
    s = requests.Session()
    res = s.send(r)

    openapi_response = RequestsOpenAPIResponse(res)
    validator = ResponseValidator(spec)
    result = validator.validate(openapi_request, openapi_response)
    response_errors = result.errors

    print('Request errors: {}'.format(request_errors))
    print('Response errors: {}'.format(response_errors))
    if request_errors or response_errors:
        errors_count = len(request_errors) + len(response_errors)
        print(color(' [FAIL] {:d} errors found '.format(errors_count), fg='white', bg='red', style='bold'))
        print("Response body: {}".format(res.text))
    else:
        errors_count = 0
        print(color(' [PASS] No errors found ', fg='white', bg='green', style='bold'))
    print()
    return errors_count
def validate_request(req, path_pattern, path_params, spec, url):
    print('Validating URL: {}'.format(url))
    counters['requests'] += 1
    openapi_request = RequestsOpenAPIRequest(req, path_pattern, path_params)
    validator = RequestValidator(spec)
    result = validator.validate(openapi_request)
    request_errors = result.errors

    r = req.prepare()
    s = requests.Session()
    res = s.send(r)

    openapi_response = RequestsOpenAPIResponse(res)
    validator = ResponseValidator(spec)
    result = validator.validate(openapi_request, openapi_response)
    response_errors = result.errors

    print('Request errors: {}'.format(request_errors))
    print('Response errors: {}'.format(response_errors))
    if request_errors or response_errors:
        errors_count = len(request_errors) + len(response_errors)
        print(
            color(' [FAIL] {:d} errors found '.format(errors_count),
                  fg='white',
                  bg='red',
                  style='bold'))
        print("Response body: {}".format(res.text))
    else:
        errors_count = 0
        print(
            color(' [PASS] No errors found ',
                  fg='white',
                  bg='green',
                  style='bold'))
    print()
    return errors_count
Exemple #3
0
class OpenApiSpecManager(SharedExtension):

    _loaded = Event()

    def setup(self):
        log.info('   ###   OpenApiSpecManager.setup')
        super().setup()

    def load_spec(self, spec_file):
        log.debug('%s.load_spec: %s' % (self.__class__.__name__, spec_file))
        # TODO: supporting loading from url instead of just file
        # TODO: How to handle/interpret/respect spec.servers[].url's?
        # TODO: Or should this be generated/injected into the spec_dict on startup?
        #spec_file = '/home/sar/vcs/nameko-openapi/petstore.yaml'
        spec_dict = yaml.safe_load(open(spec_file))
        self.spec = openapi_core.create_spec(spec_dict)
        self.request_validator = RequestValidator(self.spec)
        self.response_validator = ResponseValidator(self.spec)
        self._loaded.send(self.spec)

    def wait_for_spec(self):
        """Allow other extensions to wait until the spec is loaded."""
        return self._loaded.wait()

    def get_operation_by_id(self, operation_id):
        self.wait_for_spec()
        for path_name, path in six.iteritems(self.spec.paths):
            for http_method, operation in six.iteritems(path.operations):
                if operation.operation_id == operation_id:
                    return operation

    def validate_request(self, request, raise_for_errors=True):
        result = self.request_validator.validate(request)
        if raise_for_errors:
            result.raise_for_errors()
        return result

    def validate_response(self,
                          response,
                          openapi_request,
                          raise_for_errors=True):
        result = self.response_validator.validate(openapi_request, response)
        if raise_for_errors:
            result.raise_for_errors()
        return result
Exemple #4
0
    def register():
        spec_dict = read_yaml_file(filepath)

        validate_spec(spec_dict)
        spec = create_spec(spec_dict)

        def spec_view(request):
            return FileResponse(
                filepath,
                request=request,
                content_type='text/yaml'
            )
        config.add_view(route_name=route_name, view=spec_view)
        config.add_route(route_name, route)

        custom_formatters = config.registry.settings.get('pyramid_openapi3_formatters')

        config.registry.settings['pyramid_openapi3'] = {
           "filepath": filepath,
           "spec_route_name": route_name,
           "spec": spec,
           "request_validator": RequestValidator(spec, custom_formatters),
           "response_validator": ResponseValidator(spec, custom_formatters),
        }
    def put(self, tenant_id):
        logger.debug(f"top of PUT /tenants/{tenant_id}")
        tenant = Tenant.query.filter_by(tenant_id=tenant_id).first()
        if not tenant:
            raise errors.ResourceError(msg=f'No tenant found with tenant_id {tenant_id}.')
        # additional authorization checks on update based on the tenant_id of the request:
        check_authz_tenant_update(tenant_id)
        validator = RequestValidator(utils.spec)
        result = validator.validate(FlaskOpenAPIRequest(request))
        if result.errors:
            logger.debug(f"openapi_core validation failed. errors: {result.errors}")
            raise errors.ResourceError(msg=f'Invalid PUT data: {result.errors}.')
        validated_body = result.body
        logger.debug(f"initial openapi_core validation passed. validated_body: {dir(validated_body)}")
        # TODO --
        # ------------------------- This DOES NOT WORK ------------------------------------
        # the validated_body ONLY contains fields in the OAI spec; need to change this to look at the
        # request body itself
        if not getattr(validated_body, 'site_id', tenant.site_id) == tenant.site_id:
            raise errors.ResourceError(msg=f'Invalid PUT data: cannot change site_id.')
        if not getattr(validated_body, 'tenant_id', tenant.tenant_id) == tenant.tenant_id:
            raise errors.ResourceError(msg=f'Invalid PUT data: cannot change tenant_id.')
        if not getattr(validated_body, 'base_url', tenant.base_url) == tenant.base_url:
            raise errors.ResourceError(msg=f'Invalid PUT data: cannot change base_url.')
        # ------------------------------------------------------------------------------------

        # validate the existence of the ldap and owner objects:
        if getattr(validated_body, 'owner', None):
            owner = TenantOwner.query.filter_by(email=validated_body.owner).first()
            if not owner:
                raise errors.ResourceError(msg=f'Invalid tenant description. Owner {validated_body.owner} not found.')
            logger.debug("owner was valid.")
        if getattr(validated_body, 'user_ldap_connection_id', None):
            ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.user_ldap_connection_id).first()
            if not ldap:
                raise errors.ResourceError(msg=f'Invalid tenant description. '
                                               f'LDAP {validated_body.user_ldap_connection_id} not found.')
        if getattr(validated_body, 'service_ldap_connection_id', None) and \
                not validated_body.service_ldap_connection_id == getattr(validated_body, 'user_ldap_connection_id', None):
            ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.service_ldap_connection_id).first()
            if not ldap:
                raise errors.ResourceError(msg=f'Invalid tenant description. '
                                               f'LDAP {validated_body.service_ldap_connection_id} not found.')

        # overlay the tenant_current with the updates specified in the request body.
        changes_dict = {}
        # security_kernel
        new_security_kernel = getattr(validated_body, 'security_kernel', None)
        if new_security_kernel and not new_security_kernel == tenant.security_kernel:
            changes_dict['security_kernel'] = {'prev': tenant.security_kernel, 'new': new_security_kernel}
            tenant.security_kernel = new_security_kernel
        # token_service
        new_tokens_service = getattr(validated_body, 'token_service', None)
        if new_tokens_service and not new_tokens_service == tenant.token_service:
            changes_dict['tokens_service'] = {'prev': tenant.token_service, 'new': new_tokens_service}
            tenant.token_service = new_tokens_service
        # authenticator
        new_authenticator = getattr(validated_body, 'authenticator', None)
        if new_authenticator and not new_authenticator == tenant.authenticator:
            changes_dict['authenticator'] = {'prev': tenant.authenticator, 'new': new_authenticator}
            tenant.authenticator = new_authenticator
        # admin_user
        new_admin_user = getattr(validated_body, 'admin_user', None)
        if new_admin_user and not new_admin_user == tenant.admin_user:
            changes_dict['admin_user'] = {'prev': tenant.admin_user, 'new': new_admin_user}
            tenant.admin_user = new_admin_user
        # token_gen_services
        new_token_gen_services = getattr(validated_body, 'token_gen_services', None)
        if new_token_gen_services and not new_token_gen_services == tenant.token_gen_services:
            changes_dict['token_gen_services'] = {'prev': tenant.token_gen_services, 'new': new_token_gen_services}
            tenant.token_gen_services = new_token_gen_services
        # service_ldap_connection_id
        new_service_ldap_connection_id = getattr(validated_body, 'service_ldap_connection_id', None)
        if new_service_ldap_connection_id and not new_service_ldap_connection_id == tenant.service_ldap_connection_id:
            changes_dict['service_ldap_connection_id'] = {'prev': tenant.service_ldap_connection_id,
                                                          'new': new_service_ldap_connection_id}
            tenant.service_ldap_connection_id = new_service_ldap_connection_id
        # user_ldap_connection_id
        new_user_ldap_connection_id = getattr(validated_body, 'user_ldap_connection_id', None)
        if new_user_ldap_connection_id and not new_user_ldap_connection_id == tenant.user_ldap_connection_id:
            changes_dict['user_ldap_connection_id'] = {'prev': tenant.user_ldap_connection_id,
                                                          'new': new_user_ldap_connection_id}
            tenant.user_ldap_connection_id = new_user_ldap_connection_id
        # public_key
        new_public_key = getattr(validated_body, 'public_key', None)
        if new_public_key and not new_public_key == tenant.public_key:
            changes_dict['public_key'] = {'prev': tenant.public_key, 'new': new_public_key}
            tenant.public_key = new_public_key
        # status
        new_status = getattr(validated_body, 'status', None)
        if new_status and not new_status == tenant.status:
            changes_dict['status'] = {'prev': tenant.status.serialize, 'new': new_status.upper()}
            tenant.status = new_status
        # description
        new_description = getattr(validated_body, 'description', None)
        if new_description and not new_description == tenant.description:
            changes_dict['description'] = {'prev': tenant.description, 'new': new_description}
            tenant.description = new_description
        # owner
        new_owner = getattr(validated_body, 'owner', None)
        if new_owner and not new_owner == tenant.owner:
            changes_dict['owner'] = {'prev': tenant.owner, 'new': new_owner}
            tenant.owner = new_owner
        # last_update_time and last_updated_by
        update_time = datetime.datetime.utcnow()
        updated_by = f'{g.username}@{g.tenant_id}'
        tenant.last_update_time = update_time
        tenant.last_updated_by = updated_by
        # create the history record
        tenant_history = TenantHistory(
            tenant_id=tenant.tenant_id,
            update_time=update_time,
            updated_by=updated_by,
            updates_as_json=json.dumps(changes_dict)
        )
        db.session.add(tenant_history)
        try:
            db.session.commit()
            logger.info(f"update to tenant committed to db. tenant object: {tenant}")
        except (sqlalchemy.exc.SQLAlchemyError, sqlalchemy.exc.DBAPIError) as e:
            logger.debug(f"got exception trying to commit updated tenant object to db. Exception: {e}")
            msg = utils.get_message_from_sql_exc(e)
            logger.debug(f"returning msg: {msg}")
            raise errors.ResourceError(f"Invalid PUT data; {msg}")
        logger.debug("returning serialized tenant object.")
        return utils.ok(result=tenant.serialize, msg="Tenant updated successfully.")
    def post(self):
        logger.debug(f"top of POST /tenants")
        validator = RequestValidator(utils.spec)
        result = validator.validate(FlaskOpenAPIRequest(request))
        if result.errors:
            logger.debug(f"openapi_core validation failed. errors: {result.errors}")
            raise errors.ResourceError(msg=f'Invalid POST data: {result.errors}.')

        validated_body = result.body
        logger.debug(f"initial openapi_core validation passed. validated_body: {dir(validated_body)}")

        # check reserved words "owners" and "ldaps" -- these cannot be tenant id's:
        try:
            if validated_body.tenant_id.lower() == 'owners':
                raise errors.ResourceError("Invalid tenant_id; 'owners' is a reserved keyword.")
            if validated_body.tenant_id.lower() == 'ldaps':
                raise errors.ResourceError("Invalid tenant_id; 'ldaps' is a reserved keyword.")
            if validated_body.tenant_id.lower() == 'ready':
                raise errors.ResourceError("Invalid tenant_id; 'ready' is a reserved keyword.")
            if validated_body.tenant_id.lower() == 'hello':
                raise errors.ResourceError("Invalid tenant_id; 'hello' is a reserved keyword.")
        except Exception as e:
            msg = f"Could not check tenant description for reserved words; Errors: {e}"
            logger.error(msg)
            raise errors.ResourceError(msg)
        logger.debug("got past the reserved words check.")
        # validate the existence of the site object:
        try:
            site_id = validated_body.site_id
            site = Site.query.filter_by(site_id=site_id).first()
        except Exception as e:
            logger.error(f"Got exception trying to retrieve site; e: {e}")
            raise errors.ResourceError(msg='Invalid tenant description; could not verify site_id.')
        if not site:
            raise errors.ResourceError(msg=f'Invalid tenant description. site {validated_body.site_id} not found.')
        logger.debug(f"site_id {site_id} is ok.")
        # validate the existence of the ldap and owner objects:
        owner = TenantOwner.query.filter_by(email=validated_body.owner).first()
        if not owner:
            raise errors.ResourceError(msg=f'Invalid tenant description. Owner {validated_body.owner} not found.')
        logger.debug("owner was valid.")

        # ldap objects are optional:
        if getattr(validated_body, 'user_ldap_connection_id', None):
            ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.user_ldap_connection_id).first()
            if not ldap:
                raise errors.ResourceError(msg=f'Invalid tenant description. '
                                               f'LDAP {validated_body.user_ldap_connection_id} not found.')
        if getattr(validated_body, 'service_ldap_connection_id', None) and \
                not validated_body.service_ldap_connection_id == getattr(validated_body, 'user_ldap_connection_id', None):
            ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.service_ldap_connection_id).first()
            if not ldap:
                raise errors.ResourceError(msg=f'Invalid tenant description. '
                                               f'LDAP {validated_body.service_ldap_connection_id} not found.')

        logger.debug("ldap was valid; creating tenant record..")
        # create the tenant record --
        tenant = Tenant(tenant_id=validated_body.tenant_id,
                        base_url=validated_body.base_url,
                        site_id=validated_body.site_id,
                        status=validated_body.status,
                        public_key=getattr(validated_body, 'public_key', None),
                        token_service=validated_body.token_service,
                        security_kernel=validated_body.security_kernel,
                        authenticator=validated_body.authenticator,
                        owner=validated_body.owner,
                        admin_user=validated_body.admin_user,
                        token_gen_services=validated_body.token_gen_services,
                        service_ldap_connection_id=getattr(validated_body, 'service_ldap_connection_id', None),
                        user_ldap_connection_id=getattr(validated_body, 'user_ldap_connection_id', None),
                        description=getattr(validated_body, 'description', None),
                        create_time=datetime.datetime.utcnow(),
                        created_by=f'{g.username}@{g.tenant_id}',
                        last_updated_by=f'{g.username}@{g.tenant_id}',
                        last_update_time=datetime.datetime.utcnow())
        db.session.add(tenant)
        try:
            db.session.commit()
            logger.info(f"new tenant committed to db. tenant object: {tenant}")
        except (sqlalchemy.exc.SQLAlchemyError, sqlalchemy.exc.DBAPIError) as e:
            logger.debug(f"got exception trying to commit new tenant object to db. Exception: {e}")
            msg = utils.get_message_from_sql_exc(e)
            logger.debug(f"returning msg: {msg}")
            raise errors.ResourceError(f"Invalid POST data; {msg}")
        logger.debug("returning serialized tenant object.")
        return utils.ok(result=tenant.serialize, msg="Tenant created successfully.")
Exemple #7
0
from sqlalchemy import func
from sqlalchemy.exc import IntegrityError

from penguin_judge.models import (transaction, scoped_session, Contest,
                                  Environment, JudgeResult, JudgeStatus,
                                  Problem, Submission, TestCase, Token, User,
                                  Worker)
from penguin_judge.mq import get_mq_conn_params
from penguin_judge.utils import json_dumps, pagination_header

DEFAULT_MEMORY_LIMIT = 256  # MiB

app = Flask(__name__)
with open(os.path.join(os.path.dirname(__file__), 'schema.yaml'), 'r') as f:
    _spec = create_spec(yaml.safe_load(f))
_request_validator = RequestValidator(_spec)


def response204() -> Response:
    resp = make_response((b'', 204))
    resp.headers.pop(key='content-type')
    return resp


def jsonify(resp: Union[dict, list],
            *,
            status: Optional[int] = None,
            headers: Optional[Dict[str, str]] = None) -> Response:
    return app.response_class(json_dumps(resp),
                              mimetype=app.config["JSONIFY_MIMETYPE"],
                              status=status,
Exemple #8
0
from flask import Flask, request
import json
import os
from openapi_core import create_spec
from openapi_core.shortcuts import RequestValidator
from openapi_core.wrappers.flask import FlaskOpenAPIRequest
from pprint import pprint

app = Flask(__name__)

with open(f"{os.path.dirname(os.path.abspath(__file__))}/openapi.json") as f:
    openapi_file = json.load(f)

spec = create_spec(openapi_file)
validator = RequestValidator(spec)


@app.before_request
def validate():
    openapi_request = FlaskOpenAPIRequest(request)
    result = validator.validate(openapi_request)

    if result.errors:
        pprint(result.errors)


@app.route("/cars", methods=["POST"])
def new_car():
    # creating new car:
    pprint(request.json)
    return "created"