I need to start this post with an all credits for this module goes toScott Thomas, he created the original. I simply saw it, asked if I could use it, found out about an intellectual property piece that prevented me from taking it with me, and reverse engineered it based on how it worked previously. I did add a bit of functionality to it though, so there is that. With that out of the way, let’s do some scripting!

Have you ever wished you could connect to a remote server and not have to worry about entering your credentials each time? Do you have a script that requires additional authentication but you don’t want to get prompted for it? Do badgers occasionally attempt to consume your lunch meat while you aren’t looking?

If you answered yes to any of these (Especially the badgers) then have I got the module for you! CredManager is a module that will store your credentials in your registry in the current user hive, and then convert the strings back into credentials for you…

Now I know, you are saying to yourself, “Nic… Why is this that great even??? I mean, that isn’t really that special, and how is this going to help me with the damn badger problem???”

To this I say, “FEAR NOT CITIZEN! For I’ve also included a handy set of functions for testing and changing those credentials! Let’s see those pesky badgers get your lunch now that you can automate your credential prompts!”

So the module has four functions associated with it:

Get-SavedCreds
Test-SavedCreds
New-SavedCreds
Set-SavedCreds

All of them take the argument of -CredType which allows you to specify a string to call upon the credential. If you think this is confusing, you should see the look on the badger! But again fear not, I’ll show you an example of it in practice.

Test-SavedCreds has an extra argument that is just a switch, -Office365. By setting this flag, you will test your credentials against O365 instead of your local AD.

And a last point, if you are using this and you cannot talk to your local AD (And not testing for Office 365 credentials) It will FAIL. So don’t use this in a DMZ. (The test portion at least, which makes the whole module a little less cool.)

So I’ll start with the script itself! (And also I’ve included a v1.0.zip at the end of this post. You can just copy that to the %systemroot%\System32\WindowsPowerShell\ directory and merge the folders. It just added a module in the modules folder called CredManager.)

function New-SavedCreds {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true)]
        [string]$CredType
    )
    if ((Test-Path -Path HKCU:\System\CurrentControlSet\SecCreds) -eq $false) {
        New-Item -Path HKCU:\System\CurrentControlSet\SecCreds
    }
    New-Item -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType)
    $cred = Get-Credential
    New-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name UserName -Value $cred.UserName
    $pass = $cred.Password | ConvertFrom-SecureString 
    New-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name Password -Value $pass
}


function Get-SavedCreds {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $false)]
        [string]$CredType
    )
    if ($CredType) {
        $test = Test-Path -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType)
        if ($test) {
            $userName = (Get-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name UserName).UserName
            $password = (Get-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name Password).password | ConvertTo-SecureString
            $cred = New-Object System.Management.Automation.PSCredential $userName, $password
            return $cred
        }
        else {
            Write-Host -ForegroundColor Red "Credentials not found on machine."
        }
    }
    else {
        $RegCreds = (Get-ChildItem -Path HKCU:\System\CurrentControlSet\SecCreds\).PsChildName
        foreach ($RegCred in $RegCreds) {
            Write-Host -ForegroundColor Green "$RegCred found in your user profile."
        }
    }
}

function Test-SavedCreds {
    Param(
        [Parameter(Mandatory = $true, Valuefrompipeline = $true)]
        [string]$CredType,
        [Parameter(Mandatory = $false)]
        [switch]$Office365
    )
    $test = Test-Path -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType)
    if ($test) {
        $userName = (Get-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name UserName).UserName
        $password = (Get-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name Password).password | ConvertTo-SecureString
        $cred = New-Object System.Management.Automation.PSCredential $userName, $password
        if ($Office365) {
            $ErrorActionPreference = 'silentlycontinue'
            $testSess = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $cred -Authentication Basic -AllowRedirection
            $ErrorActionPreference = 'continue'
            if ($testSess) {
                Remove-PSSession $testSess
                return $true
            }
            else {
                return $false
            }
        }
        else {
            $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
            $domainCount = $userName.IndexOf('\') + 1
            $userNameTrim = $userName.Substring($domainCount)
            $password = $cred.GetNetworkCredential().Password
            $domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain, $UserNameTrim, $Password)
            if ($domain.Name -eq $null) {
                return $false
            }
            else {
                return $true
            }
        }
    }
    else {
        return $false
    }
}

function Set-SavedCreds {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true, Valuefrompipeline = $true)]
        [string]$CredType
    )
    $test = Test-Path -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType)
    if ($test) {
        $cred = Get-Credential
        if ($cred) {
            Set-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name UserName -Value $cred.UserName
            $pass = $cred.Password | ConvertFrom-SecureString
            Set-ItemProperty -Path HKCU:\System\CurrentControlSet\SecCreds\$($CredType) -Name Password -Value $pass
        }
    }
}

Now, this will allow you to set your credentials and play with them. The biggest key here is the test-savedCreds which will return either a $true or $false based on if it authenticated properly.

As I promised! An example of it’s use in a script: My Connect-Office365 script:

Write-Host -ForegroundColor Yellow `
    " ############################
 ## Cmdlets Added          ##
 ## Connect-Office365      ##
 ############################
 ############################"
Import-Module CredManager
function Connect-Office365 {
    $testCred = Test-SavedCreds -CredType O365 -Office365
    if ($testCred -eq $true) {
        $creds = Get-SavedCreds -CredType O365
        $Session365 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $creds -Authentication Basic -AllowRedirection
        Import-PSSession $Session365
        $host.UI.RawUI.BackgroundColor = "Black"
        $host.UI.RawUI.ForegroundColor = "Gray"
        cls
    }
    else {
        $testPath = Test-Path HKCU:\System\CurrentControlSet\SecCreds\O365
        while ($testCred -eq $false) {
            if ($testPath -eq $true) {
                Set-SavedCreds -CredType O365
                $testCred = Test-SavedCreds -CredType O365 -Office365
            }
            else {
                New-SavedCreds -CredType O365
                $testCred = Test-SavedCreds -CredType O365 -Office365
                $testPath = Test-Path HKCU:\System\CurrentControlSet\SecCreds\O365
            }
        }
        Connect-Office365
    }
}

Now some key points here. First I attempt to test the credentials with the $testCreds = Test-SavedCreds. If this returns true, just load the credentials up into a variable and connect away!

If it returns false, the next step is to test the path to where I would have the creds. (This is only important the first time, because we need to use the New-SavedCreds on initial use to create the keys.) Then it will continue to test the credentials, if they show up as a failure it will prompt you again. (In case that badger’s shenanigans caused you to misstype your password the first 15 times.)

As promised: A download Link for v1.0.zip

Leave a Reply

Your email address will not be published. Required fields are marked *