2

我希望能够使用 PowerShell 登录 VIServers 并让它在脚本第一次运行时询问凭据,然后将这些凭据保存在 password.txt 文件中,让 VIServer 只使用存储在本地的 password.txt 文件如果用户再次运行脚本,则为用户的计算机。痛点是,当用户想要多次运行脚本时,凭据提示会一次又一次地弹出。

我可以使用 Stackoverflow 上发布的另一个答案中的以下代码(链接: http: //www.adminarsenal.com/admin-arsenal-blog/secure-password-with-powershell-encrypting-credentials-part-1

它有效:

    Read-Host "Enter Password" -AsSecureString | ConvertFrom-SecureString |
               Out-File "G:\dev\Password.txt"

    $pass = Get-Content "G:\dev\Password.txt" | ConvertTo-SecureString

    $User = "MyUserName"
    $File = "G:\dev\Password.txt"
    $MyCredential = New-Object -TypeName System.Management.Automation.PSCredential
                    -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString)

我从 vmware 博客中找到了以下内容(链接:http: //blogs.vmware.com/PowerCLI/2011/11/have-you-seen-powerclis-credential-store-feature.html

这是来自 vmware 博客的代码(有一些解释):

要使用凭证存储,我执行以下操作:

New-VICredentialStoreItem -Host 192.168.10.10 -User "Andrey" -Password "my favorite password"

现在我可以输入:

Connect-VIServer 192.168.10.10

当我没有指定用户和/或密码时,Connect-VIServer 会检查凭证存储,找到我新存储的凭证并使用它。

默认情况下,凭证存储文件存储在用户配置文件目录下。它是加密的。如果我让你感兴趣,请查看“help *VICredentialStoreItem”了解详细信息。

-Andrey Anastasov,PowerCLI 架构师

=============现在是我修改后的 VIServer 代码版本========== $Hostname = 192.168.10.10

New-VICredentialStoreItem -Host $Hostname -User $User -Password $pass

我在正确的轨道上吗?

我应该怎么做才能只输入 1 次凭据,然后让脚本调用 $creds 变量,而不必每次都输入凭据?

4

3 回答 3

1

我在这个问题的大多数答案中看到的问题是密码是以纯文本形式处理和存储的。安全方面,这是一个很大的禁忌。PowerShell 可以确保这些凭据在内存中以及存储时的安全。可以创建一个安全的 XML 文件,该文件只能由创建它的用户访问,并且只能在创建它的机器上访问。我没有创建所有这些脚本,我在不同位置在网上找到了一些片段,所以我没有名字可以信任。

#Store-Credentials
#This script collects the credentials used by my other scripts and saves them into secure XML files.
#The XML files can only be imported by my user account, and only from the machine it was created on specifically.
#This script needs to be run any time you change your password, obviously...

    $counter = 0
    $again = $true

    while($again){
        if($counter -ge 3){
            Write-Warning -Message ('You have entered your password {0} times incorrectly' -f $counter)
            Write-Warning -Message ('Please wait until {0} to try again to avoid risking locking yourself out.' -f $((Get-Date).AddMinutes(+15).ToShortTimeString()))
            Start-Sleep -Seconds 30
        }

        # Get username and password from user...
        $username = Read-Host -Prompt 'Please enter your SSO using full path (Domain\SSO)'
        $password = Read-Host -AsSecureString -Prompt 'Please enter your password'

        try{
            $creds = New-Object System.Management.Automation.PSCredential $username,$password

            # Get the current domain
            $domain = 'LDAP://{0}' -f $creds.GetNetworkCredential().Domain

            # Try to get the username and password from the network...
            $username = $creds.GetNetworkCredential().UserName
            $password = $creds.GetNetworkCredential().Password

        }
        catch{
            Write-Warning -Message ('There was a problem with what you entered: {0}' -f $_.exception.message)
            continue
        }

        # Check against the domain to authenticate the user.
        $UserObject = New-Object System.DirectoryServices.DirectoryEntry($domain,$username,$password)
        # If we get a result back with a name property then we're good to go and we can store the credential.
        if($UserObject.name){
            Write-Host "Saving credentials..."
            Export-Clixml -InputObject $creds -Path $env:userprofile\SSOCreds.xml
           
            #Check for stored credentials...
            $creds_stored = Test-Path -Path $env:userprofile\SSOCreds.xml

                If ($creds_stored -eq $true)
                    {Write-Host "Credentials saved."}
                Else
                    {Write-Host "There was a problem writing the file...  your credentials were not saved."}
           
            $again = $false
            Remove-Variable password -Force
        }
        else{
            $counter++

            Write-Warning -Message ('The password you entered for {0} was incorrect.  Attempts {1}. Please try again.' -f $userName,$counter)
        }
    }

存储凭据后,您可以使用以下部分将它们包含在其他脚本的开头

#Check for stored credentials to log onto the vCenter...
        $creds_stored = Test-Path -Path $env:userprofile\SSOCreds.xml

        If ($creds_stored -eq $true) {

            Write-Host "Stored credentials found." -ForegroundColor Cyan
            $creds = Import-Clixml -Path $env:userprofile\SSOCreds.xml
       
        }
        Else {

            $creds = Get-Credential -Message "Please enter your credentials to acces the vCenter using full path (Domain\SSO)."
            Write-Host "If you would like to store your credentials, use the Store-Credentials script." -ForegroundColor Cyan
       
        }

        #Connect-ViServer server.domain.com
        Connect-VIServer -Server $vCenter -Credential $creds -Force
于 2021-01-21T02:19:42.793 回答
0

首先将凭证保存到磁盘,如下所示:

$credential = Get-Credential
$credential.Password | ConvertFrom-SecureString | Set-Content c:\temp\Cred.txt

然后从磁盘加载它并创建一个 $Credential 变量,如下所示:

$username = "Domain\UserName"
$encrypted = Get-Content C:\Temp\Cred.txt | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential($username, $encrypted)

然后您可以使用接收 $credential 输入的函数:

function Connect-vCenter
{
    Param (

    [Parameter(Mandatory = $True)]
    $vCenterServer, 
    [System.Management.Automation.PSCredential]$Credential
    )

    if ($Credential)
    {
        Add-PSSnapin VMware.VimAutomation.Core
        Connect-VIServer $vCenterServer -Credential $Credential
    }
    else
    {
        Add-PSSnapin VMware.VimAutomation.Core
        Connect-VIServer $vCenterServer
    }

}

运行它:

Connect-vCenter -vCenterServer vCenter -Credential $Credential

当然只有加密凭证的用户可以使用它,但是如果你想用不同的密钥(不太安全)加密它,你可以像这样添加 -Key 参数:

$Key = [Byte]1..16
$credential.Password | ConvertFrom-SecureString -Key $Key | Set-Content c:\temp\Cred.txt

解密:

$encrypted = Get-Content C:\Temp\Cred.txt | ConvertTo-SecureString -Key $Key
$credential = New-Object System.Management.Automation.PsCredential($username, $encrypted)
于 2015-07-06T21:53:01.853 回答
0

根据您提供的内容,我可以看到的最简单的方法是将该命令包装在另一个脚本中。一种检查凭证存储,如果您要查找的条目不存在,则提示您输入凭证。

你能告诉我你的工作流程是什么样的吗?

于 2015-07-06T21:44:47.880 回答