diff --git a/devops/helpers/ssh_client.py b/devops/helpers/ssh_client.py index 751b3121..22b17027 100644 --- a/devops/helpers/ssh_client.py +++ b/devops/helpers/ssh_client.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import base64 import os import posixpath import stat @@ -214,7 +215,10 @@ class SSHClient(object): stderr = chan.makefile_stderr('rb') cmd = "%s\n" % command if self.sudo_mode: - cmd = 'sudo -S bash -c "%s"' % cmd.replace('"', '\\"') + encoded_cmd = base64.b64encode(cmd) + cmd = "sudo -S bash -c 'eval $(base64 -d <(echo \"{0}\"))'".format( + encoded_cmd + ) chan.exec_command(cmd) if stdout.channel.closed is False: stdin.write('%s\n' % self.password) diff --git a/devops/tests/helpers/test_ssh_client.py b/devops/tests/helpers/test_ssh_client.py index 1e7dfeb7..42cd9441 100644 --- a/devops/tests/helpers/test_ssh_client.py +++ b/devops/tests/helpers/test_ssh_client.py @@ -14,6 +14,7 @@ # pylint: disable=no-self-use +import base64 from contextlib import closing from os.path import basename import posixpath @@ -52,6 +53,7 @@ username = 'user' password = 'pass' private_keys = [] command = 'ls ~ ' +encoded_cmd = base64.b64encode("%s\n" % command) @mock.patch('devops.helpers.ssh_client.logger', autospec=True) @@ -340,7 +342,9 @@ class TestSSHClient(TestCase): mock.call.makefile('wb'), mock.call.makefile('rb'), mock.call.makefile_stderr('rb'), - mock.call.exec_command('sudo -S bash -c "{}\n"'.format(command)) + mock.call.exec_command( + "sudo -S bash -c '" + "eval $(base64 -d <(echo \"{0}\"))'".format(encoded_cmd)) )) self.assertIn( mock.call.debug( @@ -373,7 +377,9 @@ class TestSSHClient(TestCase): mock.call.makefile('wb'), mock.call.makefile('rb'), mock.call.makefile_stderr('rb'), - mock.call.exec_command('sudo -S bash -c "{}\n"'.format(command)) + mock.call.exec_command( + "sudo -S bash -c '" + "eval $(base64 -d <(echo \"{0}\"))'".format(encoded_cmd)) )) self.assertIn( mock.call.debug(