JFLarvoire / SysToolsLib

A library of Windows and Linux system management tools
Apache License 2.0
314 stars 93 forks source link

$isSystem Check (2nd attempt) #7

Closed nischl closed 6 years ago

nischl commented 7 years ago

Hiho,

there was still no solution für the "is the script running as a service"-problem.

as I always have to run scripts as a different user than the System Account I changed my script to another approach:

$isSystem = !([System.environment]::UserInteractive)

Have you already evaluated this approach? With all my tests it came up correctly and I am using it in production now

furt1v3ly commented 7 years ago

Based on another forum discussion elsewhere I worked around this by adding a global setting variable: $serviceUser = 'DOMAIN\SERVICEACCT'

And then in Main adding this just under $IsSystem = $isServiceUser = ($serviceUser -eq $userName)

And finally changing the first check in if ($Start) where you check $IsSystem to: if ($isSystem -or $isServiceUser) { # If running as SYSTEM, ie. invoked as a service

The mess of code needed to get the if ($Setup) section to put that user in and prompt for a password was so ugly I gave up on it and ripped out the failed attempt. Right now I just manually set the service credentials on the rare occasion when I push a new version out.

If you are wondering, Set-Service can't do it so you have dig into WMI. Google "Set-ServiceCredential" if you want to see what is involved.

omrsafetyo commented 6 years ago

I have just submitted a pull request that adds user and password as arguments.

I resolved the above issue in my environment (code not submitted entirely), with the following:

1) Get the RunAs account of the service: $RunasAccount = (Get-WmiObject win32_Service -Filter "Name='$serviceName'").StartName

Once I have the configured RunAs account for the service,

2) Add that to the IsSystem check - in my case I had an old fork, so this would need to be updated, but this is also the piece I did not submit in my pull request: $isSystem = ($userName -eq "NT AUTHORITY\SYSTEM" -or $userName -eq $RunasAccount)

This would be changed to:

$isSystem = ($identity.IsSystem -or $userName -eq $RunasAccount)

Unless I'm missing something, or not remembering correctly (it has been a while since I worked on this, I just pulled it out this morning after over a year), setting the service credentials is as simple as:

if ( $username -and $password ) {
    $securePassword = ConvertTo-SecureString $Password -AsPlainText -Force
    $Credentials = New-Object -Type System.Management.Automation.PSCredential ($User,$securePassword)
    $pss = New-Service $serviceName $exeFullName -DisplayName $serviceDisplayName -Description $ServiceDescription -StartupType Automatic -Credential $Credentials
  }
JFLarvoire commented 6 years ago

OK, thanks, I'll look at it over the week-end.

JFLarvoire commented 6 years ago

It took me a surprisingly long time to find the obvious solution: Once you allow to run the service under any account, including possibly the current user account, it is not possible anymore to rely on user account detection to distinguish if the Start and Stop commands came from the user or from the Service Control Manager. Omrsafetyo merge request forced me to think hard about an alternative. And the solution is surprisingly simple: Use different options in the PSService.exe stub, when passing on the Start and Stop commands. I called them -SCMStart and -SCMStop. That change is simple, and gives a reliable code that works in all account combinations cases. This is now implemented in commits c72ce058a192bba9381e5fd020d1edaab3740486 and f6d8894abaec80faa1edcaf74ce261402dcbeef9.

omrsafetyo commented 6 years ago

Thanks JFLavoire, I'm sorry I didn't provide that information in the first place - the account I had been using was already set up as a service account, so it wasn't an issue that I had to think about when I coded it up.

I'm quite certain I didn't run into some of the same issues described in my environment, but then, I may not have tested quite as thoroughly as you did. Good work working that out.