Git Product home page Git Product logo

bettercredentials's Introduction

The Better Credentials Module

The goal of BetterCredentials is to provide a completely backwards-compatible Get-Credential command that enhances the in-the-box Get-Credential by adding additional features which are missing from the built-in command. Specifically, storing credentials for automation, and providing more complete prompts with an explanation of what the credentials are for.

TO INSTALL:

Use the PowerShellGet module included in WMF (PowerShell) 5, or the PackageManagement Preview for PowerShell 3 and 4.

Just run:

    Install-Module BetterCredentials -AllowClobber

The -AllowClobber switch is to allow the BetterCredentials module to do what it's designed to do: provide you a better, backwards compatible Get-Credential command, clobbering the built-in version.

Features

Prompting

The original motivation for writing BetterCredentials was to take advantage of some of the features of PowerShell's underlying credential API which are inexplicably ignored in the built-in Get-Credential, particularly to allow one-off prompting for passwords inline (that is, in the console, instead of via the credentials dialog), without having to resort to a configuration change.

You can use the -Inline switch to force prompting in the host instead of with a popup dialog, or even pass in a -Password value (secure string or not, I won't judge) which allows you to easily create credential objects without a prompt at all.

Additionally, you can set the -Title parameter to control the text that's show at the top of the prompt window, and even set the -Description parameter to add text in the prompt.

Storage

Despite the fact that this feature arrived late in the life of BetterCredentials, clearly the best feature is the fact that it can store your passwords in the Windows Credential Manager (sometimes called the Vault), and retrive them on demand so you don't have to enter them over and over. The Windows Credential Manager is what's used by Internet Explorer and Remote Desktop to store passwords, and it keeps them safely encrypted to your account and machine, and provides a user interface where they can be securely reviewed, deleted or even modified.

On our BetterCredentials\Get-Credential command, the -Store switch causes the returned credentials to be stored in the vault, and the -Delete switch makes sure they are not. As of version 4.5, you can also use the Set-Credential and Remove-Credental commands to explicitly store or remove credentials.

Once you've stored credentials in the vault, future requests for the same credential -- where you pass in a username (and optionally, a domain) will simply return the credentials without prompting. Because of this, there is also a -Force switch (alias: -New) which prevents loading and forces the prompt to be displayed. When you need to change a stored password, use both together:

BetterCredentials\Get-Credential -Force -Store

Additionally, in 4.5 there are two commands for searching and/or testing for credentials in the vault: Find-Credential and Test-Credential...

Unattended Usage

When Get-Credential is called from a script running unattended, e.g. in a scheduled task, script execution will hang prompting for credentials if there is no credential in the vault corresponding to the given username. Normally one might execute Get-Credential username -Store to populate the credential vault prior to putting the scheduled task into production, but might also forget to do so. In version 4.5 the new Test-Credential command solves the script hanging problem by returning a true or false value depending on whether a credential corresponding to a user name is currently stored in the vault.

NOTES

In my scripts and sample code, I nearly always use BetterCredentials\Get-Credential as a way to make sure that I'm invoking this overload of Get-Credential, but the idea is that you can simply import the BetterCredentials module in your profile and automatically get this overload whenever you're calling Get-Credential. Of course, I haven't (yet) overloaded the [Credential] transform attribute, so the automatic prompting when you pass a user name to a -Credential attribute doesn't use my module -- you have to explicitly call Get-Credential.

Licensed under MIT license, see License.

bettercredentials's People

Contributors

jaspain avatar jaykul avatar juneb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bettercredentials's Issues

Test-Credential not exported

Looks like in the version of the module on the PSGallery, the Test-Credential function is not exported. In the GH repo it is, and both have the same module version number:
untitled

Possibly allow a validation of credentials when retrieved, possibly by a switch

Like many admins I use very long secure credentials, which are subject to all kinds of typo errors. I'd like to see a switch added to Get-Credential that would validate a credential that was inputted.

I created this function to validate credentials when they are entered (and I use it day to day for this type of functionality). It leverages the AccountManagement namespace as described Richard Siddaway's blog post: https://richardspowershellblog.wordpress.com/2008/05/25/system-directoryservices-accountmanagement/. I'd like to see the functionality added in.

Here is my function:

Function Get-ValidatedCredential
{
    <#
        .SYNOPSIS
		Retrieves a credential from the user with the standard Windows dialog, and
		then it validates that the password is correct for the account.
        .DESCRIPTION
		Uses the standard dialog with the option to customize the title, the prompt text, and
		to prefill a domain name and user name.  The credential is then tested against the 			 
                domain to validate that the password is correct. If it is not, the user is prompted again.
		The user does have the option to click Cancel and exit this function.
        .PARAMETER DomainName
		The domain name of the user to validate
        .PARAMETER DomainUser
		The username (sAMAccountName) of the user to validate
        .PARAMETER DialogTitle
		The title of the dialog presented to request credentials
        .PARAMETER DialogPrompt
		The prompt of the dialog presented to request credentials
        .EXAMPLE
		PS C:\> Get-ValidatedCredential -DomainName $env:USERDOMAIN -DomainUser MyServiceAccount -DialogTitle 'Enter credentials' -DialogPrompt 'Enter the credentials for the service account to use'
        .NOTES
                This script is based on Richard Siddaway's blog about the System.DirectoryServices.AccountManagement namespace. 
                https://richardspowershellblog.wordpress.com/2008/05/25/system-directoryservices-accountmanagement/
        .INPUTS
                [system.string]
        .OUTPUTS
                [pscredential]
        #>
	[cmdletbinding()]
	param(
		[parameter(Mandatory = $true, HelpMessage='The domain name of the account to be validated', ValueFromPipelineByPropertyName = $true)]
		[string]$DomainName,

		[parameter(Mandatory = $true, HelpMessage = 'The user name of the account to be validated', ValueFromPipelineByPropertyName = $true)]
		[string]$DomainUser,

		[parameter(ValueFromPipelineByPropertyName = $true)]
		[string]$DialogTitle = 'Enter credentials',

		[parameter(ValueFromPipelineByPropertyName = $true)]
		[string]$DialogPrompt = 'Enter the credentials to be validated'
	)

	$MyName = $MyInvocation.InvocationName
	Write-Verbose -Message ('[{0}] Starting {1}' -f [DateTime]::Now, $MyName)
	
	Add-Type -AssemblyName System.DirectoryServices.AccountManagement 

	$HaveValidCredentials = $false
	do
	{
		$Credential = $Host.UI.PromptForCredential($DialogTitle, $DialogPrompt, ('{0}\{1}' -f $DomainName, $DomainUser), $DomainName)
		if ($Credential -eq $null)
		{
			#Throw 'User clicked cancel, exiting the script'
			Write-Verbose -Message ('[{0}] Cancel was clicked, exiting this function quietly' -f $MyName)
			if (Test-Path -Path variable:\Context)
			{
				$Context.Dispose()
			}
			return $null 
		}
		$Context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList ([System.DirectoryServices.AccountManagement.ContextType]::Domain, $DomainName)
		if ($Context.ValidateCredentials($DomainUser, $Credential.GetNetworkCredential().Password))
		{
			$HaveValidCredentials = $true
			Write-Verbose -Message ('[{0}] Current provided credentials are valid, and password is correct, continuing with the installation' -f $MyName)
		}
	}
	until ($HaveValidCredentials)
	$Context.Dispose()
	$Credential
}

Pushing 4.5 to PSGallery

Was hoping you could push 4.5 to psgallery. I'm fixing my local repo, but I feel bad creating a repo and pushing this internal if you are maintaining it externally.

Thanks!

PowerShell 5.1 installation requires -AllowClobber flag

Example:

PS C:\Users\cknox> install-module bettercredentials -Scope CurrentUser
PackageManagement\Install-Package : A command with name 'Get-Credential' is already available on this system. This
module 'BetterCredentials' may override the existing commands. If you still want to install this module
'BetterCredentials', use -AllowClobber parameter.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1661 char:21
+ ...          $null = PackageManagement\Install-Package @PSBoundParameters
+                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (Microsoft.Power....InstallPackage:InstallPackage) [Install-Package],
   Exception
    + FullyQualifiedErrorId : CommandAlreadyAvailable,Validate-ModuleCommandAlreadyAvailable,Microsoft.PowerShell.Pack
   ageManagement.Cmdlets.InstallPackage

Test-Credential throws exception

Test-Credential and Find-Credential don’t work as expected. The problem lies with the Find function in CredentialManagement.cs. Because CredWrite alters the names of credentials, you are using the function FixTarget to make this alteration transparent when credentials are retrieved. Thus FixTarget needs to be applied to the filter argument of the Find function to make that transparent as well.

Also in the Find function CredEnumerate returns false when it fails. In addition to some exception-worthy problems, the failure may be due to there being no credentials that pass the filter (ERROR_NOT_FOUND). In the case of ERROR_NOT_FOUND, the Find function should return a null result rather than throwing an exception.

In my pull request, I am proposing changes to the Find function, and based on these changes I also added some additional examples for Test-Credential and Find-Credential.

A path forward for cross-platform

In order to support PowerShell Core on platforms other than Windows, it's necessary to abstract the credential storage part of this module out into something where we can plug in different solutions on different platforms. For instance:

  • Windows Credential Vault
  • MacOS Keychain
  • Linux D-Bus secret service, or pass

Something like Docker's Credential Helpers seems to be the best approach, although we can't just use theirs, because their plugins and client library are written in Go, which doesn't really interop with ... anything.

Store credentials by something else than the username

Hi,

I really like your module, but there is one thing that is missing for me.

Is there a way to store (and get) credentials by title/website? I found the parameter Target in Set-Credential. How do I get it (based on the target)?

I use my username on multiple services, but with different password.

I could maybe use DOMAIN for the website/service, but it's not that beautiful. I'd have to remove the domain before using the credential.

Thank you a lot

Get-Credential throws exception when credential not already stored

Get-Credential is trying to load a credential object even if it's not been stored yet. This causes an exception to be thrown.

May be related to #9 as well.

If we wrap module Line 351 with setting ErrorActionPreference to SilentlyContinue it seems that this would resolve it.

Alternately I imagine changing the CredentialManagement.Store class function Load() to not throw an exception on line 198 might be the more elegant solution.

Support -Target in Get-Credential

In Set-Credential you can specify the -target attribute, it would be nice to support -target in Get-Credential as well.

This would allow setting the target as some short name, and allow easy get requests of the short target name vs username. Mainly for use from CLI.

For example I may want to request the credentials for a client Office 365 login with a username of
[email protected] but would set the target to compa and be able to easy recall it with get-credential -target compa

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.