我遇到了一个函数问题,我已写过该函数,以便在针对远程计算机运行时返回本地组的成员。我们使用辅助域帐户获取管理员权限,因此我使用了Invoke-Command,因此我们可以使用该帐户运行脚本块,但是,当我执行此操作而不是使用我的管理员凭据运行新的PowerShell窗口时,它可以& #39; t枚举本地用户不是本地用户的成员。
$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
}
}
当我在本地登录的计算机上运行时,它将返回本地组的所有成员。如果我用我的第二个帐户启动一个新控制台,它也可以工作。如果使用Invoke-Command传递凭据,我会收到与缺少网络访问有关的错误,并且似乎在首先在计算机上成功列出两个本地帐户后发生。
失败时为lg变量返回的信息:
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
如果成功,会员部分也包括域组和用户(如果远程使用shell作为第二个帐户运行,或者在作为第二个帐户登录的服务器上本地,则相同的结果):
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
收到两种不同的错误,方法略有不同:
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
第一条消息来自于尝试返回成员变量,第二条消息是我尝试将该变量设为数组时。我认为他们基本上有相同的根本原因。我尝试将-EnableNetworkAccess开关添加到Invoke-Command,但这并没有改变收到的错误。
我很欣赏我已经知道了一种方法来完成这项工作,但是我们想知道是否有任何方法可以使用管理员凭据运行shell,并且只有在需要为远程服务器传递时才引入它们。它似乎不是一个身份验证问题,因为我们可以使用Invoke-Command运行更简单的命令,即ipconfig或whoami。
我使用的是PowerShell 5.1
感谢。
答案 0 :(得分:0)
PoSH远程控制要求帐户是目标主机上的本地管理员,但下面列出的命令除外。这是......
'我们使用辅助域帐户获取管理员权限'
......本地管理员?
https://technet.microsoft.com/en-us/library/ff699046.aspx 某些cmdlet具有-ComputerName参数,使您可以在不使用Windows PowerShell远程处理的情况下使用远程计算机。这意味着您可以在运行Windows PowerShell的任何计算机上使用cmdlet,即使计算机未配置为Windows PowerShell远程处理也是如此。这些cmdlet包括以下
如果您尝试跨域远程操作,您将受到Windows双跳限制的攻击,并且您需要为该类型的方案进行规划和配置。见下文。
https://blogs.msdn.microsoft.com/clustering/2009/06/25/powershell-remoting-and-the-double-hop-problem 一个简单的“双跳”解决方案
您可以使用CredSSP将您的凭据委派给远程计算机,以便远程计算机的每次远程访问也可以使用。要启用此功能,您需要在客户端计算机上运行(从提升的命令提示符下)以下命令:
或者这个选项......
https://blogs.technet.microsoft.com/ashleymcglone/2016/08/30/powershell-remoting-kerberos-double-hop-solved-securely 您是否面临PowerShell远程处理和凭据的问题?你远程进入你的跳跃盒,但是那里的任何遥控都会得到一个大的红色ACCESS DENIED。也许你已经尝试过CredSSP,但人们说这不安全。阅读今天的帖子,了解为PowerShell远程处理启用Kerberos双跃点的完全合法,安全,安全且简便的方法。
答案 1 :(得分:0)
谢谢,postanote,链接。
最后,我看了一个在本地使用第二个帐户凭据调用命令的过程,同时保留在同一个shell中。这是通过创建脚本文件并在单独的进程中运行它来捕获标准输出/错误并解析返回的字符串来完成的。我希望这是有道理的,我有时会解释一些事情。
这是我回来的内容:(我应该在这里说我创建自定义.NET类型作为单独脚本的一部分,作为导入函数的模块清单的一部分加载)
[CmdletBinding(SupportsShouldProcess)]
Param (
[string[]]$computer = $global:LoggedOnUser.Computer,
[string]$group = "administrators",
[System.Management.Automation.PSCredential]$creds = $global:AdminUser.Credentials
)
Begin {
# Initialise output array
$groupArray = @()
# Check C:\Temp exists locally
if (!(Test-Path C:\Temp)) { New-Item -Path C:\Temp -ItemType Directory -Force }
# Run this locally with second administrator account in a new process
$secondAccountSB = {
param([System.Management.Automation.PSCredential]$creds = $creds,$c = $c, $group = $group)
$prcsi = New-Object System.Diagnostics.ProcessStartInfo "PowerShell"
$prcsi.Arguments = "-File C:\Temp\Local_Group_Check.ps1 -c $c -group $group"
$prcsi.RedirectStandardError = $true
$prcsi.RedirectStandardOutput = $true
$prcsi.LoadUserProfile = $false
$prcsi.UserName = $creds.UserName
$prcsi.Password = $creds.Password
$prcsi.Domain = "Domain"
$prcsi.UseShellExecute = $false
$prcsi.WorkingDirectory = "C:\Temp"
$prc = New-Object System.Diagnostics.Process
$prc.StartInfo = $prcsi
$prc.Start() | Out-Null
$prc.WaitForExit()
$output = $prc.StandardOutput.ReadToEnd()
$failed = $prc.StandardError.ReadToEnd()
$output
$failed
}
# Create string for a script
$groupReportSB = "
param(`$c,`$group)
# Add Directory Services .NET Type
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
`$ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
# Initialise array
`$localGroups = @()
# Connect to local Directory Services
`$context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList `$ctype,`$c
`$idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
Try { `$lg = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity(`$context,`$idtype,`$group) }
Catch [System.Management.Automation.MethodInvocationException] {
`$errorMessage = `$_.Exception.InnerException.Message
Write-Host `"`$($`c.ToUpper()): `$(`$errorMessage.Trim())`" -ForegroundColor Yellow -BackgroundColor Black
continue
}
# Obtain a list of each local group's members
`$members = `$lg.Members
# Create PSObject
foreach (`$member in `$members) {
if ((`$member.StructuralObjectClass -eq `$null) -or (`$member.StructuralObjectClass -ilike `"user`")) {
`$groupMembers = `"N/A`"
}
else { [string]`$groupMembers = `$member.Members -join `"; `" }
`$gm = New-Object -TypeName psobject
`$gm | Add-Member -MemberType NoteProperty -Name Account -Value `$member.SamAccountName
`$gm | Add-Member -MemberType NoteProperty -Name Computer -Value `$c.ToUpper()
`$gm | Add-Member -MemberType NoteProperty -Name Description -Value `$member.Description
`$gm | Add-Member -MemberType NoteProperty -Name Object -Value `$member.StructuralObjectClass
`$gm | Add-Member -MemberType NoteProperty -Name Group -Value `$lg.Name
`$gm | Add-Member -MemberType NoteProperty -Name Members -Value `$groupMembers
`$gm | Add-Member -MemberType NoteProperty -Name Context -Value `$member.ContextType
`$gm | Add-Member -MemberType NoteProperty -Name Scope -Value `$member.GroupScope
`$localGroups += `$gm
}
# Return Local Groups for this machine
`$localGroups
"
}
Process {
$count = 1
$total = $computer.Count
foreach ($c in $computer) {
Write-Host "[$($count)/$($total)] Collecting information from $c..."
if (Test-Path C:\Temp\Local_Group_Check.ps1) { Remove-Item C:\Temp\Local_Group_Check.ps1 -Force }
$groupReportSB | Out-File -FilePath C:\Temp\Local_Group_Check.ps1 -Force -NoClobber
$returnedOutput = & $secondAccountSB -c $c -group $group
$groupArray += ConvertTo-WinPSObject -inputObject $returnedOutput -dataType LocalGroups
$count ++
}
}
End {
# Return Group Array
$groupArray
}
正如我所说,这样做的目的是使其与其他管理功能相配合,这些功能具有更好的远程运行功能,并使用户保持在一直运行的同一个shell中。一个次要的,提升的帐户。
我知道代码没有正确显示,但它会在具有PS语法功能的编辑器中显示。