Add more validation to barbican order

Change-Id: I37d014f46b5ba0f2732507f54bebe0a82b872092
Closes-Bug: #1540937
This commit is contained in:
Oleksii Chuprykov 2016-02-11 19:39:38 +02:00
parent 4686c5d2f2
commit fe7d14fba9
2 changed files with 71 additions and 2 deletions

View File

@ -11,6 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import six
from heat.common import exception
from heat.common.i18n import _
from heat.engine import attributes
@ -61,6 +63,22 @@ class Order(resource.Resource):
'key', 'asymmetric', 'certificate'
)
# full-cmc is declared but not yet supported in barbican
REQUEST_TYPES = (
STORED_KEY, SIMPLE_CMC, CUSTOM
) = (
'stored-key', 'simple-cmc', 'custom'
)
ALLOWED_PROPERTIES_FOR_TYPE = {
KEY: [NAME, ALGORITHM, BIT_LENGTH, MODE, PAYLOAD_CONTENT_TYPE,
EXPIRATION],
ASYMMETRIC: [NAME, ALGORITHM, BIT_LENGTH, MODE, PASS_PHRASE,
PAYLOAD_CONTENT_TYPE, EXPIRATION],
CERTIFICATE: [NAME, REQUEST_TYPE, SUBJECT_DN, SOURCE_CONTAINER_REF,
CA_ID, PROFILE, REQUEST_DATA]
}
properties_schema = {
NAME: properties.Schema(
properties.Schema.STRING,
@ -105,6 +123,7 @@ class Order(resource.Resource):
properties.Schema.STRING,
_('The type of the certificate request.'),
support_status=support.SupportStatus(version='5.0.0'),
constraints=[constraints.AllowedValues(REQUEST_TYPES)]
),
SUBJECT_DN: properties.Schema(
properties.Schema.STRING,
@ -128,12 +147,13 @@ class Order(resource.Resource):
),
REQUEST_DATA: properties.Schema(
properties.Schema.STRING,
_('The content of the CSR.'),
_('The content of the CSR. Only for certificate orders.'),
support_status=support.SupportStatus(version='5.0.0'),
),
PASS_PHRASE: properties.Schema(
properties.Schema.STRING,
_('The passphrase the created key.'),
_('The passphrase the created key. Can be set only '
'for asymmetric type of order.'),
support_status=support.SupportStatus(version='5.0.0'),
),
}
@ -189,6 +209,7 @@ class Order(resource.Resource):
return order_ref
def validate(self):
super(Order, self).validate()
if self.properties[self.TYPE] != self.CERTIFICATE:
if (self.properties[self.ALGORITHM] is None
or self.properties[self.BIT_LENGTH] is None):
@ -198,6 +219,19 @@ class Order(resource.Resource):
'bit_length': self.BIT_LENGTH,
'type': self.properties[self.TYPE]}
raise exception.StackValidationFailed(message=msg)
declared_props = sorted([k for k, v in six.iteritems(
self.properties) if k != self.TYPE and v is not None])
allowed_props = sorted(self.ALLOWED_PROPERTIES_FOR_TYPE[
self.properties[self.TYPE]])
diff = sorted(set(declared_props) - set(allowed_props))
if diff:
msg = _("Unexpected properties: %(unexpected)s. Only these "
"properties are allowed for %(type)s type of order: "
"%(allowed)s.") % {
'unexpected': ', '.join(diff),
'type': self.properties[self.TYPE],
'allowed': ', '.join(allowed_props)}
raise exception.StackValidationFailed(message=msg)
def check_create_complete(self, order_href):
order = self.client().orders.get(order_href)

View File

@ -106,6 +106,41 @@ class TestOrder(common.HeatTestCase):
msg,
res.validate)
def test_key_order_validation_fail(self):
snippet = copy.deepcopy(self.res_template)
snippet['Properties']['pass_phrase'] = "something"
res = self._create_resource('test', snippet, self.stack)
msg = ("Unexpected properties: pass_phrase. Only these properties "
"are allowed for key type of order: algorithm, "
"bit_length, expiration, mode, name, payload_content_type.")
self.assertRaisesRegexp(exception.StackValidationFailed,
msg,
res.validate)
def test_certificate_validation_fail(self):
snippet = copy.deepcopy(self.res_template)
snippet['Properties']['type'] = 'certificate'
res = self._create_resource('test', snippet, self.stack)
msg = ("Unexpected properties: algorithm, bit_length, mode. Only "
"these properties are allowed for certificate type of order: "
"ca_id, name, profile, request_data, request_type, "
"source_container_ref, subject_dn.")
self.assertRaisesRegexp(exception.StackValidationFailed,
msg,
res.validate)
def test_asymmetric_order_validation_fail(self):
snippet = copy.deepcopy(self.res_template)
snippet['Properties']['type'] = 'asymmetric'
snippet['Properties']['subject_dn'] = 'asymmetric'
res = self._create_resource('test', snippet, self.stack)
msg = ("Unexpected properties: subject_dn. Only these properties are "
"allowed for asymmetric type of order: algorithm, bit_length, "
"expiration, mode, name, pass_phrase, payload_content_type")
self.assertRaisesRegexp(exception.StackValidationFailed,
msg,
res.validate)
def test_attributes(self):
mock_order = mock.Mock()
mock_order.status = 'test-status'