web-dev-qa-db-ja.com

powershellおよびエラーConvertTo-SecureStringによる再利用のための資格情報の保存:指定された状態での使用にはキーが無効です

この投稿で説明したようなことをして、資格情報をセキュリティで保護されたファイルに保存して、自動化プロセスがそれを使用してInvoke-commandを介してリモートPSスクリプトを実行できるようにしました: http://blogs.technet.com/b/robcost /archive/2008/05/01/powershell-tip-storing-and-using-password-credentials.aspx

アカウントでこれを実行するとうまくいきます-パスワードは暗号化されたファイルから読み取られ、Invoke-commandに渡され、すべてがうまくいきます。

今日、スクリプトの準備が整ったときに、自動化されたプロセスで使用されるWindowsアカウントでスクリプトを実行しようとしましたが、スクリプトがファイルからセキュリティで保護されたパスワードを読み取ろうとしたときにこのエラーが発生しました:

ConvertTo-SecureString : Key not valid for use in specified state.
At \\remoted\script.ps1:210 char:87
+ $password = get-content $PathToFolderWithCredentials\pass.txt | convertto-sec
urestring <<<<
    + CategoryInfo          : InvalidArgument: (:) [ConvertTo-SecureString], C
   ryptographicException
    + FullyQualifiedErrorId : ImportSecureString_InvalidArgument_Cryptographic
   Error,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand

私の同僚に彼のアカウントで実行するように頼むと、彼は同じエラーを受け取りました。

これは、資格情報を保存するために使用しているコードです。

$PathToFolderWithCredentials = "\\path\removed"

write-Host "Enter login as domain\login:"
read-Host | out-file $PathToFolderWithCredentials\login.txt

write-Host "Enter password:"
read-Host -assecurestring | convertfrom-securestring | out-file $PathToFolderWithCredentials\pass.txt

write-Host "*** Credentials have been saved to $pathtofolder ***"

これは、Invokeコマンドで使用する自動プロセスによって実行されるスクリプト内のコードです。

$login= get-content $PathToFolderWithCredentials\login.txt
$password = get-content $PathToFolderWithCredentials\pass.txt | convertto-securestring
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $login,$password

行$ password = get-content $ PathToFolderWithCredentials\pass.txtでエラーが発生します|安全な文字列に変換

何か案は?

26
mishkin

ConvertFrom-SecureStringは、Key(およびSecureKey)パラメーターを取ります。キーを指定して暗号化された標準文字列を保存し、ユーザーアカウントに関係なく、ConvertTo-SecureStringで再びキーを使用して安全な文字列を取得できます。

http://technet.Microsoft.com/en-us/library/dd315356.aspx

プロジェクトでは、公開鍵を使用してパスワードを暗号化し、自動化プロセスがパスワードを復号化する秘密鍵を使用する非対称暗号化を実装しました: 自動展開

23
manojlds

同じコンピューター上で、それを実行するために使用するのと同じログインでパスワード文字列を作成する必要があります。

21
Michele

別のアプローチは、ConvertFrom-SecureStringが使用する「CurrentUser」ではなく、「LocalMachine」スコープを使用してデータを保護することです。

public static string Protect(SecureString input, DataProtectionScope dataProtectionScope = DataProtectionScope.CurrentUser, byte[] optionalEntropy = null)
{
    byte[] data = SecureStringToByteArray(input);
    byte[] data2 = ProtectedData.Protect(data, optionalEntropy, dataProtectionScope);
    for (int i = 0; i < data.Length; i++)
    {
        data[i] = 0;
    }

    return ByteArrayToString(data2);
}
private static byte[] SecureStringToByteArray(SecureString s)
{
    var array = new byte[s.Length * 2];
    if (s.Length > 0)
    {
        IntPtr intPtr = Marshal.SecureStringToGlobalAllocUnicode(s);
        try
        {
            Marshal.Copy(intPtr, array, 0, array.Length);
        }
        finally
        {
            Marshal.FreeHGlobal(intPtr);
        }
    }

    return array;
}
private static string ByteArrayToString(byte[] data)
{
    var stringBuilder = new StringBuilder();
    for (int i = 0; i < data.Length; i++)
    {
        stringBuilder.Append(data[i].ToString("x2", CultureInfo.InvariantCulture));
    }

    return stringBuilder.ToString();
}

暗号化された文字列は、スコープ「CurrentUser」を使用しているConvertTo-SecureStringで使用できます。

1
wangzq

以下では、資格情報をファイルとして保存し、それらの資格情報を別のユーザーがリモートで実行する別のスクリプトで使用できるようにします。

このコードは、David Leeが作成した素晴らしい記事から引用したものであり、自分自身からのわずかな調整のみを行っています https://blog.kloud.com.au/2016/04/21/using-saved-credentials-securely- in-powershell-scripts /

最初のステップは、AESを使用して安全なパスワードをファイルに保存することです。以下は、スタンドアロンスクリプトとして実行されます。

            # Prompt you to enter the username and password
            $credObject = Get-Credential

            # The credObject now holds the password in a ‘securestring’ format
            $passwordSecureString = $credObject.password

            # Define a location to store the AESKey
            $AESKeyFilePath = “aeskey.txt”
            # Define a location to store the file that hosts the encrypted password
            $credentialFilePath = “credpassword.txt”

            # Generate a random AES Encryption Key.
            $AESKey = New-Object Byte[] 32
            [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey)

            # Store the AESKey into a file. This file should be protected! (e.g. ACL on the file to allow only select people to read)

            Set-Content $AESKeyFilePath $AESKey # Any existing AES Key file will be overwritten

            $password = $passwordSecureString | ConvertFrom-SecureString -Key $AESKey

            Add-Content $credentialFilePath $password

次に、資格情報を使用する必要があるスクリプトで、次を使用します。

            #set up path and user variables
            $AESKeyFilePath = “aeskey.txt” # location of the AESKey                
            $SecurePwdFilePath = “credpassword.txt” # location of the file that hosts the encrypted password                
            $userUPN = "domain\userName" # User account login 

            #use key and password to create local secure password
            $AESKey = Get-Content -Path $AESKeyFilePath 
            $pwdTxt = Get-Content -Path $SecurePwdFilePath
            $securePass = $pwdTxt | ConvertTo-SecureString -Key $AESKey

            #crete a new psCredential object with required username and password
            $adminCreds = New-Object System.Management.Automation.PSCredential($userUPN, $securePass)

            #use the $adminCreds for some task
            some-Task-that-needs-credentials -Credential $adminCreds

ユーザーがパスワードファイルとキーファイルにアクセスできる場合、ユーザーのパスワードを解読できることに注意してください。

1
Chris Horan

資格情報を使用するN人のユーザーの既知のリスト(1人の開発者userMeとシステム/サービスユーザーuserSys)があると仮定すると、 pass.txtファイル:各ユーザーに1つ。

したがって、userXのパスワードは、たとえば2 *.pass.txtファイル:

  • userX.userMe.pass.txt
  • userX.userSys.pass.txt

UserMeが信任状を望んでいるとき、彼/彼女はuserX.userMe.pass.txtなど.

0
Marc