From d42ea31f75a1735b0e12cc435bb4feec580dbd9b Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Thu, 20 Jul 2017 12:21:42 -0400 Subject: [PATCH] use a named pipe for isolated secret passthrough (not stdin) it's not unusual for the secret data we pass into the `run_isolated.yml` playbook to be quite long, namely because it can contain RSA key data; by passing this value into the ansible-playbook process using `vars_prompt`, we're limited by pexpect's tty line limit (which looks like it caps out around 4k). Because of this, large payloads are being truncated and causing job run failures. this changes the implementation to use a named pipe instead, which doesn't have the same limitation see: #7183 --- awx/main/isolated/isolated_manager.py | 15 ++++++++++----- awx/main/tests/unit/isolated/test_expect.py | 3 ++- awx/playbooks/run_isolated.yml | 6 ++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/awx/main/isolated/isolated_manager.py b/awx/main/isolated/isolated_manager.py index 06278fb049..dfdbed34d1 100644 --- a/awx/main/isolated/isolated_manager.py +++ b/awx/main/isolated/isolated_manager.py @@ -4,7 +4,6 @@ import codecs import StringIO import json import os -import re import shutil import stat import tempfile @@ -150,6 +149,13 @@ class IsolatedManager(object): secrets['ssh_key_data'] = buff.getvalue() os.remove(self.ssh_key_path) + # write the entire secret payload to a named pipe + # the run_isolated.yml playbook will use a lookup to read this data + # into a variable, and will replicate the data into a named pipe on the + # isolated instance + secrets_path = os.path.join(self.private_data_dir, 'env') + run.open_fifo_write(secrets_path, base64.b64encode(json.dumps(secrets))) + self.build_isolated_job_data() extra_vars = { @@ -172,9 +178,6 @@ class IsolatedManager(object): logger.debug('Starting job on isolated host with `run_isolated.yml` playbook.') status, rc = IsolatedManager.run_pexpect( args, self.awx_playbook_path(), self.management_env, buff, - expect_passwords={ - re.compile(r'Secret:\s*?$', re.M): base64.b64encode(json.dumps(secrets)) - }, idle_timeout=self.idle_timeout, job_timeout=settings.AWX_ISOLATED_LAUNCH_TIMEOUT, pexpect_timeout=5 @@ -216,7 +219,9 @@ class IsolatedManager(object): '- /project/.svn', '- /project/.hg', # don't rsync job events that are in the process of being written - '- /artifacts/job_events/*-partial.json.tmp' + '- /artifacts/job_events/*-partial.json.tmp', + # rsync can't copy named pipe data - we're replicating this manually ourselves in the playbook + '- /env' ] for filename, data in ( diff --git a/awx/main/tests/unit/isolated/test_expect.py b/awx/main/tests/unit/isolated/test_expect.py index c44ba681f3..5b8c4aac27 100644 --- a/awx/main/tests/unit/isolated/test_expect.py +++ b/awx/main/tests/unit/isolated/test_expect.py @@ -163,7 +163,8 @@ def test_build_isolated_job_data(private_data_dir, rsa_key): '- /project/.git', '- /project/.svn', '- /project/.hg', - '- /artifacts/job_events/*-partial.json.tmp' + '- /artifacts/job_events/*-partial.json.tmp', + '- /env' ]) diff --git a/awx/playbooks/run_isolated.yml b/awx/playbooks/run_isolated.yml index 1dbd1e6561..5233f63dd1 100644 --- a/awx/playbooks/run_isolated.yml +++ b/awx/playbooks/run_isolated.yml @@ -8,10 +8,8 @@ - name: Prepare data, dispatch job in isolated environment. hosts: all gather_facts: false - vars_prompt: - - prompt: "Secret" - name: "secret" - private: yes + vars: + secret: "{{ lookup('pipe', 'cat ' + src + '/env') }}" tasks: