diff options
author | Jordan Borean <jborean93@gmail.com> | 2020-04-16 20:24:23 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-16 20:24:23 +1000 |
commit | 702949e64c4eec7f40a920ea72a2f47e28ca53b3 (patch) | |
tree | 750d0b4ab2bdb1a636081b6e6837ea06a537cd5b | |
parent | 77a916e763054421b9df2994bfbb9e7e4028028c (diff) | |
download | ansible-702949e64c4eec7f40a920ea72a2f47e28ca53b3.tar.gz |
windows - fix up env var quoting for unicode single quotes (#68968)
* windows - fix up env var quoting for unicode single quotes
* Add sanity ignore check for smart quotes
-rw-r--r-- | changelogs/fragments/win_env_var.yaml | 3 | ||||
-rw-r--r-- | lib/ansible/executor/powershell/module_wrapper.ps1 | 15 | ||||
-rw-r--r-- | lib/ansible/plugins/shell/cmd.py | 3 | ||||
-rw-r--r-- | test/integration/targets/win_exec_wrapper/tasks/main.yml | 2 | ||||
-rw-r--r-- | test/sanity/ignore.txt | 1 | ||||
-rw-r--r-- | test/units/plugins/shell/test_cmd.py | 2 |
6 files changed, 17 insertions, 9 deletions
diff --git a/changelogs/fragments/win_env_var.yaml b/changelogs/fragments/win_env_var.yaml new file mode 100644 index 0000000000..5375b76540 --- /dev/null +++ b/changelogs/fragments/win_env_var.yaml @@ -0,0 +1,3 @@ +bugfixes: +- windows environment - Support env vars that contain the unicode variant of single quotes - https://github.com/ansible-collections/ansible.windows/issues/45 +- shell cmd - Properly escape double quotes in the command argument diff --git a/lib/ansible/executor/powershell/module_wrapper.ps1 b/lib/ansible/executor/powershell/module_wrapper.ps1 index b457515318..68e425ff76 100644 --- a/lib/ansible/executor/powershell/module_wrapper.ps1 +++ b/lib/ansible/executor/powershell/module_wrapper.ps1 @@ -67,13 +67,14 @@ foreach ($variable in $Variables) { # set the environment vars if ($Environment) { - foreach ($env_kv in $Environment.GetEnumerator()) { - Write-AnsibleLog "INFO - setting environment '$($env_kv.Key)' for $ModuleName" "module_wrapper" - $env_key = $env_kv.Key.Replace("'", "''") - $env_value = $env_kv.Value.ToString().Replace("'", "''") - $escaped_env_set = "[System.Environment]::SetEnvironmentVariable('$env_key', '$env_value')" - $ps.AddScript($escaped_env_set).AddStatement() > $null - } + # Escaping quotes can be problematic, instead just pass the string to the runspace and set it directly. + Write-AnsibleLog "INFO - setting environment vars for $ModuleName" "module_wrapper" + $ps.Runspace.SessionStateProxy.SetVariable("_AnsibleEnvironment", $Environment) + $ps.AddScript(@' +foreach ($env_kv in $_AnsibleEnvironment.GetEnumerator()) { + [System.Environment]::SetEnvironmentVariable($env_kv.Key, $env_kv.Value) +} +'@).AddStatement() > $null } # import the PS modules diff --git a/lib/ansible/plugins/shell/cmd.py b/lib/ansible/plugins/shell/cmd.py index e475e8ee39..d83aa11515 100644 --- a/lib/ansible/plugins/shell/cmd.py +++ b/lib/ansible/plugins/shell/cmd.py @@ -52,6 +52,7 @@ class ShellModule(PSShellModule): # https://stackoverflow.com/questions/3411771/multiple-character-replace-with-python for c in '^()%!"<>&|': # '^' must be the first char that we scan and replace if c in s: - s = s.replace(c, "^" + c) + # I can't find any docs that explicitly say this but to escape ", it needs to be prefixed with \^. + s = s.replace(c, ("\\^" if c == '"' else "^") + c) return '^"' + s + '^"' diff --git a/test/integration/targets/win_exec_wrapper/tasks/main.yml b/test/integration/targets/win_exec_wrapper/tasks/main.yml index 9679918a45..8fc54f7ca8 100644 --- a/test/integration/targets/win_exec_wrapper/tasks/main.yml +++ b/test/integration/targets/win_exec_wrapper/tasks/main.yml @@ -164,6 +164,7 @@ single_quote: "single ' quote" hyphen-var: abc@123 '_-(){}[]<>*+-/\?"''!@#$%^&|;:i,.`~0': '_-(){}[]<>*+-/\?"''!@#$%^&|;:i,.`~0' + '‘key': 'value‚' register: environment_block - name: assert environment block for task @@ -177,6 +178,7 @@ - '"hyphen-var=abc@123" in environment_block.stdout_lines' # yaml escaping rules - (\\ == \), (\" == "), ('' == ') - '"_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0=_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0" in environment_block.stdout_lines' + - '"‘key=value‚" in environment_block.stdout_lines' - name: test out become requires without become_user set test_all_options: diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index c46acfbfb4..9cc6f0400a 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -347,6 +347,7 @@ test/integration/targets/wait_for/files/testserver.py metaclass-boilerplate test/integration/targets/want_json_modules_posix/library/helloworld.py future-import-boilerplate test/integration/targets/want_json_modules_posix/library/helloworld.py metaclass-boilerplate test/integration/targets/win_exec_wrapper/library/test_fail.ps1 pslint:PSCustomUseLiteralPath +test/integration/targets/win_exec_wrapper/tasks/main.yml no-smart-quotes # We are explicitly testing smart quote support for env vars test/integration/targets/win_module_utils/library/legacy_only_new_way_win_line_ending.ps1 line-endings # Explicitly tests that we still work with Windows line endings test/integration/targets/win_module_utils/library/legacy_only_old_way_win_line_ending.ps1 line-endings # Explicitly tests that we still work with Windows line endings test/integration/targets/win_script/files/test_script.ps1 pslint:PSAvoidUsingWriteHost # Keep diff --git a/test/units/plugins/shell/test_cmd.py b/test/units/plugins/shell/test_cmd.py index 69b0de1248..670b80ab30 100644 --- a/test/units/plugins/shell/test_cmd.py +++ b/test/units/plugins/shell/test_cmd.py @@ -7,7 +7,7 @@ from ansible.plugins.shell.cmd import ShellModule ['arg1', 'arg1'], [None, '""'], ['arg1 and 2', '^"arg1 and 2^"'], - ['malicious argument\\"&whoami', '^"malicious argument\\^"^&whoami^"'], + ['malicious argument\\"&whoami', '^"malicious argument\\\\^"^&whoami^"'], ['C:\\temp\\some ^%file% > nul', '^"C:\\temp\\some ^^^%file^% ^> nul^"'] ]) def test_quote_args(s, expected): |