在不提示的情况下在 Powershell 中获取当前用户的凭据对象

Posted

技术标签:

【中文标题】在不提示的情况下在 Powershell 中获取当前用户的凭据对象【英文标题】:Get current user's credentials object in Powershell without prompting 【发布时间】:2010-10-12 18:26:40 【问题描述】:

我有一个 Powershell 脚本,它将通过自动化工具针对多台服务器运行。

它在 Windows 机器上运行良好,因为远程调用使用该工具的服务帐户,无需在代码中提示或公开任何凭据。

此脚本还可以使用 SharpSSH 包通过 SSH 在 Linux 机器上运行。 SharpSSH 不会自动使用 Powershell 用户的凭据,但需要用户名和密码、RSA 密钥文件或 PSCredential 对象。

我无法使用 Get-Credential 提示输入凭据,因为它是通过自动化工具运行的。我不想在代码中公开用户名和密码,也不想有一个 RSA 密钥。我想从当前 Powershell 用户(服务帐户)构造一个 PSCredential 对象。

尝试[System.Net.CredentialCache]::DefaultNetworkCredentials 显示空白,[System.Security.Principal.WindowsIdentity]::GetCurrent() 未提供我需要的对象或信息。

有没有人可以从当前用户创建PSCredential 对象?或者可能是针对这个问题的完全不同的替代方案?

非常感谢!

【问题讨论】:

【参考方案1】:

Windows API 不会公开您需要的信息,这就是 Powershell 无法获取它们的原因。它是安全子系统的一个有意的功能。唯一可行的方法是让 Linux 机器信任调用机器,例如将它们加入 Active Directory(或任何 kerberos 设置)。

除此之外,您还需要以某种方式存储和传递这些信息。

您可以将 RSA 密钥存储在用户的密钥库中并在运行时提取它(使用 .NET Crypto/Keystore 库),因此您不会将密钥与代码一起存储。这样,密钥本身将受到操作系统的保护,并且仅在调用用户经过身份验证时才可用。您还需要安装一件东西,但这可能是实现您的目标的唯一方法。

【讨论】:

啊,真不幸。经过一些讨论和研究,我们将使用 RSA 密钥。无论如何,它最终会在未来启用更多功能。谢谢,泰勒! 你说如果用户是AD的一部分,你可以得到一个凭证对象;那是对的吗?我正在尝试在 Windows 上执行此操作(问题的标题)。【参考方案2】:

“尝试 [System.Net.CredentialCache]::DefaultNetworkCredentials 显示空白,并且 [System.Security.Principal.WindowsIdentity]::GetCurrent() 未提供我需要的对象或信息。”

你已经有了答案。我用它在几个脚本中传递当前登录用户的凭据:

$Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$Username = $Credentials.UserName
$Password = $Credentials.Password

如果您尝试将它们转储到任何类型的可读输出,当您转储它们时这些值是空的(出于明显的安全原因),但是它们确实可以在您需要 PSCredential 对象的地方工作。

【讨论】:

你能给我们一个 cmdlet 的例子,它可以接受这个 PSCredential,因为我还没有找到。一直在尝试使用它传递给 Send-MailMessage 没有成功 这似乎对我不起作用:> pss mytarget -Credential $Credentials Enter-PSSession: Cannot process argument transformation on parameter 'Credential'. userName【参考方案3】:

由于您可以从凭证对象中获取明文密码,因此我怀疑您是否可以在不提示的情况下获取此密码。

【讨论】:

【参考方案4】:

如何使用服务帐户的加密密钥加密密码?

一个简单的例子:

以服务帐户运行 PowerShell,运行以下命令并将输出保存到文本文件(或将其嵌入到计划任务调用中):

$String = '<PASSWORD>'
ConvertFrom-SecureString -SecureString (ConvertTo-SecureString -String $String -AsPlainText -Force)

在您的计划任务中使用以下命令来解密和使用密码:

 $EncryptedString = '<ENCRYPTED PASSWORD FROM ABOVE>'
 [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString -String $EncryptedString)))

这应该可以解决问题。但是,您不能在另一台计算机上重复使用加密的密码,或者如果您出于某种原因破坏了本地密钥库:)

【讨论】:

secureString 方法是可逆的,因此密码在技术上并不安全。如果没有 -force 选项,您将得到:“ConvertTo-SecureString : 系统无法保护纯文本输入。” @cmcginty ConvertTo-SecureString 仅对创建它的计算机上的用户是可逆的。解密它需要以该用户身份登录。因此,NTFS 权限足以保护您保存到的文本文件。

以上是关于在不提示的情况下在 Powershell 中获取当前用户的凭据对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在不提示用户提供 Facebook 权限的情况下在 iOS 应用程序中获取公共 Facebook 页面的提要?

如何在不进行硬编码的情况下在 C++ 中获取类数组的长度?

如何在不参考 NSEvent 的情况下在 Objective-C 中获取键盘状态

如何在不刷新页面的情况下在屏幕上显示新记录?

如何在不定义任何限制的情况下在 python 中获取任意数量的输入?

在不使用字符串的情况下在 javascript 中获取另一个时区的时区偏移量