diff --git a/PSGSuite/Public/Authentication/New-GoogleService.ps1 b/PSGSuite/Public/Authentication/New-GoogleService.ps1 index 7352d8cf..a7d19f7e 100644 --- a/PSGSuite/Public/Authentication/New-GoogleService.ps1 +++ b/PSGSuite/Public/Authentication/New-GoogleService.ps1 @@ -55,19 +55,50 @@ function New-GoogleService { $script:_PSGSuiteSessions[$sessionKey] | Select-Object -ExpandProperty Service } else { - if ($script:PSGSuite.P12KeyPath -or $script:PSGSuite.P12Key) { + if ($script:PSGSuite.JSONServiceAccountKey -or $script:PSGSuite.JSONServiceAccountKeyPath) { + Write-Verbose "Building ServiceAccountCredential from JSONServiceAccountKey as user '$User'" + try { + if (-not $script:PSGSuite.JSONServiceAccountKey) { + $script:PSGSuite.JSONServiceAccountKey = ([System.IO.File]::ReadAllBytes($script:PSGSuite.JSONServiceAccountKeyPath)) + Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -JSONServiceAccountKey $script:PSGSuite.JSONServiceAccountKey -Verbose:$false + } + $stream = New-Object System.IO.MemoryStream $([System.Text.Encoding]::ASCII.GetBytes($script:PSGSuite.JSONServiceAccountKey)), $null + $credential = ([Google.Apis.Auth.OAuth2.GoogleCredential]::FromStream($stream)).CreateWithUser($User).CreateScoped($Scope).UnderlyingCredential + } + catch { + $PSCmdlet.ThrowTerminatingError($_) + } + finally { + if ($stream) { + $stream.Close() + } + } + } + elseif ($script:PSGSuite.P12KeyPath -or $script:PSGSuite.P12Key -or $script:PSGSuite.P12KeyObject) { try { Write-Verbose "Building ServiceAccountCredential from P12Key as user '$User'" - 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 + if ($script:PSGSuite.P12KeyPath -or $script:PSGSuite.P12Key) { + 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 + } + if ($script:PSGSuite.P12KeyPassword) { + $P12KeyPassword = $script:PSGSuite.P12KeyPassword + } + else { + $P12KeyPassword = "notasecret" + } + $certificate = New-Object 'System.Security.Cryptography.X509Certificates.X509Certificate2' -ArgumentList ([System.Byte[]]$script:PSGSuite.P12Key),$P12KeyPassword,([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable) + } + else { + $certificate = $script:PSGSuite.P12KeyObject } - $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 } ).FromCertificate($certificate) + } catch { $PSCmdlet.ThrowTerminatingError($_) @@ -116,7 +147,7 @@ function New-GoogleService { } } else { - $PSCmdlet.ThrowTerminatingError((ThrowTerm "The current config '$($script:PSGSuite.ConfigName)' does not contain a P12KeyPath or a ClientSecretsPath! PSGSuite is unable to build a credential object for the service without a path to a credential file! Please update the configuration to include a path at least one of the two credential types.")) + $PSCmdlet.ThrowTerminatingError((ThrowTerm "The current config '$($script:PSGSuite.ConfigName)' does not contain a JSONServiceAccountKeyPath, P12KeyPath, or ClientSecretsPath! PSGSuite is unable to build a credential object for the service without a path to a credential file! Please update the configuration to include a path at least one of the three credential types.")) } $svc = New-Object "$ServiceType" (New-Object 'Google.Apis.Services.BaseClientService+Initializer' -Property @{ HttpClientInitializer = $credential diff --git a/PSGSuite/Public/Configuration/Get-PSGSuiteConfig.ps1 b/PSGSuite/Public/Configuration/Get-PSGSuiteConfig.ps1 index b6200290..d5030844 100644 --- a/PSGSuite/Public/Configuration/Get-PSGSuiteConfig.ps1 +++ b/PSGSuite/Public/Configuration/Get-PSGSuiteConfig.ps1 @@ -57,6 +57,9 @@ function Get-PSGSuiteConfig { [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $String)) } + elseif ($String -is [ScriptBlock]) { + $String.InvokeReturnAsIs() + } else { $String } @@ -65,14 +68,30 @@ function Get-PSGSuiteConfig { @{l = 'ConfigName';e = {$choice}}, @{l = 'P12KeyPath';e = {Decrypt $_.P12KeyPath}}, 'P12Key', + @{l = 'P12KeyPassword';e = {Decrypt $_.P12KeyPassword}}, + @{l = 'P12KeyObject';e = {Decrypt $_.P12KeyObject}}, @{l = 'ClientSecretsPath';e = {Decrypt $_.ClientSecretsPath}}, @{l = 'ClientSecrets';e = {Decrypt $_.ClientSecrets}}, - @{l = 'AppEmail';e = {Decrypt $_.AppEmail}}, + @{l = 'AppEmail';e = { + if ($_.AppEmail) { + Decrypt $_.ServiceAccountClientID + } + elseif ($_.ClientSecrets) { + (Decrypt $_.ClientSecrets | ConvertFrom-Json).client_email + } + }}, @{l = 'AdminEmail';e = {Decrypt $_.AdminEmail}}, @{l = 'CustomerID';e = {Decrypt $_.CustomerID}}, @{l = 'Domain';e = {Decrypt $_.Domain}}, @{l = 'Preference';e = {Decrypt $_.Preference}}, - @{l = 'ServiceAccountClientID';e = {Decrypt $_.ServiceAccountClientID}}, + @{l = 'ServiceAccountClientID';e = { + if ($_.ServiceAccountClientID) { + Decrypt $_.ServiceAccountClientID + } + elseif ($_.ClientSecrets) { + (Decrypt $_.ClientSecrets | ConvertFrom-Json).client_id + } + }}, @{l = 'Chat';e = { $dict = @{ Webhooks = @{} diff --git a/PSGSuite/Public/Configuration/Set-PSGSuiteConfig.ps1 b/PSGSuite/Public/Configuration/Set-PSGSuiteConfig.ps1 index 65396cfa..279ed2aa 100644 --- a/PSGSuite/Public/Configuration/Set-PSGSuiteConfig.ps1 +++ b/PSGSuite/Public/Configuration/Set-PSGSuiteConfig.ps1 @@ -15,11 +15,14 @@ function Set-PSGSuiteConfig { .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 P12KeyPassword + The password for the P12 Key file. If not specified the default of 'notasecret' will be used and this config value will not be set. This is only needed in the case where the P12 file has been manually rexported with a custom password + .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. 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. + 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 JSONServiceAccountKeyPath or 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. + 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 JSONServiceAccountKeyPath or P12KeyPath is also specified, ClientSecrets will be ignored. .PARAMETER AppEmail The application email from the Google Developer's Console. This typically looks like the following: @@ -95,6 +98,9 @@ function Set-PSGSuiteConfig { [Byte[]] $P12Key, [parameter(Mandatory = $false,ValueFromPipelineByPropertyName = $true)] + [SecureString] + $P12KeyPassword, + [parameter(Mandatory = $false,ValueFromPipelineByPropertyName = $true)] [string] $ClientSecretsPath, [parameter(Mandatory = $false,ValueFromPipelineByPropertyName = $true)] @@ -145,6 +151,9 @@ function Set-PSGSuiteConfig { elseif ($string -is [System.String] -and $String -notlike '') { ConvertTo-SecureString -String $string -AsPlainText -Force } + elseif ($string -is [System.Management.Automation.ScriptBlock]) { + $string + } } } Process { @@ -164,7 +173,7 @@ function Set-PSGSuiteConfig { } } Write-Verbose "Setting config name '$ConfigName'" - $configParams = @('P12Key','P12KeyPath','ClientSecretsPath','ClientSecrets','AppEmail','AdminEmail','CustomerID','Domain','Preference','ServiceAccountClientID','Webhook','Space') + $configParams = @('P12Key','P12KeyPath','P12KeyPassword','ClientSecretsPath','ClientSecrets','AppEmail','AdminEmail','CustomerID','Domain','Preference','ServiceAccountClientID','Webhook','Space') if ($SetAsDefaultConfig -or !$configHash["DefaultConfig"]) { $configHash["DefaultConfig"] = $ConfigName } @@ -190,6 +199,9 @@ function Set-PSGSuiteConfig { $configHash["$ConfigName"]['P12Key'] = ([System.IO.File]::ReadAllBytes($PSBoundParameters[$key])) } } + P12KeyPassword { + $configHash["$ConfigName"][$key] = $PSBoundParameters[$key] + } ClientSecretsPath { if (-not [System.String]::IsNullOrWhiteSpace($PSBoundParameters[$key].Trim())) { $configHash["$ConfigName"][$key] = (Encrypt $PSBoundParameters[$key])