def _validate_bit_length(self, meta, schema_name): bit_length = int(meta.get('bit_length', 0)) if bit_length <= 0: raise exception.UnsupportedField(field="bit_length", schema=schema_name, reason=u._("Must have " "non-zero positive" " bit_length to" " generate secret")) if bit_length % 8 != 0: raise exception.UnsupportedField(field="bit_length", schema=schema_name, reason=u._("Must be a" " positive integer" " that is a" " multiple of 8"))
def validate(self, json_data, parent_schema=None): schema_name = self._full_name(parent_schema) self._assert_schema_is_valid(json_data, schema_name) container_type = json_data.get('type') secret_refs = json_data.get('secret_refs') if not secret_refs: return json_data secret_refs_names = set(secret_ref.get('name', '') for secret_ref in secret_refs) self._assert_validity( len(secret_refs_names) == len(secret_refs), schema_name, u._("Duplicate reference names are not allowed"), "secret_refs") # The combination of container_id and secret_id is expected to be # primary key for container_secret so same secret id (ref) cannot be # used within a container secret_ids = set(self._get_secret_id_from_ref(secret_ref) for secret_ref in secret_refs) self._assert_validity( len(secret_ids) == len(secret_refs), schema_name, u._("Duplicate secret ids are not allowed"), "secret_refs") # Ensure that our secret refs are valid relative to our config, no # spoofing allowed! req_host_href = utils.get_base_url_from_request() for secret_ref in secret_refs: if not secret_ref.get('secret_ref').startswith(req_host_href): raise exception.UnsupportedField( field='secret_ref', schema=schema_name, reason=u._( "Secret_ref does not match the configured hostname, " "please try again" ) ) if container_type == 'rsa': self._validate_rsa(secret_refs_names, schema_name) elif container_type == 'certificate': self._validate_certificate(secret_refs_names, schema_name) return json_data
def test_should_abort_with_validation_unsupported_field( self, mock_pecan_abort): mock_pecan_abort.side_effect = ValueError('Abort!') body = json.dumps({'key1': 'value1'}) req = mock.MagicMock() req.body_file = mock.MagicMock() req.body_file.read.return_value = body validator = mock.MagicMock() validator.validate.side_effect = exception.UnsupportedField('Field') exception_result = self.assertRaises( ValueError, api.load_body, req, validator=validator) self.assertEqual('Abort!', str(exception_result)) validator.validate.assert_called_once_with(json.loads(body))
def _validate_asymmetric_meta(self, asymmetric_meta, schema_name): """Validation specific to meta for asymmetric type order.""" # Validate secret metadata. secret_validator = NewSecretValidator() secret_validator.validate(asymmetric_meta, parent_schema=self.name) if (asymmetric_meta.get('payload_content_type', '').lower() != 'application/octet-stream'): raise exception.UnsupportedField(field='payload_content_type', schema=schema_name, reason=u._("Only 'application/oc" "tet-stream' " "supported")) self._assert_validity( asymmetric_meta.get('algorithm') is not None, schema_name, u._("'algorithm' is required field " "for asymmetric type order"), "meta") self._validate_bit_length(asymmetric_meta, schema_name)
def validate(self, json_data, parent_schema=None): schema_name = self._full_name(parent_schema) try: schema.validate(json_data, self.schema) except schema.ValidationError as e: raise exception.InvalidObject(schema=schema_name, reason=e.message, property=get_invalid_property(e)) secret = json_data.get('secret') if secret is None: raise exception.InvalidObject(schema=schema_name, reason=_("'secret' attributes " "are required"), property="secret") # If secret group is provided, validate it now. self.secret_validator.validate(secret, parent_schema=self.name) if 'payload' in secret: raise exception.InvalidObject(schema=schema_name, reason=_("'payload' not " "allowed for secret " "generation"), property="secret") # Validation secret generation related fields. # TODO: Invoke the crypto plugin for this purpose if secret.get('payload_content_type') != 'application/octet-stream': raise exception.UnsupportedField(field='payload_content_type', schema=schema_name, reason=_("Only 'application/oc" "tet-stream' supported")) if secret.get('mode', '').lower() != 'cbc': raise exception.UnsupportedField(field="mode", schema=schema_name, reason=_("Only 'cbc' " "supported")) if secret.get('algorithm', '').lower() != 'aes': raise exception.UnsupportedField(field="algorithm", schema=schema_name, reason=_("Only 'aes' " "supported")) # TODO(reaperhulk): Future API change will move from bit to byte_length bit_length = int(secret.get('bit_length', 0)) if bit_length <= 0: raise exception.UnsupportedField(field="bit_length", schema=schema_name, reason=_("Must have non-zero " "positive bit_length " "to generate secret")) if bit_length % 8 != 0: raise exception.UnsupportedField(field="bit_length", schema=schema_name, reason=_("Must be a positive " "integer that is a " "multiple of 8")) return json_data