#PSTip Storing of credentials

I frequently use different credentials to connect to some of my servers. Oh man, I wish I have just one account J As Configuration Manager is based on WMI, my most frequently used cmdlet is Get-WmiObject. And I use its Credential parameter to pass credentials I need for specific server. You can save your credentials to a variable by using the Get-Credential cmdlet.

PS> $cred = Get-Credential domain\makovec

But after some time it’s boring to do this every time I start my session. So, I am saving my credentials to a file and load it in $profile. I have three functions for working with credentials.

  1. New-DMCredential – creates a new file with credentials stored inside.
  2. Get-DMCredential – load credentials from a file (and then save it to a variable).
  3. Show-DMCredential – ehh, sometimes I forgot current password (especially after holiday). This one shows me password in clear text.

I got this idea of storing it this way from Lee Holmes’s PowerShell Cookbook. I’ve just written a function around his code. You can see dDM alias used in the following examples. This alias is used as a file name for stored credentials (used as output of New-DMCredential function and input of Get-DMCredential). The name of variable holding credential object is also based on this alias name.

PS> New-DMCredential -UserName domain\makovec -Alias dDM

It creates file with credentials. To be clear – the file doesn’t contain data in a clear text. It’s encrypted using Data Protection API.

I can use this stored credentials to assign them to a variable (this is the line I have in my $profile):

PS> Get-DMCredential -UserName domain\makovec -Alias dDM

When I want to connect to one of my servers I can use this variable:

PS> Connect-ConfigMgrProvider -ComputerName MyServer -Credential $dDM

Or I can see my password when needed:

PS> Show-DMCredential $dDM
Pa$$w0rd

Here are the functions I use. I’ve commented it inline.

function New-DMCredential
{
    [CmdletBinding()]
    param(
        [Parameter(
            Mandatory = $true,
            Position = 0
        )]
        [string]$UserName,
        [Parameter(
            Mandatory = $true,
            Position = 1
        )]
        [string]$Alias
    )

    # Where the credentials will be stored
    $path = 'c:\Scripts\Resources\cred\'

    # get credentials for given username
    $cred = Get-Credential $UserName

    # and save encrypted text to a file
    $cred.Password | ConvertFrom-SecureString | Set-Content -Path ("$path\$Alias")
}

function Get-DMCredential
{
    [CmdletBinding()]
    param(
        [Parameter(
            Mandatory = $true,
            Position = 0
        )]
        [string]$UserName,
        [Parameter(
            Mandatory = $true,
            Position = 1
        )]
        [string]$Alias
    )

    # where to load credentials from
    $path = 'c:\Scripts\Resources\cred\'

    # receive cred as a PSCredential object
    $pwd = Get-Content -Path ("$path\$Alias") | ConvertTo-SecureString
    $cred = New-Object System.Management.Automation.PSCredential $UserName, $pwd

    # assign a cred to a global variable based on input
    Invoke-Expression "`$Global:$($Alias) = `$cred"
    Remove-Variable -Name cred
    Remove-Variable -Name pwd
}
}

function Show-DMCredential
{
    param($cred)
    # Just to see password in clear text
        [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($cred.Password))
}

I can probably change this script to module and make it a bit more user friendly. I will do that soon. At the moment–you can do that as your homework :).

Share on:
comments powered by Disqus