Credentials (PowerShell)

From vWiki
Jump to navigation Jump to search


When running commands that require a connection to a remote machine its useful to be able to store a user/pass combination so that you aren't repeatedly prompted every time you run a command. Create a credential object, then supply that in place of a username in a command

PS H:\> $cred = Get-Credential

cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
PS H:\> Get-WMIObject -query "SELECT * FROM Win32_OperatingSystem" -credential $cred -computer

SystemDirectory : C:\WINDOWS\system32
Organization    : SandfordIT
BuildNumber     : 3790
RegisteredUser  : Me
SerialNumber    : 69712-640-3560061-45009
Version         : 5.2.3790

However, this doesn't really help much in a fully scripted situation where you need to supply user and pass in an unattended fashion, for that you also need the help of ConvertTo-SecureString , but if you want to be secure you need to use Store Password Securely


The following example creates a Credential object that can be used for in place of Get_Credential

$pass = ConvertTo-SecureString $svr.pass -asplaintext -force
$cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist $svr.user,$pass
$wmiobj = Get-WMIObject -query "SELECT * FROM Win32_BIOS" -credential $cred -computer $svr.ip

Store Password Securely

Adapted (a little) from by Brandon This is a two stage process, 1st you have to create a file with your (encrypted) password in (its encrypted by the currently logged in user - so if its going to be used in a scheduled task, make sure the user that will execute the script creates the password file).

$Credential = Get-Credential
$credential.Password | ConvertFrom-SecureString | Set-Content "Pass.fil"

Then you can use this in a script, the $cred is a standard credential object.

$pass = Get-Content "Cred.fil" | ConvertTo-SecureString 
$cred = New-Object System.Management.Automation.PsCredential("DOMAIN\user",$pass)

For a complete, but simple user/pass caching system use something like the following. I use this script to create a local user/pass file which gets used whenever I need to provide credentials in a script.

$UserFile = "User.fil"
$PassFile = "Pass.fil"  

# Check for credential files, create if required
if (!(Test-Path $UserFile) -or !(Test-Path $PassFile)) {
    Write-Host "Credential files not found"
    $cred = Get-Credential -Credential ($env:userdomain + "\" + $env:username)
    $cred.UserName | Set-Content $UserFile -Force
    $cred.Password | ConvertFrom-SecureString | Set-Content $PassFile -Force
    Write-Host "Credentials saved"
# Load password credential from encrypted file
$pass = Get-Content $PassFile | ConvertTo-SecureString
$user = Get-Content $UserFile
$cred = New-Object System.Management.Automation.PsCredential($user, $pass)

...obviously to make the above more useful you'd test that the user/pass combo supplied was correct prior to saving to file.

ConvertTo-SecureString : Key not valid for use in specified state

This is the error you get if you try to decrypt the contents of your password file using a user account other than that which was used to encrypt it.

The password file must be created/encrypted as the same logged in user as the account under which the script will run. Therefore if your script will be running from a scheduled task, run from a server using a service account, you must be logged onto the that machine with the service account when you create the file.

Convert SecureString To Plain Text

To decrypt a secure string use the following (this must be run from the same user session used to encrypt the string)

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($EncryptPass)

Logged-In User's Credentials

To use the credentials of the existing logged in session where a CmdLet requires that you specify them use the following...

$cred = [System.Net.CredentialCache]::DefaultCredentials