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