From b4a785be1d5c7a6c43f4aa0ba65a7147aa161f37 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Robles Date: Fri, 23 Jan 2015 13:06:39 +0200 Subject: [PATCH] Fix content type validation if missing payload If no payload is provided, our API specifies that the payload's content type will be optional, but this doesn't mean that it will not be validated. This commit disables clients putting unsupported content types. Closes-Bug: #1376490 Change-Id: I0836f30c8ea23eff515ff7d5f944f5cf85ebb5e8 --- barbican/common/validators.py | 23 +++++++++++++------ barbican/tests/api/test_resources.py | 12 ++++++++-- barbican/tests/common/test_validators.py | 6 +++-- .../api/v1/functional/test_orders.py | 8 +++---- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/barbican/common/validators.py b/barbican/common/validators.py index eb2335efa..426979b8c 100644 --- a/barbican/common/validators.py +++ b/barbican/common/validators.py @@ -154,9 +154,9 @@ class NewSecretValidator(ValidatorBase): expiration = self._extract_expiration(json_data, schema_name) self._assert_expiration_is_valid(expiration, schema_name) json_data['expiration'] = expiration + content_type = json_data.get('payload_content_type') if 'payload' in json_data: - content_type = json_data.get('payload_content_type') content_encoding = json_data.get('payload_content_encoding') self._validate_content_parameters(content_type, content_encoding, schema_name) @@ -173,6 +173,10 @@ class NewSecretValidator(ValidatorBase): "payload_content_type is specified"), "payload") + if content_type: + self._validate_payload_content_type_is_supported(content_type, + schema_name) + return json_data def _extract_name(self, json_data): @@ -225,12 +229,8 @@ class NewSecretValidator(ValidatorBase): "be supplied."), "payload_content_type") - self._assert_validity( - content_type.lower() in mime_types.SUPPORTED, - schema_name, - u._("payload_content_type is not one of {supported}").format( - supported=mime_types.SUPPORTED), - "payload_content_type") + self._validate_payload_content_type_is_supported(content_type, + schema_name) if content_type == 'application/octet-stream': self._assert_validity( @@ -248,6 +248,15 @@ class NewSecretValidator(ValidatorBase): "payload_content_type is text/plain"), "payload_content_encoding") + def _validate_payload_content_type_is_supported(self, content_type, + schema_name): + self._assert_validity( + content_type.lower() in mime_types.SUPPORTED, + schema_name, + u._("payload_content_type is not one of {supported}").format( + supported=mime_types.SUPPORTED), + "payload_content_type") + def _extract_payload(self, json_data): """Extracts and returns the payload from the JSON data. diff --git a/barbican/tests/api/test_resources.py b/barbican/tests/api/test_resources.py index 5da851fe9..ac1ce37e7 100644 --- a/barbican/tests/api/test_resources.py +++ b/barbican/tests/api/test_resources.py @@ -1516,8 +1516,7 @@ class WhenCreatingOrdersUsingOrdersResource(FunctionalTest): "algorithm": "AES", "bit_length": 256, "mode": "cbc", - 'payload_content_type': - 'application/octet-stream'} + 'payload_content_type': 'application/octet-stream'} self.key_order_req = {'type': self.type, 'meta': self.meta} @@ -1594,6 +1593,15 @@ class WhenCreatingOrdersUsingOrdersResource(FunctionalTest): ) self.assertEqual(resp.status_int, 415) + def test_should_raise_add_new_order_with_unsupported_content_type(self): + self.meta["payload_content_type"] = 'unsupported type' + resp = self.app.post_json( + '/orders/', + self.key_order_req, + expect_errors=True, + ) + self.assertEqual(resp.status_int, 400) + class WhenGettingOrdersListUsingOrdersResource(FunctionalTest): def setUp(self): diff --git a/barbican/tests/common/test_validators.py b/barbican/tests/common/test_validators.py index ea51a543a..d2592a479 100644 --- a/barbican/tests/common/test_validators.py +++ b/barbican/tests/common/test_validators.py @@ -887,8 +887,10 @@ class WhenTestingAsymmetricTypeOrderValidator(utils.BaseTestCase): self.asymmetric_order_req) def test_should_raise_with_wrong_payload_content_type_in_order_refs(self): - self.asymmetric_order_req['meta' - ]['payload_content_type'] = 'plain/text' + # NOTE(jaosorior): this is actually a valid content type, but it is not + # supported by asymmetric key orders. + self.asymmetric_order_req['meta']['payload_content_type'] = ( + 'text/plain') self.assertRaises(excep.UnsupportedField, self.validator.validate, self.asymmetric_order_req) diff --git a/functionaltests/api/v1/functional/test_orders.py b/functionaltests/api/v1/functional/test_orders.py index 25689eaf9..c0f34c541 100644 --- a/functionaltests/api/v1/functional/test_orders.py +++ b/functionaltests/api/v1/functional/test_orders.py @@ -384,11 +384,8 @@ class OrdersTestCase(base.TestCase): @utils.parameterized_dataset({ 'empty': [''], - 'invalid': ['invalid'], - 'text': ['text'], 'text/plain': ['text/plain'], 'text_plain_space_charset_utf8': ['text/plain; charset=utf-8'], - 'text_slash_with_no_subtype': ['text/'] }) @testcase.attr('positive') def test_create_order_defaults_valid_payload_content_type(self, pct): @@ -402,7 +399,10 @@ class OrdersTestCase(base.TestCase): @utils.parameterized_dataset({ 'int': [123], - 'oversized_string': [base.TestCase.oversized_field] + 'invalid': ['invalid'], + 'oversized_string': [base.TestCase.oversized_field], + 'text': ['text'], + 'text_slash_with_no_subtype': ['text/'], }) @testcase.attr('negative') def test_create_order_defaults_invalid_payload_content_type(self, pct):