Skip to content

Commit

Permalink
!deploy v2.22.0 - enhanced PSGSuiteConfig management and portability
Browse files Browse the repository at this point in the history
## 2.22.0

* Miscellaneous: _Config management and portability updates_
  * Added: `Export-PSGSuiteConfig` function to export key parts of your config in a transportable JSON file.
  * Added: `Import-PSGSuiteConfig` function to import a config from a JSON file (i.e. one created with `Export-PSGSuiteConfig`) or from a JSON string (i.e. stored in a secure variable in a CI/CD system.)
  * Updated: All config functions now store the P12Key or the ClientSecrets JSON string in the encrypted config directly. This is to allow removal of the secrets files as well as enable PSGSuite to run in a contained environment via importing the config from a secure JSON string.
  * Updated: `[Get|Set|Switch]-PSGSuiteConfig` to include the P12Key and ClientSecrets parameters that enable housing of the key/secret directly on the encrypted config.
  * Updated: If the global PSGSuite variable `$global:PSGSuite` exists during module import, it will default to using that as it's configuration, otherwise it will import the default config if set.
  • Loading branch information
scrthq authored Dec 27, 2018
2 parents ac1a0c5 + 0ccb071 commit 08b7958
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ FunctionBackups/*
BuildOutput/*
*config.csv
PSGSuite.zip
PSGSuite*.json
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

* [Changelog](#changelog)
* [2.22.0](#2220)
* [2.21.3](#2213)
* [2.21.2](#2212)
* [2.21.1](#2211)
Expand Down Expand Up @@ -68,6 +69,15 @@

***

## 2.22.0

* Miscellaneous: _Config management and portability updates_
* Added: `Export-PSGSuiteConfig` function to export key parts of your config in a transportable JSON file.
* Added: `Import-PSGSuiteConfig` function to import a config from a JSON file (i.e. one created with `Export-PSGSuiteConfig`) or from a JSON string (i.e. stored in a secure variable in a CI/CD system.)
* Updated: All config functions now store the P12Key or the ClientSecrets JSON string in the encrypted config directly. This is to allow removal of the secrets files as well as enable PSGSuite to run in a contained environment via importing the config from a secure JSON string.
* Updated: `[Get|Set|Switch]-PSGSuiteConfig` to include the P12Key and ClientSecrets parameters that enable housing of the key/secret directly on the encrypted config.
* Updated: If the global PSGSuite variable `$global:PSGSuite` exists during module import, it will default to using that as it's configuration, otherwise it will import the default config if set.

## 2.21.3

* [Issue #131](https://github.com/scrthq/PSGSuite/issues/131)
Expand Down
2 changes: 1 addition & 1 deletion PSGSuite/PSGSuite.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
RootModule = 'PSGSuite.psm1'

# Version number of this module.
ModuleVersion = '2.21.3'
ModuleVersion = '2.22.0'

# ID used to uniquely identify this module
GUID = '9d751152-e83e-40bb-a6db-4c329092aaec'
Expand Down
12 changes: 8 additions & 4 deletions PSGSuite/Public/Authentication/New-GoogleService.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ function New-GoogleService {
$User = $script:PSGSuite.AdminEmail
)
Process {
if ($script:PSGSuite.P12KeyPath) {
if ($script:PSGSuite.P12KeyPath -or $script:PSGSuite.P12Key) {
try {
Write-Verbose "Building ServiceAccountCredential from P12Key as user '$User'"
$certificate = New-Object 'System.Security.Cryptography.X509Certificates.X509Certificate2' -ArgumentList (Resolve-Path $script:PSGSuite.P12KeyPath),"notasecret",([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
if (-not $script:PSGSuite.P12Key) {
$script:PSGSuite.P12Key = ([System.IO.File]::ReadAllBytes($script:PSGSuite.P12KeyPath))
Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -P12Key $script:PSGSuite.P12Key -Verbose:$false
}
$certificate = New-Object 'System.Security.Cryptography.X509Certificates.X509Certificate2' -ArgumentList ([System.Byte[]]$script:PSGSuite.P12Key),"notasecret",([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$credential = New-Object 'Google.Apis.Auth.OAuth2.ServiceAccountCredential' (New-Object 'Google.Apis.Auth.OAuth2.ServiceAccountCredential+Initializer' $script:PSGSuite.AppEmail -Property @{
User = $User
Scopes = [string[]]$Scope
Expand All @@ -41,8 +45,8 @@ function New-GoogleService {
'https://www.googleapis.com/auth/tasks.readonly'
)
if (-not $script:PSGSuite.ClientSecrets) {
$script:PSGSuite.ClientSecrets = (Get-Content $script:PSGSuite.ClientSecretsPath -Raw)
Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -ClientSecretsPath $script:PSGSuite.ClientSecretsPath -Verbose:$false
$script:PSGSuite.ClientSecrets = ([System.IO.File]::ReadAllText($script:PSGSuite.ClientSecretsPath))
Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -ClientSecrets $script:PSGSuite.ClientSecrets -Verbose:$false
}
$credPath = Join-Path (Resolve-Path (Join-Path "~" ".scrthq")) "PSGSuite"
Write-Verbose "Building UserCredentials from ClientSecrets as user '$User' and prompting for authorization if necessary."
Expand Down
52 changes: 52 additions & 0 deletions PSGSuite/Public/Configuration/Export-PSGSuiteConfig.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
function Export-PSGSuiteConfig {
<#
.SYNOPSIS
Allows you to export an unecrypted PSGSuite config in a portable JSON string format. Useful for moving a config to a new machine or storing the full as an encrypted string in your CI/CD / Automation tools.
.DESCRIPTION
Allows you to export an unecrypted PSGSuite config in a portable JSON string format. Useful for moving a config to a new machine or storing the full as an encrypted string in your CI/CD / Automation tools.
.PARAMETER Path
The path you would like to save the JSON file to. Defaults to a named path in the current directory.
.PARAMETER ConfigName
The config that you would like to export. Defaults to the currently loaded config.
.EXAMPLE
Export-PSGSuiteConfig -ConfigName Personal -Path ".\PSGSuite_personal_config.json"
Exports the config named 'Personal' to the path specified.
#>
[CmdletBinding()]
Param (
[parameter(Mandatory = $false,Position = 0)]
[Alias('OutPath','OutFile','JsonPath')]
[String]
$Path,
[parameter(Mandatory = $false)]
[String]
$ConfigName = $script:PSGSuite.ConfigName
)
Begin {
$baseConf = if ($PSBoundParameters.Keys -contains 'ConfigName'){
Get-PSGSuiteConfig -ConfigName $ConfigName -NoImport -PassThru -Verbose:$false
}
else {
Show-PSGSuiteConfig -Verbose:$false
}
if ($PSBoundParameters.Keys -notcontains 'Path') {
$Path = (Join-Path $PWD.Path "PSGSuite_$($baseConf.AdminEmail)_$($baseConf.ConfigName).json")
}
}
Process {
try {
Write-Verbose "Updating current saved config for '$ConfigName' with P12Key and ClientSecrets contents if missing."
$baseConf | Set-PSGSuiteConfig -NoImport -Verbose:$false
Write-Verbose "Exporting config '$ConfigName' to path: $Path"
Get-PSGSuiteConfig -ConfigName $ConfigName -NoImport -PassThru -Verbose:$false | Select-Object ConfigName,P12Key,ClientSecrets,AppEmail,AdminEmail,CustomerId,Domain,Preference | ConvertTo-Json -Depth 5 -Compress -Verbose:$false | Set-Content -Path $Path -Verbose:$false
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
}
}
1 change: 1 addition & 0 deletions PSGSuite/Public/Configuration/Get-PSGSuiteConfig.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ function Get-PSGSuiteConfig {
$decryptedConfig = $encConf |
Select-Object -Property @{l = 'ConfigName';e = {$choice}},
@{l = 'P12KeyPath';e = {Decrypt $_.P12KeyPath}},
P12Key,
@{l = 'ClientSecretsPath';e = {Decrypt $_.ClientSecretsPath}},
@{l = 'ClientSecrets';e = {Decrypt $_.ClientSecrets}},
@{l = 'AppEmail';e = {Decrypt $_.AppEmail}},
Expand Down
69 changes: 69 additions & 0 deletions PSGSuite/Public/Configuration/Import-PSGSuiteConfig.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
function Import-PSGSuiteConfig {
<#
.SYNOPSIS
Allows you to import an unecrypted PSGSuite config from a portable JSON string format, typically created with Export-PSGSuiteConfig. Useful for moving a config to a new machine or storing the full as an encrypted string in your CI/CD / Automation tools.
.DESCRIPTION
Allows you to import an unecrypted PSGSuite config from a portable JSON string format, typically created with Export-PSGSuiteConfig. Useful for moving a config to a new machine or storing the full as an encrypted string in your CI/CD / Automation tools.
.PARAMETER Json
The Json string to import.
.PARAMETER Path
The path of the Json file you would like import.
.PARAMETER Temporary
If $true, the imported config is not stored in the config file and the imported config persists only for the current session.
.PARAMETER PassThru
If $true, outputs the resulting config object to the pipeline.
.EXAMPLE
Import-Module PSGSuite -MinimumVersion 2.22.0
Import-PSGSuiteConfig -Json '$(PSGSuiteConfigJson)' -Temporary
Azure Pipelines inline script task that uses a Secure Variable named 'PSGSuiteConfigJson' with the Config JSON string stored in it, removing the need to include credential or key files anywhere.
#>
[CmdletBinding(DefaultParameterSetName = "Json")]
Param (
[parameter(Mandatory = $true,Position = 0,ValueFromPipeline = $true,ParameterSetName = "Json")]
[Alias('J')]
[String]
$Json,
[parameter(Mandatory = $true,ValueFromPipelineByPropertyName = $true,ParameterSetName = "Path")]
[Alias('P')]
[String]
$Path,
[parameter(Mandatory = $false)]
[Alias('Temp','T')]
[Switch]
$Temporary,
[parameter(Mandatory = $false)]
[Switch]
$PassThru
)
Process {
try {
switch ($PSCmdlet.ParameterSetName) {
Path {
Write-Verbose "Importing config from path: $Path"
$script:PSGSuite = (ConvertFrom-Json (Get-Content $Path -Raw))
}
Json {
Write-Verbose "Importing config from Json string"
$script:PSGSuite = (ConvertFrom-Json $Json)
}
}
if (-not $Temporary) {
Write-Verbose "Saving imported config"
$script:PSGSuite | Set-PSGSuiteConfig
}
if ($PassThru) {
return $script:PSGSuite
}
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
}
}
42 changes: 35 additions & 7 deletions PSGSuite/Public/Configuration/Set-PSGSuiteConfig.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ function Set-PSGSuiteConfig {
The friendly name for the config you are creating or updating
.PARAMETER P12KeyPath
The path to the P12 Key file downloaded from the Google Developer's Console. If both P12KeyPath and ClientSecretsPath are specified, P12KeyPath takes precedence
The path to the P12 Key file downloaded from the Google Developer's Console. If both P12KeyPath and ClientSecretsPath are specified, P12KeyPath takes precedence.
.PARAMETER P12Key
The P12Key in byte array format. If the actual P12Key is present on the config, the P12KeyPath is not needed. The config will auto-update with this value after running any command, if P12KeyPath is filled and this value is not already present.
.PARAMETER ClientSecretsPath
The path to the Client Secrets JSON file downloaded from the Google Developer's Console. Using the ClientSecrets JSON will prompt the user to complete OAuth2 authentication in their browser on the first run and store the retrieved Refresh and Access tokens in the user's home directory. If P12KeyPath is also specified, ClientSecretsPath will be ignored.
The path to the Client Secrets JSON file downloaded from the Google Developer's Console. Using the ClientSecrets JSON will prompt the user to complete OAuth2 authentication in their browser on the first run and store the retrieved Refresh and Access tokens in the user's home directory. The config will auto-update with this value after running any command, if ClientSecretsPath is filled and this value is not already present. If P12KeyPath is also specified, ClientSecretsPath will be ignored.
.PARAMETER ClientSecrets
The string contents of the Client Secrets JSON file downloaded from the Google Developer's Console. Using the ClientSecrets JSON will prompt the user to complete OAuth2 authentication in their browser on the first run and store the retrieved Refresh and Access tokens in the user's home directory. If P12KeyPath is also specified, ClientSecrets will be ignored.
Expand Down Expand Up @@ -86,6 +89,9 @@ function Set-PSGSuiteConfig {
[string]
$P12KeyPath,
[parameter(Mandatory = $false,ValueFromPipelineByPropertyName = $true)]
[Byte[]]
$P12Key,
[parameter(Mandatory = $false,ValueFromPipelineByPropertyName = $true)]
[string]
$ClientSecretsPath,
[parameter(Mandatory = $false,ValueFromPipelineByPropertyName = $true)]
Expand Down Expand Up @@ -155,7 +161,7 @@ function Set-PSGSuiteConfig {
}
}
Write-Verbose "Setting config name '$ConfigName'"
$configParams = @('P12KeyPath','ClientSecretsPath','ClientSecrets','AppEmail','AdminEmail','CustomerID','Domain','Preference','ServiceAccountClientID','Webhook','Space')
$configParams = @('P12Key','P12KeyPath','ClientSecretsPath','ClientSecrets','AppEmail','AdminEmail','CustomerID','Domain','Preference','ServiceAccountClientID','Webhook','Space')
if ($SetAsDefaultConfig -or !$configHash["DefaultConfig"]) {
$configHash["DefaultConfig"] = $ConfigName
}
Expand All @@ -164,9 +170,28 @@ function Set-PSGSuiteConfig {
}
foreach ($key in ($PSBoundParameters.Keys | Where-Object {$configParams -contains $_})) {
switch ($key) {
P12Key {
if (-not $_p12Key) {
$_p12Key = @()
}
if ($P12Key.Count -gt 1) {
$_p12Key = $P12Key
}
else {
$_p12Key += $P12Key
}
}
P12KeyPath {
if (-not [System.String]::IsNullOrWhiteSpace($PSBoundParameters[$key].Trim())) {
$configHash["$ConfigName"][$key] = (Encrypt $PSBoundParameters[$key])
$configHash["$ConfigName"]['P12Key'] = ([System.IO.File]::ReadAllBytes($PSBoundParameters[$key]))
}
}
ClientSecretsPath {
$configHash["$ConfigName"][$key] = (Encrypt $PSBoundParameters[$key])
$configHash["$ConfigName"]['ClientSecrets'] = (Encrypt $(Get-Content $PSBoundParameters[$key] -Raw))
if (-not [System.String]::IsNullOrWhiteSpace($PSBoundParameters[$key].Trim())) {
$configHash["$ConfigName"][$key] = (Encrypt $PSBoundParameters[$key])
$configHash["$ConfigName"]['ClientSecrets'] = (Encrypt $(Get-Content $PSBoundParameters[$key] -Raw))
}
}
Webhook {
if ($configHash["$ConfigName"].Keys -notcontains 'Chat') {
Expand Down Expand Up @@ -200,10 +225,13 @@ function Set-PSGSuiteConfig {
}
}
}
$configHash["$ConfigName"]['ConfigPath'] = (Join-Path $(Get-Module PSGSuite | Get-StoragePath -Scope $Script:ConfigScope) "Configuration.psd1")
$configHash | Export-Configuration -CompanyName 'SCRT HQ' -Name 'PSGSuite' -Scope $script:ConfigScope
}
End {
if ($_p12Key) {
$configHash["$ConfigName"]['P12Key'] = $_p12Key
}
$configHash["$ConfigName"]['ConfigPath'] = (Join-Path $(Get-Module PSGSuite | Get-StoragePath -Scope $Script:ConfigScope) "Configuration.psd1")
$configHash | Export-Configuration -CompanyName 'SCRT HQ' -Name 'PSGSuite' -Scope $script:ConfigScope
if (!$NoImport) {
Get-PSGSuiteConfig -ConfigName $ConfigName -Verbose:$false
}
Expand Down
1 change: 1 addition & 0 deletions PSGSuite/Public/Configuration/Switch-PSGSuiteConfig.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
$script:PSGSuite = [PSCustomObject]($fullConf[$choice]) |
Select-Object -Property @{l = 'ConfigName';e = {$choice}},
@{l = 'P12KeyPath';e = {Decrypt $_.P12KeyPath}},
P12Key,
@{l = 'ClientSecretsPath';e = {Decrypt $_.ClientSecretsPath}},
@{l = 'ClientSecrets';e = {Decrypt $_.ClientSecrets}},
@{l = 'AppEmail';e = {Decrypt $_.AppEmail}},
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ Update-GSSheetValue Export-GSSheet

### Most recent changes

#### 2.22.0

* Miscellaneous: _Config management and portability updates_
* Added: `Export-PSGSuiteConfig` function to export key parts of your config in a transportable JSON file.
* Added: `Import-PSGSuiteConfig` function to import a config from a JSON file (i.e. one created with `Export-PSGSuiteConfig`) or from a JSON string (i.e. stored in a secure variable in a CI/CD system.)
* Updated: All config functions now store the P12Key or the ClientSecrets JSON string in the encrypted config directly. This is to allow removal of the secrets files as well as enable PSGSuite to run in a contained environment via importing the config from a secure JSON string.
* Updated: `[Get|Set|Switch]-PSGSuiteConfig` to include the P12Key and ClientSecrets parameters that enable housing of the key/secret directly on the encrypted config.
* Updated: If the global PSGSuite variable `$global:PSGSuite` exists during module import, it will default to using that as it's configuration, otherwise it will import the default config if set.

#### 2.21.3

* [Issue #131](https://github.com/scrthq/PSGSuite/issues/131)
Expand Down
12 changes: 11 additions & 1 deletion psake.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,17 @@ try {
`$Script:ConfigName = `$ConfigName
}
try {
Get-PSGSuiteConfig @confParams -ErrorAction Stop
if (`$global:PSGSuite) {
Write-Warning "Using config `$(if (`$global:PSGSuite.ConfigName){"name '`$(`$global:PSGSuite.ConfigName)' "})found in variable: ```$global:PSGSuite"
Write-Verbose "`$((`$global:PSGSuite | Format-List | Out-String).Trim())"
if (`$global:PSGSuite -is [System.Collections.Hashtable]) {
`$global:PSGSuite = New-Object PSObject -Property `$global:PSGSuite
}
`$script:PSGSuite = `$global:PSGSuite
}
else {
Get-PSGSuiteConfig @confParams -ErrorAction Stop
}
}
catch {
if (Test-Path "`$ModuleRoot\`$env:USERNAME-`$env:COMPUTERNAME-`$env:PSGSuiteDefaultDomain-PSGSuite.xml") {
Expand Down

0 comments on commit 08b7958

Please sign in to comment.