mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 11:50:42 -03:30
Merge pull request #12227 from ansible/vaultcredentialsbug
Prevent edit of vault ID once credential is created.
This commit is contained in:
commit
2041665880
@ -2664,6 +2664,13 @@ class CredentialSerializer(BaseSerializer):
|
||||
|
||||
return credential_type
|
||||
|
||||
def validate_inputs(self, inputs):
|
||||
if self.instance and self.instance.credential_type.kind == "vault":
|
||||
if 'vault_id' in inputs and inputs['vault_id'] != self.instance.inputs['vault_id']:
|
||||
raise ValidationError(_('Vault IDs cannot be changed once they have been created.'))
|
||||
|
||||
return inputs
|
||||
|
||||
|
||||
class CredentialSerializerCreate(CredentialSerializer):
|
||||
|
||||
|
||||
@ -532,6 +532,49 @@ def test_vault_password_required(post, organization, admin):
|
||||
assert 'required fields (vault_password)' in j.job_explanation
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_vault_id_immutable(post, patch, organization, admin):
|
||||
vault = CredentialType.defaults['vault']()
|
||||
vault.save()
|
||||
response = post(
|
||||
reverse('api:credential_list'),
|
||||
{
|
||||
'credential_type': vault.pk,
|
||||
'organization': organization.id,
|
||||
'name': 'Best credential ever',
|
||||
'inputs': {'vault_id': 'password', 'vault_password': 'password'},
|
||||
},
|
||||
admin,
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert Credential.objects.count() == 1
|
||||
response = patch(
|
||||
reverse('api:credential_detail', kwargs={'pk': response.data['id']}), {'inputs': {'vault_id': 'password2', 'vault_password': 'password'}}, admin
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert response.data['inputs'][0] == 'Vault IDs cannot be changed once they have been created.'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_patch_without_vault_id_valid(post, patch, organization, admin):
|
||||
vault = CredentialType.defaults['vault']()
|
||||
vault.save()
|
||||
response = post(
|
||||
reverse('api:credential_list'),
|
||||
{
|
||||
'credential_type': vault.pk,
|
||||
'organization': organization.id,
|
||||
'name': 'Best credential ever',
|
||||
'inputs': {'vault_id': 'password', 'vault_password': 'password'},
|
||||
},
|
||||
admin,
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert Credential.objects.count() == 1
|
||||
response = patch(reverse('api:credential_detail', kwargs={'pk': response.data['id']}), {'name': 'worst_credential_ever'}, admin)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
#
|
||||
# Net Credentials
|
||||
#
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useField, useFormikContext } from 'formik';
|
||||
import { shape, string } from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
@ -31,6 +32,7 @@ function CredentialInput({
|
||||
fieldOptions,
|
||||
isFieldGroupValid,
|
||||
credentialKind,
|
||||
isVaultIdDisabled,
|
||||
...rest
|
||||
}) {
|
||||
const [fileName, setFileName] = useState('');
|
||||
@ -148,6 +150,7 @@ function CredentialInput({
|
||||
onChange={(value, event) => {
|
||||
subFormField.onChange(event);
|
||||
}}
|
||||
isDisabled={isVaultIdDisabled}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
/>
|
||||
);
|
||||
@ -167,6 +170,7 @@ CredentialInput.defaultProps = {
|
||||
|
||||
function CredentialField({ credentialType, fieldOptions }) {
|
||||
const { values: formikValues } = useFormikContext();
|
||||
const location = useLocation();
|
||||
const requiredFields = credentialType?.inputs?.required || [];
|
||||
const isRequired = requiredFields.includes(fieldOptions.id);
|
||||
const validateField = () => {
|
||||
@ -242,6 +246,15 @@ function CredentialField({ credentialType, fieldOptions }) {
|
||||
<BecomeMethodField fieldOptions={fieldOptions} isRequired={isRequired} />
|
||||
);
|
||||
}
|
||||
|
||||
let disabled = false;
|
||||
if (
|
||||
credentialType.kind === 'vault' &&
|
||||
location.pathname.endsWith('edit') &&
|
||||
fieldOptions.id === 'vault_id'
|
||||
) {
|
||||
disabled = true;
|
||||
}
|
||||
return (
|
||||
<CredentialPluginField
|
||||
fieldOptions={fieldOptions}
|
||||
@ -251,6 +264,7 @@ function CredentialField({ credentialType, fieldOptions }) {
|
||||
<CredentialInput
|
||||
isFieldGroupValid={isValid}
|
||||
fieldOptions={fieldOptions}
|
||||
isVaultIdDisabled={disabled}
|
||||
/>
|
||||
</CredentialPluginField>
|
||||
);
|
||||
|
||||
@ -13,6 +13,12 @@ const fieldOptions = {
|
||||
secret: true,
|
||||
};
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: () => ({
|
||||
pathname: '/credentials/3/edit',
|
||||
}),
|
||||
}));
|
||||
describe('<CredentialField />', () => {
|
||||
let wrapper;
|
||||
test('renders correctly without initial value', () => {
|
||||
@ -113,4 +119,33 @@ describe('<CredentialField />', () => {
|
||||
expect(wrapper.find('TextInput').props().value).toBe('');
|
||||
expect(wrapper.find('TextInput').props().placeholder).toBe('ENCRYPTED');
|
||||
});
|
||||
test('Should check to see if the ability to edit vault ID is disabled after creation.', () => {
|
||||
const vaultCredential = credentialTypes.find((type) => type.id === 3);
|
||||
const vaultFieldOptions = {
|
||||
id: 'vault_id',
|
||||
label: 'Vault Identifier',
|
||||
type: 'string',
|
||||
secret: true,
|
||||
};
|
||||
wrapper = mountWithContexts(
|
||||
<Formik
|
||||
initialValues={{
|
||||
passwordPrompts: {},
|
||||
inputs: {
|
||||
password: 'password',
|
||||
vault_id: 'vault_id',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{() => (
|
||||
<CredentialField
|
||||
fieldOptions={vaultFieldOptions}
|
||||
credentialType={vaultCredential}
|
||||
/>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
expect(wrapper.find('CredentialInput').props().isDisabled).toBe(true);
|
||||
expect(wrapper.find('KeyIcon').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user