From 3748960a1f43377ff02df4e291155c9582681047 Mon Sep 17 00:00:00 2001 From: Alex Sarafian Date: Wed, 19 Apr 2017 09:13:47 +0200 Subject: [PATCH] Manage the osuser (#28) * GH-27 * GH-27: Fixed small bug with Initialize-ISHRegistry. --- CHANGELOG.md | 17 ++- .../ISHServer/Get-ISHNormalizedCredential.ps1 | 52 +++++++ Source/Modules/ISHServer/ISHServer.12.psm1 | 6 +- Source/Modules/ISHServer/ISHServer.13.psm1 | 6 +- .../ISHServer/Initialize-ISHRegistry.ps1 | 42 ++++++ .../Initialize-ISHUserLocalProfile.ps1 | 126 +++++++++++++++++ ...HUser.ps1 => Set-ISHUserAdministrator.ps1} | 19 +-- Source/Modules/ISHServer/Set-ISHUserLocal.ps1 | 130 ++++++++++++++++++ 8 files changed, 382 insertions(+), 16 deletions(-) create mode 100644 Source/Modules/ISHServer/Get-ISHNormalizedCredential.ps1 create mode 100644 Source/Modules/ISHServer/Initialize-ISHRegistry.ps1 create mode 100644 Source/Modules/ISHServer/Initialize-ISHUserLocalProfile.ps1 rename Source/Modules/ISHServer/{Initialize-ISHUser.ps1 => Set-ISHUserAdministrator.ps1} (69%) create mode 100644 Source/Modules/ISHServer/Set-ISHUserLocal.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 014fb7f..9afe748 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,25 @@ +**1.5** + +Issues: +- GH-27: Improve management of OSUser. + +In detail: +- `Initialize-ISHUser` is **deleted** and split into `Set-ISHUserLocal`, `Set-ISHUserAdministrator`, `Initialize-ISHUserLocalProfile` and `Initialize-ISHRegistry`. + - `Set-ISHUserLocal` adds the osuser when necessary to the local user registry. When the user exists, it will update the password. + - `Set-ISHUserAdministrator` sets the osuser as the local administrator. + - `Initialize-ISHUserLocalProfile` forces the osuser to fully initialize, including the user profile directory. + - `Initialize-ISHRegistry` disables registry unload. +- `Get-ISHNormalizedCredential` normalizes the credentials so they are good with all cmdlets. This is required before using any cmdlet that accepts credentials for the osuser. + **1.4** --GH-23: New dependency to [PoshPrivilege](https://www.powershellgallery.com/packages/PoshPrivilege/) for `Grant-ISHUserLogOnAsService`. +Issues: +- GH-23: New dependency to [PoshPrivilege](https://www.powershellgallery.com/packages/PoshPrivilege/) for `Grant-ISHUserLogOnAsService`. **1.3** Issues: + - GH-20: Install-ISHWindowsFeature failes withing a Docker container **1.2** diff --git a/Source/Modules/ISHServer/Get-ISHNormalizedCredential.ps1 b/Source/Modules/ISHServer/Get-ISHNormalizedCredential.ps1 new file mode 100644 index 0000000..fe482f4 --- /dev/null +++ b/Source/Modules/ISHServer/Get-ISHNormalizedCredential.ps1 @@ -0,0 +1,52 @@ +<# +# Copyright (c) 2014 All Rights Reserved by the SDL Group. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#> + +function Get-ISHNormalizedCredential +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [pscredential]$Credentials + ) + + begin + { + } + + process + { + + if($Credentials.UserName.StartsWith(".\")) + { + Write-Warning "Credentials normalization.Replaced .\ with $env:COMPUTERNAME" + New-Object System.Management.Automation.PSCredential($Credentials.UserName.Replace(".",$env:COMPUTERNAME),$Credentials.Password) + } + elseif($Credentials.UserName.indexOf("\") -lt 0) + { + Write-Warning "Credentials normalization.Prefixed with $env:COMPUTERNAME" + New-Object System.Management.Automation.PSCredential("$env:COMPUTERNAME\$($Credentials.UserName)",$Credentials.Password) + } + else + { + $Credentials + } + } + + end + { + + } +} diff --git a/Source/Modules/ISHServer/ISHServer.12.psm1 b/Source/Modules/ISHServer/ISHServer.12.psm1 index 4d8f344..da298b4 100644 --- a/Source/Modules/ISHServer/ISHServer.12.psm1 +++ b/Source/Modules/ISHServer/ISHServer.12.psm1 @@ -22,6 +22,7 @@ $exportNames=@( "Get-ISHServerFolderPath" "Grant-ISHUserLogOnAsService" "Get-ISHCOMPlus" + "Get-ISHNormalizedCredential" #endregion #region Ports @@ -39,7 +40,10 @@ $exportNames=@( "Get-ISHPrerequisites.ISH12" "Initialize-ISHLocale" "Initialize-ISHIIS" - "Initialize-ISHUser" + "Initialize-ISHUserLocalProfile" + "Set-ISHUserLocal" + "Set-ISHUserAdministrator" + "Initialize-ISHRegistry" "Initialize-ISHMSDTCSettings" "Initialize-ISHMSDTCTransactionTimeout" #endregion diff --git a/Source/Modules/ISHServer/ISHServer.13.psm1 b/Source/Modules/ISHServer/ISHServer.13.psm1 index 38c97a2..977a9fe 100644 --- a/Source/Modules/ISHServer/ISHServer.13.psm1 +++ b/Source/Modules/ISHServer/ISHServer.13.psm1 @@ -22,6 +22,7 @@ $exportNames=@( "Get-ISHServerFolderPath" "Grant-ISHUserLogOnAsService" "Get-ISHCOMPlus" + "Get-ISHNormalizedCredential" #endregion #region Ports @@ -39,7 +40,10 @@ $exportNames=@( "Get-ISHPrerequisites.ISH13" "Initialize-ISHLocale" "Initialize-ISHIIS" - "Initialize-ISHUser" + "Initialize-ISHUserLocalProfile" + "Set-ISHUserLocal" + "Set-ISHUserAdministrator" + "Initialize-ISHRegistry" #endregion #region Install diff --git a/Source/Modules/ISHServer/Initialize-ISHRegistry.ps1 b/Source/Modules/ISHServer/Initialize-ISHRegistry.ps1 new file mode 100644 index 0000000..2c4d181 --- /dev/null +++ b/Source/Modules/ISHServer/Initialize-ISHRegistry.ps1 @@ -0,0 +1,42 @@ +<# +# Copyright (c) 2014 All Rights Reserved by the SDL Group. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#> + + +function Initialize-ISHRegistry +{ + [CmdletBinding()] + param ( + ) + + begin + { + . $PSScriptRoot\Private\Test-RunningAsElevated.ps1 + Test-RunningAsElevated -StopCallerPSCmdlet $PSCmdlet + } + + process + { + # http://docs.sdl.com/LiveContent/content/en-US/SDL%20Knowledge%20Center%20full%20documentation-v2/GUID-70BAEF73-D2B4-488B-8F71-505DB8ACB244 + Write-Debug "Disabling Force Unload of registry" + Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name DisableForceUnload -Value $true + Write-Verbose "Disabled Force Unload of registry" + } + + end + { + + } +} diff --git a/Source/Modules/ISHServer/Initialize-ISHUserLocalProfile.ps1 b/Source/Modules/ISHServer/Initialize-ISHUserLocalProfile.ps1 new file mode 100644 index 0000000..b68c7ed --- /dev/null +++ b/Source/Modules/ISHServer/Initialize-ISHUserLocalProfile.ps1 @@ -0,0 +1,126 @@ +<# +# Copyright (c) 2014 All Rights Reserved by the SDL Group. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#> + +#requires -Module PoshPrivilege + +function Initialize-ISHUserLocalProfile +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [pscredential]$OSUserCredentials + ) + + begin + { + . $PSScriptRoot\Private\Test-RunningAsElevated.ps1 + Test-RunningAsElevated -StopCallerPSCmdlet $PSCmdlet + } + + process + { + $OSUserCredentials=Get-ISHNormalizedCredential -Credentials $OSUserCredentials + $osUserName=$OSUserCredentials.UserName + $osUserPassword=$OsUserCredentials.GetNetworkCredential().Password + Write-Verbose "Normalized Credentials" + Write-Debug "osUserName=$osUserName" + + $arguments=@( + "-Command" + "' { } '" + ) + $powerShellPath=& C:\Windows\System32\where.exe powershell + + Write-Debug "powerShellPath=$powerShellPath" + + # Check if execution is within a remoting session + if(Test-Path -Path Variable:\PSSenderInfo) + { + $useScheduledTask=$true + } + # Check if execution is invoked by the Windows SYSTEM user. Typically for AWS CodeDeploy and UserData execution + elseif($env:USERNAME -eq "NT AUTHORITY\SYSTEM") + { + $useScheduledTask=$true + } + # Check if execution is invoked by the Windows SYSTEM user. Typically for AWS CodeDeploy and UserData execution + elseif($env:USERNAME -eq "$($env:computername)`$") + { + $useScheduledTask=$true + } + else + { + $useScheduledTask=$false + } + Write-Debug "useScheduledTask=$useScheduledTask" + + # When the script is executing within a remoting session or from the Windows System user, we need to create and destroy a scheduled task that will force the user's profile initialization. + if($useScheduledTask) + { + Write-Verbose "Using a scheduled task to initialize $osUserName" + + Write-Debug "Added SeBatchLogonRight privilege to $osUserName" + Add-Privilege -AccountName $osUserName -Privilege SeBatchLogonRight + Write-Verbose "Added SeBatchLogonRight privilege to $osUserName" + + $taskName="Initialize $osUserName user profile" + $argumentList=$arguments -join ' ' + $command="Start-Process -FilePath powershell -LoadUserProfile -Wait -ArgumentList ""$argumentList""" + $action = New-ScheduledTaskAction -Execute $powerShellPath -Argument "-Command '& { $command }'" + Write-Debug "taskName=$taskName" + Write-Debug "command=$command" + Write-Debug "argumentList=$argumentList" + Write-Debug "Register and starting Scheduled Task $taskName" + $task = Register-ScheduledTask -TaskName $taskName -Action $action -User $osUserName -Password $osUserPassword + Write-Verbose "Scheduled Task $taskName registered" + + Start-ScheduledTask -InputObject $task + Write-Verbose "Scheduled Task $taskName started" + + $state=($task|Get-ScheduledTask).State + Write-Debug "Scheduled Task $taskName state is $state." + while($state -eq "Ready") + { + Start-Sleep -Milliseconds 500 + Write-Debug "Waiting for Scheduled Task $taskName" + + $state=($task|Get-ScheduledTask).State + Write-Debug "Scheduled Task $taskName state is $state." + } + Write-Verbose "Scheduled Task $taskName removed" + + Write-Debug "Removing Scheduled Task $taskName" + $task|Unregister-ScheduledTask -Confirm:$false + Write-Verbose "Scheduled Task $taskName removed" + + Write-Debug "Removing SeBatchLogonRight privilege from $osUserName" + Remove-Privilege -AccountName $osUserName -Privilege SeBatchLogonRight + Write-Verbose "Removed SeBatchLogonRight privilege from $osUserName" + } + else + { + Write-Verbose "Using a normal process to initialize $osUserName" + Write-Debug "Starting process" + Start-Process -FilePath $powerShellPath -ArgumentList $arguments -Credential $OsUserCredentials -LoadUserProfile -NoNewWindow -Wait + Write-Verbose "Finished process" + } + } + + end + { + + } +} diff --git a/Source/Modules/ISHServer/Initialize-ISHUser.ps1 b/Source/Modules/ISHServer/Set-ISHUserAdministrator.ps1 similarity index 69% rename from Source/Modules/ISHServer/Initialize-ISHUser.ps1 rename to Source/Modules/ISHServer/Set-ISHUserAdministrator.ps1 index 517fdec..a5eb273 100644 --- a/Source/Modules/ISHServer/Initialize-ISHUser.ps1 +++ b/Source/Modules/ISHServer/Set-ISHUserAdministrator.ps1 @@ -14,7 +14,8 @@ # limitations under the License. #> -function Initialize-ISHUser + +function Set-ISHUserAdministrator { [CmdletBinding()] param ( @@ -38,13 +39,15 @@ function Initialize-ISHUser if(Get-Module "Microsoft.PowerShell.LocalAccounts" -ListAvailable) { # https://technet.microsoft.com/en-us/library/mt651690.aspx - if(-not (Get-LocalGroupMember -Name Administrators -Member $OSUser -ErrorAction SilentlyContinue)) + if(-not (Get-LocalGroupMember -Name Administrators |Where-Object -Property Name -EQ $OSUser)) { Add-LocalGroupMember -Group "Administrators" -Member $OSUser } + Write-Verbose "Added $OSUser to Administrators" } else { + Write-Warning "Using net.exe commands because Microsoft.PowerShell.LocalAccounts module is not available" if((& net localgroup Administrators) -notcontains $OSUser) { $netCmdArgs=@( @@ -55,19 +58,9 @@ function Initialize-ISHUser ) & net $netCmdArgs } + Write-Verbose "Added $OSUser to Administrators" } - Write-Verbose "Added $OSUser to Administrators" - - # Grant Log on as Service to the osuser - Write-Debug "Granting ServiceLogonRight to $OSUser" - Grant-ISHUserLogOnAsService -User $OSUser - Write-Verbose "Granted ServiceLogonRight to $OSUser" - - # http://docs.sdl.com/LiveContent/content/en-US/SDL%20Knowledge%20Center%20full%20documentation-v2/GUID-70BAEF73-D2B4-488B-8F71-505DB8ACB244 - Write-Debug "Disabling Force Unload of registry" - Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name DisableForceUnload -Value $true - Write-Verbose "Disabled Force Unload of registry" } end diff --git a/Source/Modules/ISHServer/Set-ISHUserLocal.ps1 b/Source/Modules/ISHServer/Set-ISHUserLocal.ps1 new file mode 100644 index 0000000..66a987f --- /dev/null +++ b/Source/Modules/ISHServer/Set-ISHUserLocal.ps1 @@ -0,0 +1,130 @@ +<# +# Copyright (c) 2014 All Rights Reserved by the SDL Group. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#> + + +function Set-ISHUserLocal +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [pscredential]$OSUserCredentials + ) + + begin + { + . $PSScriptRoot\Private\Test-RunningAsElevated.ps1 + Test-RunningAsElevated -StopCallerPSCmdlet $PSCmdlet + } + + process + { + $osUserName=$OSUserCredentials.UserName + $osUserPassword=$OsUserCredentials.GetNetworkCredential().Password + $localUserNameToAdd=$osUserName.Substring($osUserName.IndexOf('\')+1) + + Write-Verbose "Normalized Credentials" + Write-Debug "osUserName=$osUserName" + + if($OsUserCredentials.UserName.StartsWith("$($env:computername)\")) + { + $overwriteLocalUser=$true + } + elseif($OsUserCredentials.UserName.StartsWith(".\")) + { + $overwriteLocalUser=$true + } + elseif($OsUserCredentials.UserName.indexOf("\") -lt 0) + { + $overwriteLocalUser=$true + } + else + { + $overwriteLocalUser=$false + } + + Write-Debug "overwriteLocalUser=$overwriteLocalUser" + + if($overwriteLocalUser) + { + $localUserName=$osUserName.Substring($osUserName.IndexOf('\')+1) + Write-Debug "localUserNameToAdd=$localUserName" + + if(Get-Module Microsoft.PowerShell.LocalAccounts -ListAvailable) + { + if(Get-LocalUser -Name $localUserName -ErrorAction SilentlyContinue) + { + Set-LocalUser -Name $localUserName -Password $OsUserCredentials.Password -AccountNeverExpires + Write-Verbose "Updated $localUserName" + } + else + { + New-LocalUser -Name $localUserName -Password $OsUserCredentials.Password -AccountNeverExpires -PasswordNeverExpires + Write-Verbose "Created $localUserName" + } + } + else + { + Write-Warning "Using net.exe commands because Microsoft.PowerShell.LocalAccounts module is not available" + + Write-Debug "Querying local users for $localUserName" + $netUserOutput=& net user + $lineHasUsers=$false + $existingUsers=@() + for($i=0;$i -lt $netUserOutput.Count;$i++) + { + if($netUserOutput[$i] -eq "The command completed successfully.") + { + $lineHasUsers=$false + } + if($lineHasUsers) + { + $existingUsers+=$netUserOutput[$i].Split(' ')|Where-Object {$_ -ne ""} + } + if($netUserOutput[$i].StartsWith("---------")) + { + $lineHasUsers=$true + } + } + + if($existingUsers -contains $localUserName) + { + & NET USER $localUserName $osUserPassword + Write-Verbose "Updated $localUserName" + } + else + { + & NET USER $localUserName $osUserPassword /ADD + $user = [adsi]"WinNT://$env:computername/$localUserName" + $user.UserFlags.value = $user.UserFlags.value -bor 0x10000 + $user.CommitChanges() + + Write-Verbose "Created $localUserName" + } + + } + } + + # Grant Log on as Service to the osuser + Write-Debug "Granting ServiceLogonRight to $OSUser" + Grant-ISHUserLogOnAsService -User $osUserName + Write-Verbose "Granted ServiceLogonRight to $OSUser" + } + + end + { + + } +}