Search code examples
powershellpuppetpowershell-5.0

Handling names with spaces


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?


Solution

  • 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.