Help Running win_command or win_shell for IIS custom log field setting.

Greetings everyone! I am beating my head against a wall trying to get this to work, and I know I’m screwing it up but I’m about at the end of my tether trying to get this right. I’m trying to add customFields to IIS site logs, and have tried win_command and win_shell to accomplish this, and I am just not finding the right way to escape it in either module.

Environment: Amazon Linux with Ansible 2.4 - Target Hosts: Windows Server 2016

The win_command I am trying to run is this:

`

  • name: Enable X-Forwarded-For Logging
    win_command: C:\Windows\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites /+"[name=‘{{ app_url }}’].logFile.customFields.[logFieldName=‘X-Forwarded-For’,sourceName=‘X-Forwarded-For’,sourceType=‘RequestHeader’]" /commit:apphost
    `

The result I get for this is:

e[0;31mfatal: [IP_REDACTED]: FAILED! => {e[0m
e[0;31m    "changed": true, e[0m
e[0;31m    "cmd": "C:\Windows\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites /+\\"[name='APP_NAME_REDACTED'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']\\" /commit:apphost", e[0m
e[0;31m    "delta": "0:00:00.390647", e[0m
e[0;31m    "end": "2018-03-14 01:00:03.620441", e[0m
e[0;31m    "msg": "non-zero return code", e[0m
e[0;31m    "rc": 1413, e[0m
e[0;31m    "start": "2018-03-14 01:00:03.229794", e[0m
e[0;31m    "stderr": "", e[0m
e[0;31m    "stderr_lines": [], e[0m
e[0;31m    "stdout": "ERROR ( message:Unknown attribute \"\"[name='APP_NAME_REDACTED'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']\"\".  Replace with -? for help. )\r\n", e[0m
e[0;31m    "stdout_lines": [e[0m
e[0;31m        "ERROR ( message:Unknown attribute \"\"[name='APP_NAME_REDACTED'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']\"\".  Replace with -? for help. )"e[0m
e[0;31m    ]e[0m

I've tried this multiple times, with various sets of single quotes, double quotes, etc. and am bombing every time. Here is the raw command without any escaping I'm trying to run, can anyone help point me towards getting this right please?


appcmd.exe set config -section:system.applicationHost/sites /+"[name='APP_NAME_REDACTED'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']" /commit:apphost

Thanks in advance for any and all help!

Looks like you have a nice and complex command to run which makes these things really difficult but luckily you are running Ansible 2.4 where the escaping rules are now aligned to Microsoft standard https://msdn.microsoft.com/en-us/library/17w5ykft(v=vs.85).aspx. We’ve created a very basic executable that you are more than welcome to use to test how your arguments look when being passed to an application from win_command. To test it out you can run the following playbook.

`

This tests your example and it results in

ok: [SERVER2016.domain.local] => { "output.stdout_lines": [ "set", "config", "-section:system.applicationHost/sites", "/+\"[name='http://google.com'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']\"", "/commit:apphost" ] }

Once you take into account basic JSON escaping rules (\ becomes \ and " becomes "), you can see the following arguments in your example are;

Argv[0] - set
Argv[1] - config
Argv[2] - -section:system.applicationHost/sites
Argv[3] - /+“[name=‘http://google.com’].logFile.customFields.[logFieldName=‘X-Forwarded-For’,sourceName=‘X-Forwarded-For’,sourceType=‘RequestHeader’]”
Argv[4] - /commit:apphost

While this is what your raw command looks like, if when you saw raw command you mean this is what you run in cmd.exe and it works the double quotes in Argv[3] are probably what’s causing the issues. When reading the rules for command-line arguments, 2 rules that pertain to double quotes are;

  • A string surrounded by double quotation marks (“string”) is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.
  • A double quotation mark preceded by a backslash (") is interpreted as a literal double quotation mark character (").

This means that when you just have " without a preceding , the parser will interpret that as the start of a quoted argument and ignore whitespaces as an argument delimiter until another double quote is found. If you preceed the double quote with , it will use the double quote as an argument char and not start/end the whitespace escaping. This means in your example, the " char is being passed into the appcmd.exe (we can see this in the PrintArgv.exe test) as an argument whereas your raw command indicates it is just being used as a whitespace switch. I would try the following command in Ansible and see how that goes (I changed " in the complex arg to just " so that the " literal isn’t passed into the application).

`

  • win_command: C:\temp\PrintArgv.exe set config -section:system.applicationHost/sites /+“[name=‘{{ app_url }}’].logFile.customFields.[logFieldName=‘X-Forwarded-For’,sourceName=‘X-Forwarded-For’,sourceType=‘RequestHeader’]” /commit:apphost
    `

When testing that with the PrintArgv.exe test I can see the following arguments are being passed into the application

TASK [debug] ************************************************************************************************************************************************ ok: [SERVER2016.domain.local] => { "output.stdout_lines": [ "set", "config", "-section:system.applicationHost/sites", "/+[name='http://google.com'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']", "/commit:apphost" ] }

Once again, escaping the JSON escaping rules we can see the following arguments are being passed into the application;

Argv[0] - set
Argv[1] - config
Argv[2] - -section:system.applicationHost/sites
Argv[3] - /+[name=‘http://google.com’].logFile.customFields.[logFieldName=‘X-Forwarded-For’,sourceName=‘X-Forwarded-For’,sourceType=‘RequestHeader’]``
Argv[4] - /commit:apphost

Also because you don’t have any whitespace characters in Argv[3], you probably don’t even need the double quotes at all but I’ll leave that up to you for testing, it may be prudent to leave them in there depending on what the value for name is.

I honestly don’t know the rules for appcmd.exe so I don’t really know how it actually expects the argument to be but I’m just going by your raw command example and trying to predict what it is expecting.

Thanks

Jordan