Invoking Powershell via C# in a web application - issues with app pool identity -


i have written stuff execute powershell via c# using runspacefactory.

i loading default powershell profile this:

   runspace runspace = runspacefactory.createrunspace();    runspace.open();    string scripttext = @". .\" + scriptfilename + "; " + command;    pipeline pipeline = runspace.createpipeline(scripttext); 

command = function profile know works.

all of powershell stuff wrapped in impersonator.

for avoidance of doubt, $profile = c:\users\administrator\documents\windowspowershell\microsoft.powershell_profile.ps1

this web application running under iis 7.5

if iis app runs under 'administrator' account, works. under other account throws error:

"the term '.\microsoft.powershell_profile.ps1' not recognized name of cmdlet, function, script file, or operable program. check spelling of name, or if path included, verify path correct , try again."

as impersonating 'administrator' account assumed location correct.

some logging invoked 'get-location' reports directory should be.

out of bloody mindedness tried force with:

  system.environment.currentdirectory = dir; 

... , attempt @ invoked 'set-location'. these work, if invoke 'get-location' runspace reports same directory before (the correct one).

i thought that, perhaps, there might problem impersonation, wrote tests touch file system in ways app pool shouldn't able do. these work.

i checked this:

string contextusername = system.security.principal.windowsidentity.getcurrent().name; 

which reports correct user both when code 'wrapped' in impersonator, , when executed via app pool identity. got desperate , tried invoke:

 @"cmd /c dir" 

... (and get-childitem). both commands return:

{} 

...when running under app pool identity (regardless of impersonation), full , accurate directory listing of correct directory when app pool running 'administrator'.

i sure missing stupid , fundamental here, if give me guidance on i've made mistake in thinking (and code), great.

this kind of "well known" issue using powershell in asp.net when in impersonated context: doesn't work way people think should work.

the reason because powershell, behind covers, spins thread of work. new thread inside powershell not inherit impersonated context.

the fix isn't pretty. this msdn blog post recommends setting asp.net flow impersonation policy (so thread behind scenes gets identity):

<configuration>     <runtime>         <legacyimpersonationpolicy enabled="false"/>         <alwaysflowimpersonationpolicy enabled="true"/>     </runtime> </configuration> 

another, uglier approach (though less hacky) use winrm. can use loopback powershell session (connect localhost) powershell, , let winrm handle impersonation. requires version 3.0.0.0 of system.management.automation.

var password = "helloworld"; var ss = new securestring(); foreach (var passchar in password) {     ss.appendchar(passchar); } var pscredential = new pscredential("username", ss); var connectioninfo = new wsmanconnectioninfo(new uri("http://localhost:5985/wsman"), "http://schemas.microsoft.com/powershell/microsoft.powershell", pscredential); using (var runspace = runspacefactory.createrunspace(connectioninfo)) {     connectioninfo.enablenetworkaccess = true;     using (var powershell = powershell.create())     { 

this tacky solution because requires winrm's windows service running, , configuring winrm. winrm isn't "that works", gets job done in first option isn't suitable.

the url used in wsmanconnectioninfo localhost winrm endpoint, default listens on port 5985 in version 3, , credentials specified connection.


Comments

Popular posts from this blog

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

html - How to style widget with post count different than without post count -

url rewriting - How to redirect a http POST with urlrewritefilter -