summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Borean <jborean93@gmail.com>2020-04-16 20:24:23 +1000
committerGitHub <noreply@github.com>2020-04-16 20:24:23 +1000
commit702949e64c4eec7f40a920ea72a2f47e28ca53b3 (patch)
tree750d0b4ab2bdb1a636081b6e6837ea06a537cd5b
parent77a916e763054421b9df2994bfbb9e7e4028028c (diff)
downloadansible-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.yaml3
-rw-r--r--lib/ansible/executor/powershell/module_wrapper.ps115
-rw-r--r--lib/ansible/plugins/shell/cmd.py3
-rw-r--r--test/integration/targets/win_exec_wrapper/tasks/main.yml2
-rw-r--r--test/sanity/ignore.txt1
-rw-r--r--test/units/plugins/shell/test_cmd.py2
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):