From 5fde6ead42250d1afac3c554c14e762cb17ae2d0 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Fri, 7 Jul 2017 13:06:59 -0400 Subject: [PATCH] properly copy prompted vault passwords on job launch see: #6924 --- awx/api/serializers.py | 15 ++-- .../functional/api/test_job_runtime_params.py | 76 +++++++++++++++++++ 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 01cbb51485..3ef89809cc 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -3139,13 +3139,14 @@ class JobLaunchSerializer(BaseSerializer): credential = attrs.get('credential', None) # fill passwords dict with request data passwords - if credential and credential.passwords_needed: - passwords = self.context.get('passwords') - try: - for p in credential.passwords_needed: - passwords[p] = data[p] - except KeyError: - errors['passwords_needed_to_start'] = credential.passwords_needed + for cred in (credential, obj.vault_credential): + if cred and cred.passwords_needed: + passwords = self.context.get('passwords') + try: + for p in cred.passwords_needed: + passwords[p] = data[p] + except KeyError: + errors.setdefault('passwords_needed_to_start', []).extend(cred.passwords_needed) extra_vars = attrs.get('extra_vars', {}) diff --git a/awx/main/tests/functional/api/test_job_runtime_params.py b/awx/main/tests/functional/api/test_job_runtime_params.py index 1089242043..b75ad32672 100644 --- a/awx/main/tests/functional/api/test_job_runtime_params.py +++ b/awx/main/tests/functional/api/test_job_runtime_params.py @@ -1,3 +1,4 @@ +import mock import pytest import yaml @@ -331,6 +332,81 @@ def test_job_launch_JT_with_default_vault_credential(machine_credential, vault_c assert job_obj.vault_credential.pk == vault_credential.pk +@pytest.mark.django_db +def test_job_launch_fails_with_missing_vault_password(machine_credential, vault_credential, + deploy_jobtemplate, post, rando): + vault_credential.vault_password = 'ASK' + vault_credential.save() + deploy_jobtemplate.credential = machine_credential + deploy_jobtemplate.vault_credential = vault_credential + deploy_jobtemplate.execute_role.members.add(rando) + deploy_jobtemplate.save() + + response = post( + reverse('api:job_template_launch', kwargs={'pk': deploy_jobtemplate.pk}), + rando, + expect=400 + ) + assert response.data['passwords_needed_to_start'] == ['vault_password'] + + +@pytest.mark.django_db +def test_job_launch_fails_with_missing_ssh_password(machine_credential, deploy_jobtemplate, post, + rando): + machine_credential.password = 'ASK' + machine_credential.save() + deploy_jobtemplate.credential = machine_credential + deploy_jobtemplate.execute_role.members.add(rando) + deploy_jobtemplate.save() + + response = post( + reverse('api:job_template_launch', kwargs={'pk': deploy_jobtemplate.pk}), + rando, + expect=400 + ) + assert response.data['passwords_needed_to_start'] == ['ssh_password'] + + +@pytest.mark.django_db +def test_job_launch_fails_with_missing_vault_and_ssh_password(machine_credential, vault_credential, + deploy_jobtemplate, post, rando): + vault_credential.vault_password = 'ASK' + vault_credential.save() + machine_credential.password = 'ASK' + machine_credential.save() + deploy_jobtemplate.credential = machine_credential + deploy_jobtemplate.vault_credential = vault_credential + deploy_jobtemplate.execute_role.members.add(rando) + deploy_jobtemplate.save() + + response = post( + reverse('api:job_template_launch', kwargs={'pk': deploy_jobtemplate.pk}), + rando, + expect=400 + ) + assert sorted(response.data['passwords_needed_to_start']) == ['ssh_password', 'vault_password'] + + +@pytest.mark.django_db +def test_job_launch_pass_with_prompted_vault_password(machine_credential, vault_credential, + deploy_jobtemplate, post, rando): + vault_credential.vault_password = 'ASK' + vault_credential.save() + deploy_jobtemplate.credential = machine_credential + deploy_jobtemplate.vault_credential = vault_credential + deploy_jobtemplate.execute_role.members.add(rando) + deploy_jobtemplate.save() + + with mock.patch.object(Job, 'signal_start') as signal_start: + post( + reverse('api:job_template_launch', kwargs={'pk': deploy_jobtemplate.pk}), + {'vault_password': 'vault-me'}, + rando, + expect=201 + ) + signal_start.assert_called_with(vault_password='vault-me') + + @pytest.mark.django_db def test_job_launch_JT_with_extra_credentials(machine_credential, credential, net_credential, deploy_jobtemplate): deploy_jobtemplate.ask_credential_on_launch = True