Tweak validation to allow multiple vault credentials

support providing vault passwords based on id
include needed passwords in launch serializer defaults
This commit is contained in:
AlanCoding 2017-11-30 14:16:32 -05:00
parent 34a8e0a9b6
commit 5ada021a6e
No known key found for this signature in database
GPG Key ID: FD2C3C012A72926B
4 changed files with 27 additions and 13 deletions

View File

@ -3449,7 +3449,8 @@ class JobLaunchSerializer(BaseSerializer):
dict(
id=cred.id,
name=cred.name,
credential_type=cred.credential_type.pk
credential_type=cred.credential_type.pk,
passwords_needed=cred.passwords_needed
)
for cred in obj.credentials.all()
]

View File

@ -626,9 +626,9 @@ class LaunchConfigCredentialsBase(SubListAttachDetachAPIView):
if not getattr(parent, ask_field_name):
return {"msg": _("Related template is not configured to accept credentials on launch.")}
elif sub.kind != 'vault' and parent.credentials.filter(credential_type__kind=sub.kind).exists():
elif sub.unique_hash() in [cred.unique_hash() for cred in parent.credentials.all()]:
return {"msg": _("This launch configuration already provides a {credential_type} credential.".format(
credential_type=sub.kind))}
credential_type=sub.unique_hash(display=True)))}
elif sub.pk in parent.unified_job_template.credentials.values_list('pk', flat=True):
return {"msg": _("Related template already uses {credential_type} credential.".format(
credential_type=sub.name))}
@ -3061,9 +3061,9 @@ class JobTemplateCredentialsList(SubListCreateAttachDetachAPIView):
return sublist_qs
def is_valid_relation(self, parent, sub, created=False):
current_extra_types = [cred.credential_type.pk for cred in parent.credentials.all()]
if sub.credential_type.pk in current_extra_types:
return {'error': _('Cannot assign multiple %s credentials.' % sub.credential_type.name)}
if sub.unique_hash() in [cred.unique_hash() for cred in parent.credentials.all()]:
return {"msg": _("Cannot assign multiple {credential_type} credentials.".format(
credential_type=sub.unique_hash(display=True)))}
return super(JobTemplateCredentialsList, self).is_valid_relation(parent, sub, created)

View File

@ -326,9 +326,14 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
@property
def passwords_needed(self):
needed = []
for field in ('ssh_password', 'become_password', 'ssh_key_unlock', 'vault_password'):
for field in ('ssh_password', 'become_password', 'ssh_key_unlock'):
if getattr(self, 'needs_%s' % field):
needed.append(field)
if self.needs_vault_password:
if self.inputs.get('vault_id'):
needed.append('vault_password.{}'.format(self.inputs.get('vault_id')))
else:
needed.append('vault_password')
return needed
def _password_field_allows_ask(self, field):
@ -369,15 +374,23 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
field_val[k] = '$encrypted$'
return field_val
def unique_hash(self):
def unique_hash(self, display=False):
'''
Credential exclusivity is not defined solely by the related
credential type (due to vault), so this produces a hash
that can be used to evaluate exclusivity
'''
if self.kind == 'vault' and self.inputs.get('id', None):
return '{}_{}'.format(self.credential_type_id, self.inputs.get('id'))
return str(self.credential_type_id)
if display:
type_alias = self.kind
else:
type_alias = self.credential_type_id
if self.kind == 'vault' and self.inputs.get('vault_id', None):
if display:
fmt_str = '{} (id={})'
else:
fmt_str = '{}_{}'
return fmt_str.format(type_alias, self.inputs.get('vault_id'))
return str(type_alias)
@staticmethod
def unique_dict(cred_qs):

View File

@ -131,7 +131,7 @@ def test_prevent_multiple_machine_creds(get, post, job_template, admin, machine_
assert get(url, admin).data['count'] == 1
resp = post(url, _new_cred('Second Cred'), admin, expect=400)
assert 'Cannot assign multiple Machine credentials.' in resp.content
assert 'Cannot assign multiple ssh credentials.' in resp.content
@pytest.mark.django_db
@ -167,7 +167,7 @@ def test_extra_credentials_unique_by_kind(get, post, job_template, admin,
assert get(url, admin).data['count'] == 1
resp = post(url, _new_cred('Second Cred'), admin, expect=400)
assert 'Cannot assign multiple Amazon Web Services credentials.' in resp.content
assert 'Cannot assign multiple aws credentials.' in resp.content
@pytest.mark.django_db