Boe wrote a great series of articles on constrained endpoints as a guest on the Hey Scripting Guy blog which inspired me.
I decided to try the approach of using a startup script to secure commands in the constrained endpoint.
Unfortunately my customer is typing adverse and I had to resort to making my solution menu driven to minimize typing.
I am attempting to break their grip on the mouse by keeping all activity in the PowerShell host. i.e. no popup graphical elements, in the hope that some of braver souls may actually try typing a few cmdlets.
(Yes, a switch statement would be better for the “Are You sure” cases below, but this is a work in progress )
Unfortunately, when my constrained endpoint’s start up script gets to the $_.Visibility = ‘Private’ sections, my screen bleeds over and over errors similar to:
The property ‘Visibility’ cannot be found on this object. Verify that the property exists and can be set.
At D:\scripts\Constrained_startup.ps1:264 char:9
- $Command.Visibility = ‘Private’
-
- CategoryInfo : InvalidOperation: (
, RuntimeException
- FullyQualifiedErrorId : PropertyAssignmentException
I must be missing something.
Tips and feedback are more than welcome!
Marty Wiedmeyer
Here’s what the script looks like:
$PVER = "ScheduledTasksProfile 1.01 - 20141023 - 14:32 Central" # *** Variables *** New-Variable -name temp -value $([io.path]::gettemppath()) Set-Variable -Name PSEmailServer -Value smtp-out.us.Nuex.com #Set-Variable -Name PSSessionConfigurationName -value WithProfile New-Variable -Name VIMPATH -Value "D:\Nuex\apps\vim\vim74\vim.exe" New-Variable -Name WD -Value "D:\Nuex\Work\" # *** Update the PATH to include our scripts directory for the current user only, in their current sesson *** $env:PATH += ";D:\Nuex\Scripts;D:\Nuex\Apps;D:\Nuex\Apps\vim\vim74" # Add the custom formatting files to the session, placing them at the beginning of the path Update-FormatData -PrependPath D:\Nuex\Modules\Nuex.format.ps1xml # Add the shared Module pdir to the $PSModulePath $env:PSModulePath = $env:PSModulePath + ";D:\Nuex\Modules" # Change the Path permantly for the entire machine #[Environment]::SetEnvironmentVariable("PATH", "D:\Nuex\Scripts;" + $env:Path, 'Machine') # *** Alias *** New-Alias -name lst -value List-ScheduledTask New-Alias -name m -value Show-NuexTaskCommands New-Alias -name stast -value Start-ScheduledTask New-Alias -name stost -value Stop-ScheduledTask New-Alias -name cst -value Control-ScheduledTask New-Alias -name raie -value Restart-AIE New-Alias -name rap -value Restart-ARPlugin New-Alias -name rar -value Restart-ARrecond $NuexTaskCommands = @" ========================= Scheduled Task Management ========================= Control-Scheduledtask [cst] -Control Nuexv3 Scheduled Tasks ============================== Process and Service Management ============================== Restart-AIE [raie] -Restart AIE Restart-ARPlugin [rap] -Restart arplugin Restart-ARrecond [rar] -Restart arrecond "@ #Define Custom Proxy functions Function Set-Nuexlog { $Script:GetTime = get-date -Format "HH:mm" $Script:Today = get-date -Format "yyyyMMdd" $Script:LogFile = "D:\Nuex\work\logs\$Today.txt" } # End function Set-NuexLog Function Write-NuexLog { Set-NuexLog $ServerName = $env:COMPUTERNAME $RemoteConnection=$PSSenderInfo|select -expandProperty ConnectionString $RemoteUser=$PSSenderInfo|select -expandProperty ConnectedUser Write-Output "$ServerName,$MenuItem,$env:UserName,$Script:GetTime,$Script:Today,$Script:CmdArgs,$RemoteUser,$RemoteConnection"|Out-File $Script:LogFile -append $Script:CmdArgs = $null } # End Function Write-NuexLog function Prompt { if ([System.IntPtr]::Size -eq 8) {$size = '64 bit'} else {$size = '32 bit'} $CurrentUser = [Security.Principal.WindowsIdentity]::GetCurrent() $SecPrin = New-Object Security.Principal.WindowsPrincipal $CurrentUser if ($SecPrin.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {$Admin = 'Administrator'} else {$Admin = 'non-Administrator'} if ($Host.Name -eq "ServerRemoteHost") {$Remote = "[REMOTE SESSION]" $MachineName = $null } else {$Remote = $null $MachineName = "$env:COMPUTERNAME" } $host.ui.RawUI.WindowTitle = "$Reminder $Admin $Size $Remote" #"$MachineName :: $(get-location) "$MachineName :: m for the menu PS>" } # End function Prompt Function Restart-AIE { $PlugAns = Read-Host "You are about to restart the AIE Service" stop-Service -DisplayName *AIE* -Confirm $MenuItem = "Restart-AIE" Write-NuexLog } # end function Restart-AIE Function Restart-ARPlugin { $PlugAns = Read-Host "You are about to restart arplugin" stop-process -Name arplugin -Confirm $MenuItem = "Restart-ARPlugin" Write-NuexLog } # end function Restart-ARPlugin Function Restart-ARrecond { $PlugAns = Read-Host "You are about to restart ARrecond" stop-process -Name ARrecond -Confirm $MenuItem = "Restart-ARrecond" Write-NuexLog } # end function Restart-ARrecond Function Show-NuexTaskCommands { $NuexTaskCommands $MenuItem = "Show-NuexTaskCommands" Write-NuexLog } # end function Show-NuexTaskCommands Function List-ScheduledTask { get-scheduledtask "*Remedyload*" } Function Control-ScheduledTask { $Script:CmdArgs=$null $TodaysDate = Get-date -format yyyyMMdd-hhmm $ANS= $Null $Target = $Env:COMPUTERNAME Write-Output "Nuexv3 Tasks on $Target :" get-scheduledtask "*Remedyload*" | select TaskName, State|format-table -AutoSize $TargetTask = Read-Host "Enter (copy/paste or type) the name of the task to affect" $Action = Read-Host "St(A)rt, St(O)p, (E)nable or (D)isable $TargetTask" switch ($Action) { A { Start-Scheduledtask $TargetTask } e { Enable-Scheduledtask $TargetTask } d { Write-Output "You are about to Disable $TargetTask -Are you sure? Ctrl-C to exit" pause Disable-Scheduledtask $TargetTask } o { Write-Output "You are about to Stop $TargetTask -Are you sure? Ctrl-C to exit" pause Stop-Scheduledtask $TargetTask } default { Write-Output "Please make a valid entry A, O, E or D. Exiting...`n" break } } $Script:CmdArgs=$Target $MenuItem = "Update-ScheduledTask" Write-NuexLog } #End Function Control-ScheduledTask Function Control-ScheduledTaskRemote { $Script:CmdArgs=$null $TodaysDate = Get-date -format yyyyMMdd-hhmm $ANS= $Null $ANS = Read-Host "Control a Scheduled Task in (D)ev or (S)IT" switch ($ANS) { D { $Target = "NUVDWITSM3AP21" } S { $Target = "NUVSWITSM3AP21" } } Write-Output "Nuexv3 Tasks on $Target :" invoke-command -comp $Target -scriptblock {get-scheduledtask "*Remedyload*"} $TargetTask = "Enter the name of the Task to affect" $Action = Read-Host "St(A)rt or St(O)p The Service" switch ($Action) { A { invoke-command -comp $Target -scriptblock {Start-Scheduledtask $TargetTask} } o { invoke-command -comp $Target -scriptblock {Stop-Scheduledtask $TargetTask} } } $Script:CmdArgs=$Target $MenuItem = "Update-ScheduledTaskRemote" Write-NuexLog } #End Function Control-ScheduledTaskRemote #Proxy functions [string[]]$proxyFunction = 'Update-ScheduledTask','Show-NuexTaskCommands','Get-Command','Restart-AIE','Restart-ARPlugin','Restart-ARrecond','List-ScheduledTask','Control-ScheduledTask','Prompt','Write-NuexLog','Set-NuexLog' #Variables Get-Variable | ForEach { $_.Visibility = 'Private' } #Aliases Get-Alias | ForEach { $_.Visibility = 'Private' } #Cmdlets ForEach ($Command in (Get-Command|Select-String "Measure-Object" -notmatch)) { If (($proxyFunction -notcontains $Command.Name)) { $Command.Visibility = 'Private' } } $ExecutionContext.SessionState.Applications.Clear() $ExecutionContext.SessionState.Scripts.Clear() $ExecutionContext.SessionState.LanguageMode = "NoLanguage" $NuexTaskCommands