Implement validation on Policy V3 API

Use JSONSchema to validate create and update operations on V3
Policy API.

Change-Id: I43146fce5018330eba2119194325bde29e4759bb
bp: api-validation
This commit is contained in:
Lance Bragstad 2014-07-23 20:01:32 +00:00 committed by Steve Martinelli
parent 647193db68
commit 28f60cfa69
3 changed files with 116 additions and 2 deletions

View File

@ -14,6 +14,8 @@
from keystone.common import controller from keystone.common import controller
from keystone.common import dependency from keystone.common import dependency
from keystone.common import validation
from keystone.policy import schema
@dependency.requires('policy_api') @dependency.requires('policy_api')
@ -22,10 +24,9 @@ class PolicyV3(controller.V3Controller):
member_name = 'policy' member_name = 'policy'
@controller.protected() @controller.protected()
@validation.validated(schema.policy_create, 'policy')
def create_policy(self, context, policy): def create_policy(self, context, policy):
ref = self._assign_unique_id(self._normalize_dict(policy)) ref = self._assign_unique_id(self._normalize_dict(policy))
self._require_attribute(ref, 'blob')
self._require_attribute(ref, 'type')
ref = self.policy_api.create_policy(ref['id'], ref) ref = self.policy_api.create_policy(ref['id'], ref)
return PolicyV3.wrap_member(context, ref) return PolicyV3.wrap_member(context, ref)
@ -42,6 +43,7 @@ class PolicyV3(controller.V3Controller):
return PolicyV3.wrap_member(context, ref) return PolicyV3.wrap_member(context, ref)
@controller.protected() @controller.protected()
@validation.validated(schema.policy_update, 'policy')
def update_policy(self, context, policy_id, policy): def update_policy(self, context, policy_id, policy):
ref = self.policy_api.update_policy(policy_id, policy) ref = self.policy_api.update_policy(policy_id, policy)
return PolicyV3.wrap_member(context, ref) return PolicyV3.wrap_member(context, ref)

36
keystone/policy/schema.py Normal file
View File

@ -0,0 +1,36 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_policy_properties = {
'blob': {
'type': 'string'
},
'type': {
'type': 'string',
'maxLength': 255
}
}
policy_create = {
'type': 'object',
'properties': _policy_properties,
'required': ['blob', 'type'],
'additionalProperties': True
}
policy_update = {
'type': 'object',
'properties': _policy_properties,
'minProperties': 1,
'additionalProperties': True
}

View File

@ -20,6 +20,7 @@ from keystone.common import validation
from keystone.common.validation import parameter_types from keystone.common.validation import parameter_types
from keystone.common.validation import validators from keystone.common.validation import validators
from keystone import exception from keystone import exception
from keystone.policy import schema as policy_schema
"""Example model to validate create requests against. Assume that this is """Example model to validate create requests against. Assume that this is
the only backend for the create and validate schemas. This is just an the only backend for the create and validate schemas. This is just an
@ -534,3 +535,78 @@ class RoleValidationTestCase(testtools.TestCase):
self.assertRaises(exception.SchemaValidationError, self.assertRaises(exception.SchemaValidationError,
self.update_role_validator.validate, self.update_role_validator.validate,
request_to_validate) request_to_validate)
class PolicyValidationTestCase(testtools.TestCase):
"""Test for V3 Policy API validation."""
def setUp(self):
super(PolicyValidationTestCase, self).setUp()
create = policy_schema.policy_create
update = policy_schema.policy_update
self.create_policy_validator = validators.SchemaValidator(create)
self.update_policy_validator = validators.SchemaValidator(update)
def test_validate_policy_succeeds(self):
"""Test that we validate a create policy request."""
request_to_validate = {'blob': 'some blob information',
'type': 'application/json'}
self.create_policy_validator.validate(request_to_validate)
def test_validate_policy_without_blob_fails(self):
"""Exception raised without `blob` in request."""
request_to_validate = {'type': 'application/json'}
self.assertRaises(exception.SchemaValidationError,
self.create_policy_validator.validate,
request_to_validate)
def test_validate_policy_without_type_fails(self):
"""Exception raised without `type` in request."""
request_to_validate = {'blob': 'some blob information'}
self.assertRaises(exception.SchemaValidationError,
self.create_policy_validator.validate,
request_to_validate)
def test_validate_policy_create_with_extra_parameters_succeeds(self):
"""Validate policy create with extra parameters."""
request_to_validate = {'blob': 'some blob information',
'type': 'application/json',
'extra': 'some extra stuff'}
self.create_policy_validator.validate(request_to_validate)
def test_validate_policy_create_with_invalid_type_fails(self):
"""Exception raised when `blob` and `type` are boolean."""
for prop in ['blob', 'type']:
request_to_validate = {prop: False}
self.assertRaises(exception.SchemaValidationError,
self.create_policy_validator.validate,
request_to_validate)
def test_validate_policy_update_without_parameters_fails(self):
"""Exception raised when updating policy without parameters."""
request_to_validate = {}
self.assertRaises(exception.SchemaValidationError,
self.update_policy_validator.validate,
request_to_validate)
def test_validate_policy_update_with_extra_parameters_succeeds(self):
"""Validate policy update request with extra parameters."""
request_to_validate = {'blob': 'some blob information',
'type': 'application/json',
'extra': 'some extra stuff'}
self.update_policy_validator.validate(request_to_validate)
def test_validate_policy_update_succeeds(self):
"""Test that we validate a policy update request."""
request_to_validate = {'blob': 'some blob information',
'type': 'application/json'}
self.update_policy_validator.validate(request_to_validate)
def test_validate_policy_update_with_invalid_type_fails(self):
"""Exception raised when invalid `type` on policy update."""
for prop in ['blob', 'type']:
request_to_validate = {prop: False}
self.assertRaises(exception.SchemaValidationError,
self.update_policy_validator.validate,
request_to_validate)