2

My Puppet agent is Windows Server 2012. I am trying to grant db rights to an AD user. If i try assigning rights to an AD user that doesn't contain any space in its name, then the script works fine. Earlier, user name without space was also not working but when i added an extra slash ('abc\\s_sql'), it worked for that user. For user name with space, it's not working at all although Puppet shows it ran successfully.

[root@pe-server] cat grant_read.pp
define db::grant_read (
    $grant_read_params
) {
    $grant_read_ps = $grant_read_params[grant_read_ps]
    $grant_read_sql = $grant_read_params[grant_read_sql]
    $read_user = $grant_read_params[read_user]
    $db_name = $grant_read_params[db_name]

    utils::powershell_script { "Grant read access to user $read_user on $db_name":
        script    => $grant_read_ps,
        parameter => "$grant_read_sql $read_user $db_name",
    }
}


[root@pe-server] cat site.pp
node 'pe-agent.abc.com' {
    $grant_read_params_Support_PROD = {
        'grant_read_ps'  => 'c:/db/grant_read.ps1',
        'grant_read_sql' => 'c:/db/grant_read.sql',
        #'read_user'     => 'abc\\s_sql',
        'read_user'      => 'abc\\APP Support_PROD',
        'db_name'        => 'ABC_MASTER',
    }

    db::grant_read { "Granting read access to tom on some db":
        grant_read_params => $grant_read_params_Support_PROD
    }
}


[root@pe-server] cat powershell_script.pp
define utils::powershell_script (String $script, String $parameter = '') {
    $powershell = 'C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -NoProfile -NoLogo -NonInteractive'
    exec { "Running $script on agent with parameter $parameter":
            command => "$powershell -File $script $parameter",
            logoutput => 'on_failure',
            timeout   => 900,
    }
}

Tried several permutations and combinations both in the site.pp file argument and grant_read.pp file but nothing seems to be working.

Any idea how i can handle this?

Technext
  • 7,887
  • 9
  • 48
  • 76
  • Have you tried changing the single quotes(' ') to double quotes (" ") – Will Webb Mar 14 '17 at 13:02
  • 2
    You probably need to add nested double quotes around the parameter: `parameter => "$grant_read_sql \"$read_user\" $db_name",` – Ansgar Wiechers Mar 14 '17 at 13:49
  • @WillWebb: I tried that earlier but that didn't work. @AnsgarWiechers: Thanks a lot! It's working. :) It's really frustrating dealing with slashes. I earlier tried single quotes around `$read_user` assuming that the variable will be passed to the `utils::powershell_script` as is without interpolating here. Can you please explain or point out some resource which can be handy in understanding the behaviour of slashes in such cases? I will really appreciate if you could post the above comment as answer (and if possible, some reference link or a small explanation why double quote worked). Thanks – Technext Mar 14 '17 at 15:26

1 Answers1

2

You need to put double quotes around a parameter with spaces. Single quotes won't work here, because they're not valid quoting characters in the Windows environment that executes the PowerShell commandline. And since you can't use a single-quoted string (lest Puppet wouldn't expand the variables) you must escape the nested double quotes with backslashes (for Puppet).

Basically, this:

"$grant_read_sql \"$read_user\" $db_name"

becomes a string like this:

'c:/db/grant_read.sql "abc\APP Support_PROD" ABC_MASTER'

and finally, when inserted into the PowerShell commandline, like this:

C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -NoProfile -NoLogo -NonInteractive -File c:/db/grant_read.ps1 c:/db/grant_read.sql "abc\APP Support_PROD" ABC_MASTER

The fully expanded commandline (see above) must be in a form that would allow running it directly from CMD or the Run dialog. Meaning that if any other token (a script path for instance) had spaces in it, that token would need to be in double quotes as well.

Bottom line: you need double quotes around a parameter for the execution of the Windows commandline, and backslashes to escape the nested double quotes inside double-quoted strings for Puppet.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • Adding to what Ansgar said, I'd also recommend using the powershell module, as it has much more robust logging for powershell commands run under Puppet: https://forge.puppet.com/puppetlabs/powershell – Peter Souter Mar 15 '17 at 11:06
  • Thanks a lot for the nice and clear explanation @Ansgar! I just came across another instance today where two parameters had values with spaces and your suggestion worked. :) Thanks again! – Technext Mar 15 '17 at 14:36
  • 1
    @PeterSouter: Thanks for the suggestion. I was actually using the powershell provider earlier for all execs until i faced [this](http://stackoverflow.com/questions/42484043/capturing-output-error-when-invoking-powershell-script) issue. If there's a way to handle it, i will be happy to try it out. I'm using the second code block suggested by @Ansgar in that link. That works fine for me. However, i'm facing issue with that approach in scenarios where a script requires parameters (as shown in the above post). In such cases, i'm not sure how to apply the `exit (1 - [int]$?)` block properly. – Technext Mar 15 '17 at 14:44