lib/TMD.Registration.ps1
Function Register-TMDPSSessionConfiguration { <# .SYNOPSIS This function creates and configures a 'TMD' PSSessionConfiguration using the desired default settings to use the TMD client .NOTES Name: Register-TMDPSSessionConfiguration Author: TransitionManager Version: 1.0 DateCreated: 2021-04-05 .EXAMPLE Register-TMDPSSessionConfiguration .LINK https://support.transitionmanager.net #> [CmdletBinding()] param( [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0 )] [String] $Name = 'TMD' ) BEGIN { ## Define the Session Configuration Settings $SessionConfiguration = @{ # Version number of the schema used for this document SchemaVersion = '2.0.0.0' # ID used to uniquely identify this document GUID = '3a310522-717a-4982-97e2-0c2cda1deaf8' # Author of this document Author = 'TransitionManager' # Description of the functionality provided by these settings Description = 'TMD Powershell endpoint' # Session type defaults to apply for this session configuration. Can be 'RestrictedRemoteServer' (recommended), 'Empty', or 'Default' SessionType = 'Default' LanguageMode = 'FullLanguage' ExecutionPolicy = 'Unrestricted' ModulesToImport = @{ 'ModuleName' = 'TMD.Common' 'ModuleVersion' = '1.0.0.0' } } ## Write the Session Configuration File $PsscFilePath = Join-Path $ENV:TEMP 'TMDSessionConfig.pssc' New-PSSessionConfigurationFile @SessionConfiguration -Path $PsscFilePath } PROCESS { ## Enabling PSRemoting for Version 6. if ((Get-PSSessionConfiguration).Count -eq 0) { Write-Verbose "Enabling PS Remoting" Enable-PSRemoting -Force -SkipNetworkProfileCheck -Confirm:$False } ## Unregister the Existing TMD Session Unregister-TMDPSSessionConfiguration -Name $Name ## Create Session Transport Option Defaults $CreateSessionTransportOptions = @{ MaxIdleTimeoutSec = 60 IdleTimeoutSec = 60 OutputBufferingMode = 'Drop' } $SessionTransportOptions = New-PSTransportOption @CreateSessionTransportOptions ## Register a PowerShell Core handler (TMD) $SessionConfigSettings = @{ Name = $Name Path = $PsscFilePath AccessMode = 'Remote' Force = $true TransportOption = $SessionTransportOptions UseSharedProcess = $false } Register-PSSessionConfiguration @SessionConfigSettings | Out-Null ## Add User's account to the allowed access list Add-PoShEndpointAccess -EndpointName $Name -SamAccountName $env:username } END { ## Remove the Temporary Pssc File Remove-Item $PsscFilePath -Force | Out-Null } } Function Unregister-TMDPSSessionConfiguration { <# .SYNOPSIS This function Removes a 'TMD' PSSessionConfiguration .NOTES Name: Unregister-TMDPSSessionConfiguration Author: TransitionManager Version: 1.0 DateCreated: 2021-04-05 .EXAMPLE Unregister-TMDPSSessionConfiguration .LINK https://support.transitionmanager.net #> [CmdletBinding()] param( [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0 )] [String] $Name = 'TMD' ) BEGIN { ## Remove an existing TMD Session Endpoints Get-PSSessionConfiguration $Name -ErrorAction SilentlyContinue | Unregister-PSSessionConfiguration Start-Sleep -Seconds 1 } END { } } Function Test-TMDPSSessionConfiguration { <# .SYNOPSIS Test the existence and configuration of the TMD PsSession Configuration .NOTES Name: Test-TMDPSSessionConfiguration Author: TransitionManager Version: 1.0 DateCreated: 2021-04-05 .EXAMPLE Test-TMDPSSessionConfiguration .LINK https://support.transitionmanager.net #> [CmdletBinding()] param( [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0 )] [String] $Name = 'TMD' ) Begin { } Process { ## Check Windows Configuration if ($IsWindows) { ## Define a Variable Stating if this user is an admin or not $IsAdmin = Test-IsAdmin ## Check to see if WinRM is running $WinRMServiceStatus = Get-Service -Name 'WinRM' | Select-Object -ExpandProperty 'Status' if($WinRMServiceStatus -ne 'Running') { ## If The user is an admin, start the WinRM Service if($IsAdmin) { ## Configure WinRM, which will enable it and start it. Or just start it. Enable-PSRemoting -Force -SkipNetworkProfileCheck -Confirm:$False -Verbose } } ## ## Check the user's registry key to ensure they have a configuration ## Write-Host 'PSSessionManager||Status||Checking TMD User Configuration' $UserRegKey = Get-ItemProperty -Path "HKCU:\Software\TransitionManager" -ErrorAction SilentlyContinue ## Ensure the Key exists if (-Not $UserRegKey) { ## Create the Registry Key first New-Item -Path 'HKCU:\Software' -Name 'TransitionManager' | Out-Null ## Create a user default TMD_Files folder path $TMDFilesFolderPath = Join-Path $ENV:USERPROFILE 'TMD_Files' ## Create the Registry Settings for TMD $RegValues = @{ Company = 'TransitionManager' TmdPsRoot = 'C:\Program Files\TransitionManager\tmconsole\resources\app\integrations\PowerShell' SessionManagerInstanceId = '68cc4602-eefd-43bf-8547-790cf8ae7a84' UserFilesRoot = $TMDFilesFolderPath DebugFolderPath = Join-Path $TMDFilesFolderPath 'debug' } $RegValues.Keys | ForEach-Object { Set-ItemProperty -Path "HKCU:\Software\TransitionManager" -Name $_ -Value $RegValues[$_] } } else { $TMDFilesFolderPath = Get-ItemPropertyValue -Path "HKCU:\Software\TransitionManager" -Name UserFilesRoot } ## ## Check for the required File Paths ## ## Create appropriate file paths for the TMD_Files folder (Per user, defaults to the user's environment home folder) $TMDFilesFolders = @( 'Input', 'Output', 'Credentials', 'Debug', 'Queue', 'Reference Designs' 'Config' ) ## Create each folder foreach ($Folder in $TMDFilesFolders) { Test-FolderPath -FolderPath (Join-Path $TMDFilesFolderPath $Folder) } ## ## Check for the TMD PowerShell Session Endpoint ## ## Only an Administrator can check on the TMD Endpoint Configuration if ($IsAdmin) { try { ## Get the TMD SessionConfiguration Write-Host 'PSSessionManager||Status||Checking TMD PowerShell Endpoint' $TMDEndpoint = Get-PSSessionConfiguration -Name 'TMD' -ErrorAction SilentlyContinue if (-Not $TMDEndpoint) { ## Run the TMD PSSessionConfiguration Registration Write-Host 'PSSessionManager||Status||Registering TMD PowerShell Endpoint' Register-TMDPSSessionConfiguration Write-Host 'PSSessionManager||Status||Registration Complete' } } catch { Throw $_ } } } ## Check Mac OS Configuration if ($IsMacOS) { if ($OutputVerbose) { Write-Host "Checking Mac Configuration" } } } End { } } function Add-PoShEndpointAccess { <# .Synopsis Adds a group or user to a PowerShell (WinRM) endpoint to allow remote management. .DESCRIPTION This function will edit the SDDL of a PowerShell (WinRM) endpoint to allow remote management for the specified account/group. If you run this against a remote computer, CredSSP needs to be enabled and you need to restart the WinRM-service manually afterwards (this function uses WinRM to connect to the remote machine, which is why it will not restart the service itself). .PARAMETER SamAccountName The SamAccount name of the user or group that you want to give access to. Could also be in the form domain\SamAccountName, for example contoso\Administrator. .PARAMETER ComputerName Specifies the computer on which the command runs. The default is the local computer. .PARAMETER EndpointName Specifies then name of the WinRM endpoint you want to configure, the default is Microsoft.PowerShell. .EXAMPLE Add-PoShEndpointAccess -SamAccountName "contoso\PoShUsers" -ComputerName MyPoShEndpoint.contoso.com #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] $SamAccountName, [Parameter(Mandatory = $false)] $ComputerName = '.', [Parameter(Mandatory = $false)] $EndpointName = 'Microsoft.PowerShell' ) Begin { } Process { if ($ComputerName -eq '.' -OR $ComputerName -eq "$($env:COMPUTERNAME)") { $IdentityObject = New-Object Security.Principal.NTAccount $SamAccountName try { $sid = $IdentityObject.Translate([Security.Principal.SecurityIdentifier]).Value } catch { throw "Failed to translate $SamAccountName to a valid SID." } try { $PSSConfig = Get-PSSessionConfiguration -Name $EndpointName -ErrorAction Stop } catch { if ($_.Tostring() -like '*access is denied*') { throw 'You need to have Admin-access to run this command!' } } $existingSDDL = $PSSConfig.SecurityDescriptorSDDL $isContainer = $false $isDS = $false $SecurityDescriptor = New-Object -TypeName Security.AccessControl.CommonSecurityDescriptor -ArgumentList $isContainer, $isDS, $existingSDDL $accessType = 'Allow' $accessMask = 268435456 $inheritanceFlags = 'none' $propagationFlags = 'none' $SecurityDescriptor.DiscretionaryAcl.AddAccess($accessType, $sid, $accessMask, $inheritanceFlags, $propagationFlags) $null = Set-PSSessionConfiguration -Name $EndpointName -SecurityDescriptorSddl ($SecurityDescriptor.GetSddlForm('All')) -Confirm:$false -Force } else { Invoke-Command -ArgumentList $SamAccountName, $EndpointName -ScriptBlock { $IdentityObject = New-Object Security.Principal.NTAccount $args[0] $EndpointName = $args[1] try { $sid = $IdentityObject.Translate([Security.Principal.SecurityIdentifier]).Value } catch { throw "Failed to translate $($args[0]) to a valid SID." } try { $PSSConfig = Get-PSSessionConfiguration -Name $EndpointName -ErrorAction Stop } catch { if ($_.Tostring() -like '*access is denied*') { throw 'You need to have Admin-access and enable CredSSP to run this command remotely!' } } $existingSDDL = $PSSConfig.SecurityDescriptorSDDL $isContainer = $false $isDS = $false $SecurityDescriptor = New-Object -TypeName Security.AccessControl.CommonSecurityDescriptor -ArgumentList $isContainer, $isDS, $existingSDDL $accessType = 'Allow' $accessMask = 268435456 $inheritanceFlags = 'none' $propagationFlags = 'none' $SecurityDescriptor.DiscretionaryAcl.AddAccess($accessType, $sid, $accessMask, $inheritanceFlags, $propagationFlags) $null = Set-PSSessionConfiguration -Name $EndpointName -SecurityDescriptorSddl ($SecurityDescriptor.GetSddlForm('All')) -Confirm:$false -Force -NoServiceRestart } -ComputerName $ComputerName } } End { } } |