diff --git a/awx/api/serializers.py b/awx/api/serializers.py index b580f57ec3..d06a179b55 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -2141,6 +2141,14 @@ class CredentialSerializer(BaseSerializer): return value return super(CredentialSerializer, self).to_internal_value(data) + def validate_credential_type(self, credential_type): + if self.instance and credential_type.pk != self.instance.credential_type.pk: + raise ValidationError( + _('You cannot change the credential type of the credential, as it may break the functionality' + ' of the resources using it.'), + ) + return credential_type + class CredentialSerializerCreate(CredentialSerializer): diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py index 89ad3cf4e2..9b81498bfa 100644 --- a/awx/main/models/credential.py +++ b/awx/main/models/credential.py @@ -1030,4 +1030,3 @@ def insights(cls): }, }, ) - diff --git a/awx/main/tests/functional/api/test_credential.py b/awx/main/tests/functional/api/test_credential.py index 1bddd26f8f..8063ff01e7 100644 --- a/awx/main/tests/functional/api/test_credential.py +++ b/awx/main/tests/functional/api/test_credential.py @@ -1446,6 +1446,34 @@ def test_field_removal(put, organization, admin, credentialtype_ssh, version, pa assert 'password' not in cred.inputs +@pytest.mark.django_db +def test_credential_type_immutable_in_v2(patch, organization, admin, credentialtype_ssh, credentialtype_aws): + cred = Credential( + credential_type=credentialtype_ssh, + name='Best credential ever', + organization=organization, + inputs={ + 'username': u'jim', + 'password': u'pass' + } + ) + cred.save() + + response = patch( + reverse('api:credential_detail', kwargs={'version': 'v2', 'pk': cred.pk}), + { + 'credential_type': credentialtype_aws.pk, + 'inputs': { + 'username': u'jim', + 'password': u'pass' + } + }, + admin + ) + assert response.status_code == 400 + assert 'credential_type' in response.data + + @pytest.mark.django_db @pytest.mark.parametrize('version, params', [ ['v1', {