web-dev-qa-db-fra.com

Enregistrement des informations d'identification pour une utilisation ultérieure par powershell et l'erreur ConvertTo-SecureString: Clé non valide pour une utilisation dans l'état spécifié

Je faisais quelque chose comme décrit dans cet article pour enregistrer les informations d'identification dans un fichier sécurisé afin que notre processus automatisé puisse l'utiliser pour exécuter des scripts PS distants via la commande Invoke: http://blogs.technet.com/b/ robcost/archive/2008/05/01/powershell-tip-storing-and-using-password-credentials.aspx

Cela fonctionne très bien lorsque je lance ceci sous mon compte - le mot de passe est lu à partir d'un fichier crypté, transmis à Invoke-command et tout va bien.

Aujourd'hui, lorsque mon script était prêt pour les heures de pointe, j'ai essayé de l'exécuter sous un compte Windows qui sera utilisé par un processus automatisé. Cette erreur s'est produite ci-dessous alors que mon script tentait de lire un mot de passe sécurisé à partir d'un fichier:

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

A demandé à mon collègue de courir sous son compte et il a eu la même erreur.

C'est le code que j'utilise pour sauvegarder les informations d'identification:

$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 ***"

C'est le code dans le script à exécuter par un processus automatisé pour les lire à utiliser dans la commande 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

Une erreur se produit sur la ligne $ password = get-content $ PathToFolderWithCredentials\pass.txt | convertto-securestring

Des idées?

26
mishkin

ConvertFrom-SecureString prend un paramètre Key (et SecureKey). Vous pouvez spécifier la clé pour enregistrer la chaîne standard cryptée, puis la réutiliser dans ConvertTo-SecureString pour récupérer la chaîne sécurisée, quel que soit le compte de l'utilisateur.

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

Dans un projet, j'ai implémenté le cryptage asymétrique, dans lequel les utilisateurs cryptent le mot de passe à l'aide de la clé publique et le processus d'automatisation dispose de la clé privée pour décrypter les mots de passe: Gestion des mots de passe dans la configuration de production pour un déploiement automatisé

23
manojlds

Vous devez créer la chaîne de mot de passe sur le même ordinateur et avec le même identifiant que vous utiliserez pour l’exécuter. 

19
Michele

Une autre approche serait de protéger les données en utilisant la portée "LocalMachine" au lieu de "CurrentUser" qui est celle utilisée par ConvertFrom-SecureString.

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();
}

La chaîne cryptée peut être utilisée par ConvertTo-SecureString qui utilise la portée "CurrentUser".

1
wangzq

La procédure ci-dessous permet d’enregistrer les informations d’identité sous forme de fichier, puis de les utiliser pour un autre script exécuté par un autre utilisateur, à distance. 

Le code est tiré d'un excellent article produit par David Lee, avec seulement quelques ajustements mineurs de moi-même https://blog.kloud.com.au/2016/04/21/using-saved-credentials-securely-in- powershell-scripts/

La première étape consiste à enregistrer un mot de passe sécurisé dans un fichier à l'aide d'AES. Le ci-dessous fonctionnera comme un script autonome:

            # 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

Ensuite, dans votre script, où vous devez utiliser des informations d'identification, utilisez les éléments suivants: 

            #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

Sachez que si l'utilisateur peut accéder au fichier de mot de passe et au fichier de clé, il peut déchiffrer le mot de passe de l'utilisateur.

0
Chris Horan