From 7122c2afa432b19d3c16ec5b19abdfd168d7594a Mon Sep 17 00:00:00 2001 From: OCram85 Date: Thu, 27 Jul 2017 15:43:37 +0200 Subject: [PATCH] adds store related functions --- src/Store/Get-CredentialStore.ps1 | 69 ++++++++++++++++++ src/Store/New-CredentialStore.ps1 | 111 +++++++++++++++++++++++++++++ src/Store/Test-CredentialStore.ps1 | 61 ++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 src/Store/Get-CredentialStore.ps1 create mode 100644 src/Store/New-CredentialStore.ps1 create mode 100644 src/Store/Test-CredentialStore.ps1 diff --git a/src/Store/Get-CredentialStore.ps1 b/src/Store/Get-CredentialStore.ps1 new file mode 100644 index 0000000..8828d92 --- /dev/null +++ b/src/Store/Get-CredentialStore.ps1 @@ -0,0 +1,69 @@ +function Get-CredentialStore { + <# + .SYNOPSIS + Reads the complete content of the credential store and returns it as a new object. + + .DESCRIPTION + The content is in a raw format. It means there is no transformation to the different credential types. + You can not use the object properties to connect with remote host. Therefore please use + Get-CredentialStoreItem. + + .PARAMETER Path + Define a custom path to a shared CredentialStore. + + .PARAMETER Shared + Switch to shared mode with this param. This enforces the command to work with a shared CredentialStore which + can be decrypted across systems. + + .INPUTS + [None] + + .OUTPUTS + [PSObject] Returns the credential store content as PSObject. + + .EXAMPLE + $CSContent = Get-CredentialStore -Path "C:\TMP\mystore.json" + + .NOTES + File Name : Get-CredentialStore.ps1 + Author : Marco Blessing - marco.blessing@googlemail.com + Requires : + + .LINK + https://github.com/OCram85/PSCredentialStore + #> + + [CmdletBinding(DefaultParameterSetName = "Private")] + param( + [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData, + + [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [switch]$Shared + ) + + if ($PSCmdlet.ParameterSetName -eq 'Private') { + $Path = "{0}\CredentialStore.json" -f $env:APPDATA + } + + if (Test-CredentialStore -Path $Path) { + try { + $FileContent = Get-Content -Path $Path -Raw + ConvertFrom-Json $FileContent + } + catch [System.Exception] { + $MessageParams = @{ + Message = "Unknown CredentialStore format. Invalid JSON file." + ErrorAction = "Stop" + } + Write-Error @MessageParams + } + } + else { + $MessageParams = @{ + Message = "Could not find the CredentialStore." + ErrorAction = "Stop" + } + Write-Error @MessageParams + } +} diff --git a/src/Store/New-CredentialStore.ps1 b/src/Store/New-CredentialStore.ps1 new file mode 100644 index 0000000..3aa3398 --- /dev/null +++ b/src/Store/New-CredentialStore.ps1 @@ -0,0 +1,111 @@ +function New-CredentialStore { + <# + .SYNOPSIS + Creates a new credential store File + + .DESCRIPTION + You need to run this script first to create a new credential store before you try to + save new credentials with New-CredentialStoreItem. + + .PARAMETER Path + Define a location for the new shared CredentialStore. The default store will be created in + $Env:ProgramData\PSCredentialStore dir. + + .PARAMETER Shared + Creates a CredentialStore in the Shared mode. This enables you to read the CredentialStore Items on + different systems or profiles. In addition you can optionally provide a custom path wit the -Path parameter. + + .PARAMETER Force + Use this switch to reset an existing store. The complete content will be wiped. + + .INPUTS + [None] + + .OUTPUTS + [None] + + .EXAMPLE + New-CredentialStore + # Creates a new private CredentialStore + + .EXAMPLE + New-CredentialStore -Force + # Resets an existing private CredentialStore + + .EXAMPLE + New-CredentialStore -Shared + # Creates a new shead CredentialStore + + .EXAMPLE + New-CredentialStore -Shared -Path "C:\TMP\CredentialStore.json" + # Creates a new shared CredentialStore in the given location. + + .NOTES + File Name : New-CredentialStore.ps1 + Author : Marco Blessing - marco.blessing@googlemail.com + Requires : + + .LINK + https://github.com/OCram85/PSCredentialStore + #> + + [CmdletBinding(DefaultParameterSetName = "Private")] + param( + [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [switch]$Shared, + + [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [ValidateNotNullOrEmpty()] + [string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData, + + [Parameter(Mandatory = $false, ParameterSetName = "Private")] + [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [switch]$Force + ) + + # Lets get the current Date in a human readable format. + $CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" + + # Set latest Credential Store version + Set-Variable -Name "CSVersion" -Value "1.2.0" -Option Constant + + # Set the CredentialStore path for private mode. + Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) + if ($PSCmdlet.ParameterSetName -eq "Private") { + $Path = "{0}\CredentialStore.json" -f $Env:APPDATA + } + + # Test if in the given store already a CredentialStore exists. + Write-Verbose "Test if there is already a credential store." + if ((Test-CredentialStore -Path $Path) -and ($Force -ne $true)) { + $MessageParam = @{ + Message = "The given file already exists. Use the 'Force' switch to override the existing store." + ErrorAction = "Stop" + } + Write-Error @MessageParam + } + # We need to use the IDictionary to keep the property sorting in the object. + $ObjProperties = [ordered]@{ + Version = $CSVersion + Creation = $CurrentDate + } + if ($PSCmdlet.ParameterSetName -eq "Shared") { + $ObjProperties.Type = "Shared" + # Check if a ChallengeFile already exists. We don't want to overide it. + # Otherwise previous created CredentialStores couln't be decrypted anymore. + if (-not (Test-ChallengeFile)) { + Set-ChallengeFile + } + } + else { + $ObjProperties.Type = "Private" + } + # Create a new object for easy conversion into a json file + $CredentialStoreObj = New-Object -TypeName psobject -Property $ObjProperties + try { + ConvertTo-Json -InputObject $CredentialStoreObj | Out-File -FilePath $Path + } + catch [System.Exception] { + $_.Exception | Format-List -Force | Out-String | Write-Error -ErrorAction Stop + } +} diff --git a/src/Store/Test-CredentialStore.ps1 b/src/Store/Test-CredentialStore.ps1 new file mode 100644 index 0000000..cf72109 --- /dev/null +++ b/src/Store/Test-CredentialStore.ps1 @@ -0,0 +1,61 @@ +function Test-CredentialStore { + <# + .SYNOPSIS + Returns the credential store state. + + .DESCRIPTION + Use this script to test your credential store. For now it only checks if + the file exists. + + .PARAMETER Path + Define a custom path to a shared CredentialStore. + + .PARAMETER Shared + Switch to shared mode with this param. This enforces the command to work with a shared CredentialStore which + can be decrypted across systems. + + .NOTES + File Name : Test-CredentialStore.ps1 + Author : Marco Blessing - marco.blessing@googlemail.com + Requires : + + .LINK + https://github.com/OCram85/PSCredentialStore + #> + [CmdletBinding(DefaultParameterSetName = "Private")] + param( + [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData, + + [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [switch]$Shared + ) + + + if ($PSCmdlet.ParameterSetName -eq "Private") { + $Path = "{0}\CredentialStore.json" -f $Env:APPDATA + } + + # Set latest Credential Store version + Set-Variable -Name "CSVersion" -Value "1.2.0" -Option Constant + + if (Test-Path $Path) { + Write-Verbose "CredentialStore in given path found." + + # try tor read the store. Removed the Get-CredentialStore function to avoid recursive calls. + try { + $FileContent = Get-Content -Path $Path -Raw + $CSContent = ConvertFrom-Json $FileContent + } + catch { + Write-Warning "Could not read or convert the given CredentialStore." + Return $False + } + Return $True + + } + Else { + Write-Verbose "The given CredentialStore does not exist!" + Return $False + } +}