Beispiel #1
0
    def test_execute_with_unrecognizable_http_op_will_result_in_Nonetype_response(
            self):
        self.http_op = HttpOperation('OGRE', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     self.SAMPLE_OP_INFOS,
                                     {"X-API-Key": "abcdef123"}, False)

        result = self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)

        self.assertIsNone(result)
Beispiel #2
0
 def test_execute_will_delete_op_request_with_url_only(self, mock_delete):
     self.http_op = HttpOperation('delete', 'https://server.de/',
                                  'pet/{petId}/uploadImage',
                                  self.SAMPLE_OP_INFOS,
                                  {"X-API-Key": "abcdef123"}, False)
     self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)
     self.assertIn(
         mock.call(url='https://server.de/pet/0/uploadImage',
                   headers={"X-API-Key": "abcdef123"}),
         mock_delete.call_args_list)
Beispiel #3
0
 def test_execute_will_put_op_request_with_url_and_params_when_form_data_param_set(
         self, mock_put):
     self.http_op = HttpOperation('put', 'https://server.de/',
                                  'pet/{petId}/uploadImage',
                                  self.SAMPLE_OP_INFOS,
                                  {"X-API-Key": "abcdef123"}, False)
     self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)
     self.assertIn(
         mock.call(data={
             'status': '',
             'name': ''
         },
                   headers={"X-API-Key": "abcdef123"},
                   url='https://server.de/pet/0/uploadImage'),
         mock_put.call_args_list)
Beispiel #4
0
    def test_execute_with_parameter_definition_will_send_request_without_parameters_set(
            self, mock_get):
        definition_no_parameters = self.SAMPLE_OP_INFOS
        definition_no_parameters.pop('parameters', 0)
        self.http_op = HttpOperation('get', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     definition_no_parameters,
                                     {"X-API-Key": "abcdef123"}, False)

        self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)

        self.assertIn(
            mock.call(params={},
                      headers={"X-API-Key": "abcdef123"},
                      url='https://server.de/pet/{petId}/uploadImage'),
            mock_get.call_args_list)
Beispiel #5
0
def create_http_op_with_random_mock(op_code,
                                    host_basepath,
                                    path,
                                    op_infos,
                                    headers,
                                    ignore_tls=True):
    replicator = Replicator(ReplicatorTest.SAMPLE_DEFINITION, True, False)
    http_op = HttpOperation(op_code, host_basepath, path, op_infos, headers,
                            replicator, False, ignore_tls)
    http_op.random.getrandbits = MagicMock(return_value=True)
    return http_op
Beispiel #6
0
    def start(self):
        print('Fetching open API from: ' + self.url)

        # Try to find the protocol, host and basePath from the Swagger spec.
        # host and schemes can be omitted, and the "standard" says you should use the spec's URL to derive them.
        # https://swagger.io/docs/specification/2-0/api-host-and-base-path/
        schemes = []
        host = None
        basePath = None

        try:
            spec = self.get_swagger_spec(self.url)
            specURL = urlparse(self.url)
        except json.JSONDecodeError:
            error_cant_connect()

        if 'openapi' not in spec:
            if 'swagger' not in spec:
                self.log_operation(
                    None, self.url, {
                        "status_code":
                        "000",
                        "documented_reason":
                        "Specification: no version string found",
                        "body":
                        "Specification: no version string found in Swagger spec"
                    }, '')
                raise SchemaException

            if not spec['swagger'].startswith('2'):
                self.log_operation(
                    None, self.url, {
                        "status_code":
                        "000",
                        "documented_reason":
                        "Specification: wrong specification version",
                        "body":
                        "Specification: version in swagger spec not supported"
                    }, '')
                raise SchemaException
        elif not spec['openapi'].startswith('3'):
            self.log_operation(
                None, self.url, {
                    "status_code": "000",
                    "documented_reason":
                    "Specification: wrong specification version",
                    "body":
                    "Specification: version in openapi spec not supported"
                }, '')
            raise SchemaException
        baseUris = []
        if 'servers' in spec and len(spec['servers']) > 0:
            for server in spec['servers']:
                baseUris.append(server['url'])
        elif 'schemes' in spec:
            schemes = spec['schemes']
        else:
            # fake the array we'd find in the spec
            schemes.append(specURL.scheme)
            self.log_operation(
                None, self.url, {
                    "status_code": "000",
                    "documented_reason":
                    "Specification: no schemes entry, fallback to spec URL scheme",
                    "body":
                    "Specification: host entry not present in Swagger spec"
                }, '')
        if len(baseUris) == 0:
            if self.host:
                host = self.host
            elif 'host' in spec:
                host = spec['host']
            else:
                host = specURL.netloc
                self.log_operation(
                    None, self.url, {
                        "status_code":
                        "000",
                        "documented_reason":
                        "Specification: no host entry, fallback to spec URL host",
                        "body":
                        "Specification: schemes entry not present in Swagger spec"
                    }, '')

            # There is no nice way to derive the basePath from the spec's URL. They *have* to include it
            if 'basePath' not in spec:
                self.log_operation(
                    None, self.url, {
                        "status_code":
                        "000",
                        "documented_reason":
                        "Specification: basePath entry missing from Swagger spec",
                        "body":
                        "Specification Error: basePath entry missing from Swagger spec"
                    }, '')
                raise SchemaException
            basePath = self.basepath if self.basepath else spec['basePath']
            host_basepath = host + basePath
            for protocol in schemes:
                baseUris.append(protocol + '://' + host_basepath)

        paths = spec['paths']
        if 'definitions' in spec:
            type_definitions = spec['definitions']
        elif 'components' in spec and 'schemas' in spec['components']:
            type_definitions = spec['components']['schemas']
        else:
            self.log_operation(
                None, self.url, {
                    "status_code":
                    "000",
                    "documented_reason":
                    "Specification: type definitions missing from Swagger spec",
                    "body":
                    "Specification Error: type definitions missing from Swagger spec"
                }, '')
            raise SchemaException
        # the specifcation can list multiple schemes (http, https, ws, wss) - all should be tested.
        # Each scheme is a potentially different end point
        replicator = Replicator(type_definitions, self.use_string_pattern,
                                True, self.max_string_length)
        for baseUri in baseUris:
            for path_key in paths.keys():
                if path_key in self.ignored_paths:
                    continue
                path = paths[path_key]

                for op_code in path.keys():
                    operation = HttpOperation(op_code,
                                              baseUri,
                                              path_key,
                                              replicator=replicator,
                                              op_infos=path[op_code],
                                              use_fuzzing=True,
                                              headers=self.headers,
                                              ignore_tls=self.ignore_tls)

                    for _ in range(self.iterations):
                        response = operation.execute()
                        validator = ResultValidator()
                        log = validator.evaluate(
                            response, path[op_code]['responses'],
                            self.log_unexpected_errors_only)
                        curlcommand = CurlCommand(response.url,
                                                  operation.op_code,
                                                  operation.request_body,
                                                  self.headers,
                                                  self.ignore_tls)

                        # log to screen for now
                        self.log_operation(operation.op_code, response.url,
                                           log, curlcommand)

        return True
Beispiel #7
0
    def start(self):
        print('Fetching open API from: ' + self.url)

        # Try to find the protocol, host and basePath from the Swagger spec.
        # host and schemes can be omitted, and the "standard" says you should use the spec's URL to derive them.
        # https://swagger.io/docs/specification/2-0/api-host-and-base-path/
        schemes = []
        host = None
        basePath = None

        client = SwaggerClient.from_url(self.url)
        spec = client.swagger_spec.spec_dict
        specURL = urlparse(self.url)

        if 'schemes' in spec:
            schemes = spec['schemes']
        else:
            # fake the array we'd find in the spec
            schemes.append(specURL.scheme)
            self.log_operation(
                None, self.url, {
                    "status_code": "000",
                    "documented_reason":
                    "Specification: no schemes entry, fallback to spec URL scheme",
                    "body":
                    "Specification: host entry not present in Swagger spec"
                }, '')

        if 'host' in spec:
            host = spec['host']
        else:
            host = specURL.netloc
            self.log_operation(
                None, self.url, {
                    "status_code":
                    "000",
                    "documented_reason":
                    "Specification: no host entry, fallback to spec URL host",
                    "body":
                    "Specification: schemes entry not present in Swagger spec"
                }, '')

        # There is no nice way to derive the basePath from the spec's URL. They *have* to include it
        if 'basePath' not in spec:
            self.log_operation(
                None, self.url, {
                    "status_code":
                    "000",
                    "body":
                    "Specification Error: basePath entry missing from Swagger spec"
                }, '')
        host_basepath = host + spec['basePath']
        paths = spec['paths']
        type_definitions = spec['definitions']
        # the specifcation can list multiple schemes (http, https, ws, wss) - all should be tested.
        # Each scheme is a potentially different end point
        for protocol in schemes:
            for path_key in paths.keys():
                path = paths[path_key]

                for op_code in path.keys():
                    operation = HttpOperation(op_code,
                                              protocol + '://' + host_basepath,
                                              path_key,
                                              op_infos=path[op_code],
                                              use_fuzzing=True,
                                              headers=self.headers)

                    for x in range(self.iterations):
                        response = operation.execute(type_definitions)
                        validator = ResultValidator()
                        log = validator.evaluate(
                            response, path[op_code]['responses'],
                            self.log_unexpected_errors_only)
                        curlcommand = CurlCommand(response.url,
                                                  operation.op_code,
                                                  operation.request_body,
                                                  self.headers)

                        # log to screen for now
                        self.log_operation(operation.op_code, response.url,
                                           log, curlcommand)
Beispiel #8
0
 def setUp(self):
     self.http_op = HttpOperation('post', 'https://server.de/',
                                  'pet/{petId}/uploadImage',
                                  self.SAMPLE_OP_INFOS,
                                  {"X-API-Key": "abcdef123"}, False)
Beispiel #9
0
class HttpOperationTest(TestCase):
    SAMPLE_OP_INFOS = {
        "tags": ["pet"],
        "summary":
        "Updates a pet in the store with form data",
        "description":
        "",
        "operationId":
        "updatePetWithForm",
        "consumes": ["application/x-www-form-urlencoded"],
        "produces": ["application/xml", "application/json"],
        "parameters": [{
            "name": "petId",
            "in": "path",
            "description": "ID of pet that needs to be updated",
            "required": True,
            "type": "integer",
            "format": "int64"
        }, {
            "name": "name",
            "in": "formData",
            "description": "Updated name of the pet",
            "required": False,
            "type": "string"
        }, {
            "name": "status",
            "in": "formData",
            "description": "Updated status of the pet",
            "required": False,
            "type": "string"
        }],
        "responses": {
            "405": {
                "description": "Invalid input"
            }
        },
        "security": [{
            "petstore_auth": ["write:pets", "read:pets"]
        }]
    }

    def setUp(self):
        self.http_op = HttpOperation('post', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     self.SAMPLE_OP_INFOS,
                                     {"X-API-Key": "abcdef123"}, False)

    def test_replace_url_parameter_replaces_placeholder_in_url_with_type_value(
            self):
        url = self.http_op.replace_url_parameter(
            ReplicatorTest.SAMPLE_DEFINITION, self.http_op.url, 'petId',
            'integer')
        self.assertEqual(url, 'https://server.de/pet/0/uploadImage')

    def test_replace_url_parameter_replaces_only_named_param(self):
        url = self.http_op.replace_url_parameter(
            ReplicatorTest.SAMPLE_DEFINITION,
            'https://server.de/pet/{petId}/uploadImage/{imgName}', 'imgName',
            'string')
        self.assertEqual(url, 'https://server.de/pet/{petId}/uploadImage/')

    def test_create_form_parameter_makes_instance_of_type_as_string(self):
        value = self.http_op.create_form_parameter(
            ReplicatorTest.SAMPLE_DEFINITION, 'integer')
        self.assertEqual(value, '0')

    def test_execute_with_unrecognizable_http_op_will_result_in_Nonetype_response(
            self):
        self.http_op = HttpOperation('OGRE', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     self.SAMPLE_OP_INFOS,
                                     {"X-API-Key": "abcdef123"}, False)

        result = self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)

        self.assertIsNone(result)

    @patch('requests.get', side_effect=mock_request_get)
    def test_execute_with_parameter_definition_will_send_request_without_parameters_set(
            self, mock_get):
        definition_no_parameters = self.SAMPLE_OP_INFOS
        definition_no_parameters.pop('parameters', 0)
        self.http_op = HttpOperation('get', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     definition_no_parameters,
                                     {"X-API-Key": "abcdef123"}, False)

        self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)

        self.assertIn(
            mock.call(params={},
                      headers={"X-API-Key": "abcdef123"},
                      url='https://server.de/pet/{petId}/uploadImage'),
            mock_get.call_args_list)

    @patch('requests.post', side_effect=mock_request_post)
    def test_execute_will_post__op_request_with_params_when_form_data_param_set(
            self, mock_post):
        self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)
        self.assertIn(
            mock.call(data={
                'status': '',
                'name': ''
            },
                      json=None,
                      headers={"X-API-Key": "abcdef123"},
                      url='https://server.de/pet/0/uploadImage'),
            mock_post.call_args_list)

    @patch('requests.get', side_effect=mock_request_get)
    def test_execute_will_get_op_request_with_url_and_params_when_form_data_param_set(
            self, mock_get):
        self.http_op = HttpOperation('get', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     self.SAMPLE_OP_INFOS,
                                     {"X-API-Key": "abcdef123"}, False)
        self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)
        self.assertIn(
            mock.call(params={
                'status': '',
                'name': ''
            },
                      url='https://server.de/pet/0/uploadImage',
                      headers={"X-API-Key": "abcdef123"}),
            mock_get.call_args_list)

    @patch('requests.delete', side_effect=mock_request_delete)
    def test_execute_will_delete_op_request_with_url_only(self, mock_delete):
        self.http_op = HttpOperation('delete', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     self.SAMPLE_OP_INFOS,
                                     {"X-API-Key": "abcdef123"}, False)
        self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)
        self.assertIn(
            mock.call(url='https://server.de/pet/0/uploadImage',
                      headers={"X-API-Key": "abcdef123"}),
            mock_delete.call_args_list)

    @patch('requests.put', side_effect=mock_request_put)
    def test_execute_will_put_op_request_with_url_and_params_when_form_data_param_set(
            self, mock_put):
        self.http_op = HttpOperation('put', 'https://server.de/',
                                     'pet/{petId}/uploadImage',
                                     self.SAMPLE_OP_INFOS,
                                     {"X-API-Key": "abcdef123"}, False)
        self.http_op.execute(ReplicatorTest.SAMPLE_DEFINITION)
        self.assertIn(
            mock.call(data={
                'status': '',
                'name': ''
            },
                      headers={"X-API-Key": "abcdef123"},
                      url='https://server.de/pet/0/uploadImage'),
            mock_put.call_args_list)