Reputation: 1303
I am writing a binary cmdlet and I would like to accept a PSCredential
parameter in order to use elevated credentials.
[Parameter]
public PSCredential Credential { get; set; }
There seems to be a distinct lack of documentation for this - all I can find is how to execute PowerShell cmdlets from C#, which is not what I wish to do.
I downloaded the SimpleImpersonation
nuget package to avoid doing the Windows impersonation myself.
using (Impersonation.LogonUser("GLOBAL", "last.first", "mypassword", LogonType.Interactive))
{
foreach (ServerInfo server in Targets)
ProcessRecord();
}
When I check System.Security.Principal.WindowsIdentity.GetCurrent().Name
the user is correct, but when I execute a command (eg ServerManager.OpenRemote(computerName)
) I receive an UnauthorizedAccessException
. If I run this code from a PowerShell instance running as the desired user the cmdlet executes flawlessly.
Does anyway have any clues as to how to utilise a PSCredential
in a C# binary cmdlet?
Upvotes: 0
Views: 1909
Reputation: 1303
I'm not sure why this has so little documentation online. As I suspected I needed to use impersonation to accomplish this. There seems to be a lot of plumbing involved with this, see here.
After some more investigation there's a nice nuget package called SimpleImpersonation.
Using:
[Parameter]
public PSCredential Credential { get; set; }
I can do this:
using (Impersonation.LogonUser("GLOBAL", Credential.UserName, Credential.Password, LogonType.Interactive))
This allows me to run commands as the impersonated user. LogonUser()
takes the username and SecureString
password.
This works fine for ServiceController
calls, but ServerManager
was still throwing COM unauthorised exceptions. I managed to find this post which said to not use OpenRemote()
but to use a ctor overload. The following code works:
using (ServerManager serverManager = new ServerManager(@"\\server\c$\windows\system32\inetsrv\config\applicationHost.config"))
{
ApplicationPoolCollection appPool = serverManager.ApplicationPools;
Console.WriteLine(appPool.Count);
}
Upvotes: 2