mirror of
https://github.com/ansible/awx.git
synced 2026-03-19 18:07:33 -02:30
AC-672 Fixed responding to passphrase prompts for project updates, re-added tests removed in earlier update.
This commit is contained in:
@@ -27,6 +27,7 @@ from celery import Task
|
|||||||
# Django
|
# Django
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from django.utils.datastructures import SortedDict
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
@@ -152,10 +153,7 @@ class BaseTask(Task):
|
|||||||
Return a dictionary of prompt regular expressions and password lookup
|
Return a dictionary of prompt regular expressions and password lookup
|
||||||
keys.
|
keys.
|
||||||
'''
|
'''
|
||||||
return {
|
return SortedDict()
|
||||||
r'Enter passphrase for .*:': 'ssh_key_unlock',
|
|
||||||
r'Bad passphrase, try again for .*:': '',
|
|
||||||
}
|
|
||||||
|
|
||||||
def run_pexpect(self, instance, args, cwd, env, passwords,
|
def run_pexpect(self, instance, args, cwd, env, passwords,
|
||||||
output_replacements=None):
|
output_replacements=None):
|
||||||
@@ -180,6 +178,7 @@ class BaseTask(Task):
|
|||||||
expect_list.extend([pexpect.TIMEOUT, pexpect.EOF])
|
expect_list.extend([pexpect.TIMEOUT, pexpect.EOF])
|
||||||
while child.isalive():
|
while child.isalive():
|
||||||
result_id = child.expect(expect_list, timeout=pexpect_timeout)
|
result_id = child.expect(expect_list, timeout=pexpect_timeout)
|
||||||
|
#print 'pexpect result_id', result_id, expect_list[result_id], expect_passwords.get(result_id, None)
|
||||||
if result_id in expect_passwords:
|
if result_id in expect_passwords:
|
||||||
child.sendline(expect_passwords[result_id])
|
child.sendline(expect_passwords[result_id])
|
||||||
updates = {'status': 'running',
|
updates = {'status': 'running',
|
||||||
@@ -407,11 +406,11 @@ class RunJob(BaseTask):
|
|||||||
|
|
||||||
def get_password_prompts(self):
|
def get_password_prompts(self):
|
||||||
d = super(RunJob, self).get_password_prompts()
|
d = super(RunJob, self).get_password_prompts()
|
||||||
d.update({
|
d[re.compile(r'^Enter passphrase for .*:\s*?$', re.M)] = 'ssh_key_unlock'
|
||||||
r'sudo password.*:': 'sudo_password',
|
d[re.compile(r'^Bad passphrase, try again for .*:\s*?$', re.M)] = ''
|
||||||
r'SSH password:': 'password',
|
d[re.compile(r'^sudo password.*:\s*?$', re.M)] = 'sudo_password'
|
||||||
r'Password:': 'password',
|
d[re.compile(r'^SSH password:\s*?$', re.M)] = 'password'
|
||||||
})
|
d[re.compile(r'^Password:\s*?$', re.M)] = 'password'
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def pre_run_check(self, job, **kwargs):
|
def pre_run_check(self, job, **kwargs):
|
||||||
@@ -663,15 +662,14 @@ class RunProjectUpdate(BaseTask):
|
|||||||
|
|
||||||
def get_password_prompts(self):
|
def get_password_prompts(self):
|
||||||
d = super(RunProjectUpdate, self).get_password_prompts()
|
d = super(RunProjectUpdate, self).get_password_prompts()
|
||||||
d.update({
|
d[re.compile(r'^Username for.*:\s*?$', re.M)] = 'scm_username'
|
||||||
re.compile(r'^Username for.*:\s*?$', re.M): 'scm_username',
|
d[re.compile(r'^Password for.*:\s*?$', re.M)] = 'scm_password'
|
||||||
re.compile(r'^Password for.*:\s*?$', re.M): 'scm_password',
|
d[re.compile(r'^Password:\s*?$', re.M)] = 'scm_password'
|
||||||
re.compile(r'^Password:\s*?$', re.M): 'scm_password',
|
d[re.compile(r'^\S+?@\S+?\'s\s+?password:\s*?$', re.M)] = 'scm_password'
|
||||||
re.compile(r'^\S+?@\S+?\'s\s+?password:\s*?$', re.M): 'scm_password',
|
d[re.compile(r'^Enter passphrase for .*:\s*?$', re.M)] = 'scm_key_unlock'
|
||||||
re.compile(r'^Enter passphrase for .*:\s*?$', re.M): 'scm_key_unlock',
|
d[re.compile(r'^Bad passphrase, try again for .*:\s*?$', re.M)] = ''
|
||||||
# FIXME: Configure whether we should auto accept host keys?
|
# FIXME: Configure whether we should auto accept host keys?
|
||||||
re.compile(r'^Are you sure you want to continue connecting \(yes/no\)\?\s*?$', re.M): 'yes',
|
d[re.compile(r'^Are you sure you want to continue connecting \(yes/no\)\?\s*?$', re.M)] = 'yes'
|
||||||
})
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def get_idle_timeout(self):
|
def get_idle_timeout(self):
|
||||||
|
|||||||
@@ -1220,6 +1220,49 @@ class ProjectUpdatesTest(BaseTransactionTest):
|
|||||||
self.check_project_update(project2, should_fail=None)#,
|
self.check_project_update(project2, should_fail=None)#,
|
||||||
#should_error=should_error)
|
#should_error=should_error)
|
||||||
|
|
||||||
|
def test_scm_key_unlock_on_project_update(self):
|
||||||
|
scm_url = 'git@github.com:ansible/ansible.github.com.git'
|
||||||
|
project = self.create_project(
|
||||||
|
name='my git project over ssh with encrypted key',
|
||||||
|
scm_type='git',
|
||||||
|
scm_url=scm_url,
|
||||||
|
scm_key_data=TEST_SSH_KEY_DATA_LOCKED,
|
||||||
|
scm_key_unlock=TEST_SSH_KEY_DATA_UNLOCK,
|
||||||
|
)
|
||||||
|
url = reverse('api:project_update_view', args=(project.pk,))
|
||||||
|
with self.current_user(self.super_django_user):
|
||||||
|
response = self.get(url, expect=200)
|
||||||
|
self.assertTrue(response['can_update'])
|
||||||
|
with self.current_user(self.super_django_user):
|
||||||
|
response = self.post(url, {}, expect=202)
|
||||||
|
project_update = project.project_updates.order_by('-pk')[0]
|
||||||
|
self.check_project_update(project, should_fail=None,
|
||||||
|
project_update=project_update)
|
||||||
|
# Verify that we responded to ssh-agent prompt.
|
||||||
|
self.assertTrue('Identity added' in project_update.result_stdout,
|
||||||
|
project_update.result_stdout)
|
||||||
|
# Try again with a bad unlock password.
|
||||||
|
project = self.create_project(
|
||||||
|
name='my git project over ssh with encrypted key and bad pass',
|
||||||
|
scm_type='git',
|
||||||
|
scm_url=scm_url,
|
||||||
|
scm_key_data=TEST_SSH_KEY_DATA_LOCKED,
|
||||||
|
scm_key_unlock='not the right password',
|
||||||
|
)
|
||||||
|
with self.current_user(self.super_django_user):
|
||||||
|
response = self.get(url, expect=200)
|
||||||
|
self.assertTrue(response['can_update'])
|
||||||
|
with self.current_user(self.super_django_user):
|
||||||
|
response = self.post(url, {}, expect=202)
|
||||||
|
project_update = project.project_updates.order_by('-pk')[0]
|
||||||
|
self.check_project_update(project, should_fail=None,
|
||||||
|
project_update=project_update)
|
||||||
|
# Verify response to ssh-agent prompt, did not accept password.
|
||||||
|
self.assertTrue('Bad passphrase' in project_update.result_stdout,
|
||||||
|
project_update.result_stdout)
|
||||||
|
self.assertFalse('Identity added' in project_update.result_stdout,
|
||||||
|
project_update.result_stdout)
|
||||||
|
|
||||||
def create_local_git_repo(self):
|
def create_local_git_repo(self):
|
||||||
repo_dir = tempfile.mkdtemp()
|
repo_dir = tempfile.mkdtemp()
|
||||||
self._temp_project_dirs.append(repo_dir)
|
self._temp_project_dirs.append(repo_dir)
|
||||||
|
|||||||
Reference in New Issue
Block a user