Enumerating local groups using Invoke-Command on remote machines - powershell

I have an issue with a function I've wrote to return members of local groups when it is run against a remote machine. We use secondary domain accounts for admin privileges so I've used Invoke-Command so we can run the script block with that account, however, when I do this as opposed to running a new PowerShell window with my admin credentials, it can't enumerate members of the local group that aren't local users.
$computers = "blah"
$creds = Get-Credential
$sb = {
param($c)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
$context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype,$c
$idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
$lg = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context,$idtype,"administrators")
$members = $lg.Members
return $members
}
foreach ($c in $computers) {
if ($c -eq $env:COMPUTERNAME) { & $sb -c $c }
else {
Invoke-Command -ComputerName $c -Credential $creds -ScriptBlock $sb -ArgumentList $c
}
}
When run against a machine that I'm logged in to locally it returns all members of the local group. It also works if I start a new console with my second account. If credentials are passed with Invoke-Command though, I receive errors pertaining to a lack of network access and it appears to happen after successfully listing the two local accounts on a machine first.
Information returned for lg variable when failing:
PSComputerName : blah
RunspaceId : hex...
IsSecurityGroup : True
GroupScope : Local
Members : {local_admin, local_user}
Context : System.DirectoryServices.AccountManagement.PrincipalContext
ContextType : Machine
Description : Administrators have complete and unrestricted access to the computer/domain
DisplayName :
SamAccountName : Administrators
UserPrincipalName :
Sid : SID...
Guid :
DistinguishedName :
StructuralObjectClass :
Name : Administrators
When it's successful, the Members section includes domain groups and users too (identical results if remotely with shell run as second account or locally on the server logged on as second account):
IsSecurityGroup : True
GroupScope : Local
Members : {local_admin, local_user, domain_group, domain_group, domain_user...}
Context : System.DirectoryServices.AccountManagement.PrincipalContext
ContextType : Machine
Description : Administrators have complete and unrestricted access to the computer/domain
DisplayName :
SamAccountName : Administrators
UserPrincipalName :
Sid : SID...
Guid :
DistinguishedName :
StructuralObjectClass :
Name : Administrators
Two different errors received with slightly different approaches:
An error occurred while enumerating through a collection: The network path was not found.
.
+ CategoryInfo : InvalidOperation: (System.Director...ctionEnumerator:PrincipalCollectionEnumerator) [], RuntimeException
+ FullyQualifiedErrorId : BadEnumeration
+ PSComputerName : blah
Cannot convert value "System.DirectoryServices.AccountManagement.PrincipalCollection" to type "System.Array". Error: "The network path was not found.
"
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
+ PSComputerName : blah
The first message is from just trying to return the members variable, the second one was when I tried to make that variable an array. I think they essentially have the same root cause. I tried adding the -EnableNetworkAccess switch to Invoke-Command, but this doesn't change the error received.
I appreciate that I already know a way to make this work, but we'd like to see if there is any way around running the shell with admin credentials and only introducing them when they need to be passed for remote servers. It doesn't appear to be an authentication issue because we can run more simple commands using Invoke-Command i.e. ipconfig or whoami.
I'm using PowerShell 5.1
Thanks.

PoSH remoteing requires the account to be a local admin on the target host, with the exception of the commands listed below. Is this...
'We use secondary domain accounts for admin privileges'
... a local admin?
https://technet.microsoft.com/en-us/library/ff699046.aspx
Some cmdlets have a –ComputerName parameter that lets you work with a remote computer without using Windows PowerShell remoting. This means you can use the cmdlet on any computer that is running Windows PowerShell, even if the computer is not configured for Windows PowerShell remoting. These cmdlets include the following
If you are trying to remote across domain, you are going to get hit with the Windows double hop restriction and you'll need to plan and configure for that type of scenario. See the below.
https://blogs.msdn.microsoft.com/clustering/2009/06/25/powershell-remoting-and-the-double-hop-problem
An Easy “Double-Hop” Solution
You can use CredSSP to delegate your credentials to the remote computer so every remote access from the remote machine will also work. To enable this, you will need to run (from an elevated command prompt) the following command on the client machine:
Or this option...
https://blogs.technet.microsoft.com/ashleymcglone/2016/08/30/powershell-remoting-kerberos-double-hop-solved-securely
Are you facing issues with PowerShell remoting and credentials? You remote into your jump box, but then any remoting beyond there gets a big red ACCESS DENIED. Maybe you’ve tried CredSSP, but people say that isn’t safe. Read today’s post for a completely legit, secure, safe, and easy way to enable Kerberos double hop for PowerShell remoting.

Related

Powershell VSCode invoke-command from localhost different user for SCCM

Because VSCode is not able to run a powershell console and debug it as a different user i am trying to get arround it with invoked credentials like this:
Start-Service -Name "WinRM"
$cred = Get-Credential -Credential domain\myuser
Invoke-command -Credential $cred -Computer "localhost" -scriptblock {
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"
Set-Location 'XXX:' # my sccm site code
Import-CMComputerInformation -CollectionName "All Systems" -ComputerName "TestComputer" -MacAddress "00:00:00:00:00:69"
}
If i start it in the debugger of VSCode (F5) it starts but cant connect then to the SCCM Server infrastructure. Could someone help me to solve this issue?
Error:
Cannot find drive. A drive with the name 'XXX' does not exist.
+ CategoryInfo : ObjectNotFound: (XXX:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
+ PSComputerName : localhost
This command cannot be run from the current drive. To run this command you must first connect to a Configuration Manager drive.
+ CategoryInfo : DeviceError: (Microsoft.Confi...ormationCommand:ImportComputerInformationCommand) [Import-CMComputerInformation], InvalidOperationException
+ FullyQualifiedErrorId : CommandCannotExecuteFromCurrentDrive,Microsoft.ConfigurationManagement.Cmdlets.Oob.Commands.ImportComputerInformationCommand
+ PSComputerName : localhost
If i logoff from my machine and login with my admin credentials and execute everything in the invoke-command scriptblock it works.
As i am not allowed to work like this by our company policy's is there maybe a alternative way or something i can do to use the visual studio code debugger?
Have you logged onto the SCCM site server interactively with the credentials you are using and opened the console at least once? I believe this initial first opening is required before the drive is accessible remotely...

Trying to Retrieve A Reg Value From Remote Machines Using Powershell

I am trying to retrieve a registry value from each computer using a for each loop and then output that value to a folder in a csv.
That part works fine. The part I am having an issue with is having powershell connect to the remote computers.
This is running internal only
I have admin rights across all workstations
Firewalls are configured to allow all traffic to pass
When I run this script I get this error for every workstation it tried to connect to:
Enter-PSSession : Connecting to remote server workstationX failed with
the following error message : WinRM cannot complete the operation.
Verify that the specified computer name is valid, that the computer
is accessible over the network, and that a firewall exception for the
WinRM service is enabled and allows access from this computer. By
default, the WinRM firewall exception for public profiles limits
access to remote computers within the same local subnet. For more
information, see the about_Remote_Troubleshooting Help topic. At
C:\Users\Rich_Ellis\Desktop\O365\O365Channels\O365Channel.ps1:5 char:2
+ {Enter-PSSession -ComputerName $Computer
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (workstationX:String) [Enter-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : CreateRemoteRunspaceFailed
My script is:
$Computers = Get-Content "C:\Users\Rich_Ellis\Desktop\O365\O365Channels\computers.txt"
foreach ($Computer in $Computers)
{Enter-PSSession -ComputerName $Computer
$key = 'HKLM:\SOFTWARE\Microsoft\Office\CLickToRun\Configuration'
(Get-ItemProperty -Path $key -Name CDNBaseUrl).CDNBaseUrl | Export-CSV -path "\\s00itstorage\OfficeChannel\$($env:COMPUTERNAME)-O365Channel03292018.csv"}
Any help would be appreciated. TIA
Molding a previous answer to your use-case:
$HKEY_LOCAL_MACHINE = 2147483650
$GwmiArgs = #{
Class = 'StdRegProv'
Namespace = 'Root\Default'
List = $True
}
ForEach ($Computer in #(Get-Content -Path 'C:\Users\Rich_Ellis\Desktop\O365\O365Channels\computers.txt'))
{
$GwmiArgs['ComputerName'] = $Computer
$Registry = Get-WmiObject #GwmiArgs
$Registry.GetStringValue(
$HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Office\ClickToRun\Configuration',
'CDNBaseUrl'
).sValue | Export-CSV -Path "\\s00itstorage\OfficeChannel\$Computer-O365Channel03292018.csv"
}
This uses wmi instead of psremoting to poll the information which may be easier to rely on as it is already configured/enabled on most PCs and can utilize IP addresses due to DCOM/RPC (psremoting only supports kerberos by default)
This solution can be further improved by using Invoke-WmiMethod instead of creating a wmi object for each poll, but I haven't done the work already for that!

Get-ADDomain fails, UI works

Trying to join a Windows Server 2016 to a domain using PowerShell.
However, PowerShell fails on Get-ADDomain with :
Get-ADDomain -Identity customer.com.au -Credential $domainCred
Error :
Get-ADDomain : Unable to contact the server. This may be because this
server does not exist, it is currently down, or it does not have the
Active Directory Web Services running. At line:1 char:1
+ Get-ADDomain -Identity customer.com.au -Credential $domainCred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (customer.com.au:ADDomain) [Get-ADDomain], ADServerDownException
+ FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADDomain
Get-ADDomainController -Discover -Service ADWS -DomainName customer.com.au
Domain : customer.com.au
Forest : customer.com.au
HostName : {CUSTOMERSVRDC06.customer.com.au}
IPv4Address : 10.20.104.86
IPv6Address :
Name : CUSTOMERSVRDC06
Site : customer-main-site
So, AD Web Services are running on a server in that domain. I can resolve the domain.
And I can even promote this server manually via Server Manager just fine, with the same credentials.
Anybody got an idea what’s wrong with AD PowerShell?
Cheers
David
Turns out there was a port still missing on the network side.
They opened up the firewall for now and it works. I suspect a random high port.
Sounds like you cannot reach the ADWS. That is common with corporate networks if firewall or policies are not designed to allow it. Regardless, you can achieve this with below options too.
Use the -Server param on Get-AD~ Cmdlets and specify a DC to query. You said you know at least 1 DC with ADWS on and reachable.
Use Invoke-Command or other PSRemoting features to remote into a DC and run those commands as if you were logged on locally on the DC. Doesn't need ADWS to be available on the Network.
You can also use PSexec with Invoke-Expression to run your code on the target machine.

Powershell. Load AD module and perform AD action

Short explanation:
We have more than 1000 PCs (Win7+8+10)
On the PCs, I would like to run a script that can remove a Computer Account from a group. (In the code examples below I'm using Get-AdComputer as it gives the same error)
I need to do this without Domain Admin rights.
The PC's do not have RSAT / Admin Tools installed.
First I tried:
$Session = New-PSSession -ComputerName DomainController1
Import-PSSession -Session $Session -Module ActiveDirectory
Get-Adcomputer TestPC
With Domain Admin account, it works just fine.
With Non Domain Admin account it fails the 1. line with:
New-PSSession : [DomainController1] Connecting to remote server DomainController1 failed with the following error message : Access is denied
Then I installed RSAT/Admin tools on a member server and tried to import AD module from that server:
$Session = New-PSSession -ComputerName MemberServer1
Import-PSSession -Session $Session -Module ActiveDirectory
Get-Adcomputer TestPC
The Import of the ActiveDirectory module is fine, with both Domain Admin account and non-Domain Admin account, but I get an error when running the "Get-Adcomputer TestPC" command:
Unable to contact the server. This may be because this server does not exist, it is currently down, or it does not have the Active Directory Web Services running.
+ CategoryInfo : ResourceUnavailable: (TestPC:ADComputer) [Get-ADComputer], ADServerDownException
+ FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
+ PSComputerName : MemberServer1
I notice the PSComputername is the Memberserver1 now, and not the DomainController1.
I guess thats why I get the error: It's trying to perform it on a non Domain Controller
Other information:
The "Get-Adcomputer TestPC" works fine with Non-Domain Admin account on a PC where RSAT / Admin tools are installed.
"Exit-PSSession" and "Remove-PSSession Memberserver1" does not help
So: How can I either :
Import the AD module from a DC, without beeing Domain Admin?
After Import of AD module from MememberServer, change "active" computer to be any DC?
Solve my problem in another way?
Thanks
Build a remote constrained session on one or more of your DCs.
Create a function for removing a computer from that group, and constrain the session to just being able to run that function. You can use a delegated account if the users don't have permission directly (If you have WMF 5 installed on the DC, you can use a virtual account).
The users can use Enter-PSSession to enter that session and run the function manually, or you can give them a local function that will do it using Invoke-Command directed at that session.

Powershell remoting does not have the correct permissions

On the non-domain server SERVER I have a local administrator account USER.
On the domain client machine I am running as a domain user.
Using the following code I attempt to view all services on SERVER
$cred = Get-Credential "SERVER\USER"
Invoke-Command -ComputerName SERVER -ScriptBlock {Get-Service} -Credential $cred
However, I receive the following error
Cannot open Service Control Manager on computer '.'. This operation might require other privileges.
+ CategoryInfo : NotSpecified: (:) [Get-Service], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.GetServiceCommand
Yet, if I RDP to SERVER as USER, I can manually open a Powershell window and run Get-Service without any issues. What's going on?
When remoting cross-domain, the remote command/session will not run with administrative rights. Even though you're connecting as a local admin, the resulting PSSession will not be elevated.
To fix this, you need to set the registry key LocalAccountTokenFilterPolicy located in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System to 1. See Microsoft for more details