diff --git a/awx/main/fields.py b/awx/main/fields.py index 852ea863eb..b2f144980f 100644 --- a/awx/main/fields.py +++ b/awx/main/fields.py @@ -673,6 +673,19 @@ class CredentialTypeInputField(JSONSchemaField): } } + def validate(self, value, model_instance): + super(CredentialTypeInputField, self).validate( + value, model_instance + ) + + for field in value.get('fields', []): + if field.get('id') == 'tower': + raise django_exceptions.ValidationError( + _('"tower" is a reserved field name'), + code='invalid', + params={'value': value}, + ) + class CredentialTypeInjectorField(JSONSchemaField): @@ -723,8 +736,14 @@ class CredentialTypeInjectorField(JSONSchemaField): value, model_instance ) - # make sure the inputs are clean first - CredentialTypeInputField().validate(model_instance.inputs, model_instance) + # make sure the inputs are valid first + try: + CredentialTypeInputField().validate(model_instance.inputs, model_instance) + except django_exceptions.ValidationError: + # If `model_instance.inputs` itself is invalid, we can't make an + # estimation as to whether our Jinja templates contain valid field + # names; don't continue + return # In addition to basic schema validation, search the injector fields # for template variables and make sure they match the fields defined in diff --git a/awx/main/tests/functional/test_credential.py b/awx/main/tests/functional/test_credential.py index 87e17034a8..62e6c49bcc 100644 --- a/awx/main/tests/functional/test_credential.py +++ b/awx/main/tests/functional/test_credential.py @@ -71,6 +71,7 @@ def test_cloud_kind_uniqueness(): ({'fields': [{'id': 'become_method', 'label': 'Become', 'choices': []}]}, False), ({'fields': [{'id': 'become_method', 'label': 'Become', 'choices': ['su', 'sudo']}]}, True), # noqa ({'fields': [{'id': 'become_method', 'label': 'Become', 'choices': ['dup', 'dup']}]}, False), # noqa + ({'fields': [{'id': 'tower', 'label': 'Reserved!', }]}, False), # noqa ]) def test_cred_type_input_schema_validity(input_, valid): type_ = CredentialType(