PowerShell 技能连载 - 在单侧启用 CredSSP

如之前所示,CredSSP 可以用在远程代码上,避免二次连接问题。不过,要使用 CredSSP 验证方式您得在客户端和服务端分别设置,才能使它们彼此信任。

这并不意味着您必须物理接触那台服务器。如果您想在您的计算机和任何一台服务器(假设那台服务器上启用了 PowerShell 远程连接)建立一个 CredSSP 信任关系,只需要做这些:

1
2
3
4
5
6
7
8
#requires -Version 2.0 -RunAsAdministrator

# this is the server you want to communicate with using CredSSP
# the server needs to have PowerShell remoting enabled already
$Server = 'NameOfServer'

Enable-WSManCredSSP -Role Client -DelegateComputer $Server -Force
Invoke-Command { Enable-WSManCredSSP -Role Server } -ComputerName $Server

如您所见,Enable-WSManCredSSP 可以远程执行。

PowerShell 技能连载 - 用 CredSSP 解决二次远程连接

在钱一个技能中我们演示了当您的远程代码试图通过第三方身份认证时会遇到的二次远程连接问题。

在您在客户端和服务端之间创建了一个可信的连接之后,可以传递您的凭据(只需要做一次,并且需要管理员权限)。

在客户端,运行这段代码:

1
Enable-WSManCredSSP -Role Client -DelegateComputer nameOfServer

在服务端,运行这段代码:

1
Enable-WSManCredSSP -Role Server

现在将 PowerShell 代码从客户端发送到服务端并执行时,服务端能够将您的凭据送给第三方验证通过,所以远程代码可以通过文件服务器的身份认证并访问共享文件夹:

1
2
3
4
5
6
7
8
#requires -Version 3.0

$code =
{
Get-ChildItem -Path \\fls01\#TRAIN1\PowerShell\Class
}

Invoke-Command -Authentication Credssp -ScriptBlock $code -ComputerName nameOfServer -Credential myCompany\myName

请注意当您使用 CredSSP 验证时,您必须提交显式的凭据(用 -Credential)且无法通过 Kerberos 透明传输当前的身份。

PowerShell 技能连载 - 理解二次远程连接问题

当您用 Invoke-Command 远程执行 PowerShell 代码时,您的凭据将会锁定在首个连接的机器上。

PowerShell 远程连接默认情况下不会传递您的凭据,不会使用您的凭据来登录别的系统。这听起来是个好主意,不过在某些情况也严重限制了您的代码。

这是一个典型的错误代码:

1
2
3
4
5
6
$code =
{
Get-ChildItem -Path \\fls01\#TRAIN1\PowerShell\Class
}

Invoke-Command -ScriptBlock $code -ComputerName server1

这段代码试图在远程访问一个文件共享。但是即便您有权限访问该共享,这段远程代码也无法使用您的身份进行第三方验证(在这个例子中是文件服务器)。

PowerShell 技能连载 - 查找隐藏的自启动程序

Ever wondered why some programs launch whenever you log into Windows? Here’s a one liner listing autostarts that affect your login:
是否好奇为什么有些程序在登录 Windows 的时候会自动启动?这是一行列出登录时自启动项的代码:

1
2
3
4
5
#requires -Version 3

Get-CimInstance -ClassName Win32_StartupCommand |
Select-Object -Property Command, Description, User, Location |
Out-GridView

PowerShell 技能连载 - Getting List of Current Group Memberships

当您可以通过 Active Directory 来获取一个用户的组成员,有一个简单的方法是直接通过用户的 access token 获取信息,而不需要 AD 联系人。

这行代码将取出当前用户所在的所有组的 SID:

1
2
#requires -Version 3.0
[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Value

这是获取翻译后的组名的方法:

1
2
#requires -Version 3.0
[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Translate( [System.Security.Principal.NTAccount])

如果这个列表中有重复,那么您就可以知道有多个 SID 指向同一个名字。这种情况在您曾经迁移过 AD(SID 历史)时可能会发生。只需要将结果用管道输出到 Sort-Object -Unique 就能移除重复。

PowerShell 技能连载 - 将 SID 翻译为用户名

是否希望将安全标识符(SID)翻译为一个真实的名称?这个函数将能够帮助您:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#requires -Version 3.0

function ConvertFrom-SID
{
param
(
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[Alias('Value')]
$Sid
)

process
{
$objSID = New-Object System.Security.Principal.SecurityIdentifier($sid)
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
$objUser.Value
}
}

您可以通过参数传入 SID,或通过管道传入一个或多个 SID 给这个函数。

PowerShell 技能连载 - 获取计算机的地理位置

这是获取地理位置信息的另一个免费源,它能够获取您当前的公网 IP 和位置信息:

1
2
3
#requires -Version 3.0

Invoke-RestMethod -Uri 'http://ipinfo.io'

结果大概如下:

1
2
3
4
5
6
ip       : 80.187.113.144
hostname : tmo-113-144.customers.d1-online.com
region :
country : DE
loc : 51.2993,9.4910
org : AS3320 Deutsche Telekom AG

PowerShell 技能连载 - 查找操作系统架构信息

这是获取您操作系统信息的一行代码:

1
Get-WmiObject -Class Win32_OperatingSystem | Select-Object -Property *OS*

结果看起来类似如下:

1
2
3
4
5
ForegroundApplicationBoost : 2
OSArchitecture : 64-bit
OSLanguage : 1031
OSProductSuite : 256
OSType : 18

如果您想知道这些数字代表什么意思,可以在网上搜索 Win32_OperatingSystem 第一个链接就会引导您到对应的 MSDN 文档。

如果您想从一个远程系统中获取信息,请使用 -ComputerName–Credential 参数。

PowerShell 技能连载 - 在 Active Directory 中查找操作系统版本

如果您安装了带有 “ActiveDirectory” PowerShell 模块的 Microsoft RSAT 工具,以下是一个快速获取您环境中操作系统清单的快速方法:

1
2
3
4
#requires -Module ActiveDirectory

Get-ADComputer -Filter * -Properties OperatingSystem, OperatingSystemServicePack, OperatingSystemVersion |
Select-Object -Property Name, OperatingSystem, OperatingSystemServicePack, OperatingSystemVersion

这将获得所有计算机的信息。您可以将搜索范围限制在指定的计算机名和 AD 位置中。以下命令将搜索范围限制在 $root AD 范围内,以及只包含名字以 “Serv” 开头的计算机中:

1
2
3
4
5
6
#requires -Module ActiveDirectory

$root = 'OU=North,OU=Clients,DC=yourcompany,DC=com'

Get-ADComputer -Filter { Name -like 'Serv*' } -Properties OperatingSystem, OperatingSystemServicePack, OperatingSystemVersion <#-ResultSetSize 10#> -SearchBase $root -SearchScope Subtree |
Select-Object -Property Name, OperatingSystem, OperatingSystemServicePack, OperatingSystemVersion

PowerShell 技能连载 - 查找一个月中的第一天和最后一天

您是否曾需要了解某个月的第一天和最后一天?

以下是一个简单的实现方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
# specify the date you want to examine
# default is today
$date = Get-Date
$year = $date.Year
$month = $date.Month

# create a new DateTime object set to the first day of a given month and year
$startOfMonth = Get-Date -Year $year -Month $month -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0
# add a month and subtract the smallest possible time unit
$endOfMonth = ($startOfMonth).AddMonths(1).AddTicks(-1)

$startOfMonth
$endOfMonth