diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cac72d2..584684ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.3.0 +- Add support for local token/key storage with [PowerShell SecretManagement](https://devblogs.microsoft.com/powershell/secretmanagement-and-secretstore-are-generally-available/). Store your access or refresh token securely and have VenafiPS use it to create a new session. +- Add `Get-TppClassAttribute` to list all attributes for a specific class. Helpful for attribute validation and getting values for all attributes. + ## 3.2.0 - Add support for token refresh to `New-VenafiSession` and `New-TppToken`. Auto-refresh $VenafiSession when token expires and we have a refresh token. [#33](https://github.com/gdbarron/VenafiPS/issues/33) - Fix invalid grant details in `Test-TppToken`, [#32](https://github.com/gdbarron/VenafiPS/issues/32) diff --git a/README.md b/README.md index ed1366d7..b6185d3b 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,16 @@ Documentation can be found at [http://VenafiPS.readthedocs.io](http://VenafiPS.r VenafiPS is published to the PowerShell Gallery. The most recent version is listed in the badge 'powershell gallery' above and can be viewed by clicking on it. To install the module, you need to have PowerShell installed first. On Windows, PowerShell will already be installed. For [Linux](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7) or [macOS](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7), you will need to install PowerShell Core; follow those links for guidance. Once PowerShell is installed, start a PowerShell prompt and execute `Install-Module -Name VenafiPS` which will install from the gallery. +### Token/Key Secret Storage + +To securely store and retrieve secrets, VenafiPS has added support for the [PowerShell SecretManagement module](https://github.com/PowerShell/SecretManagement). This can be used to store your access tokens, refresh tokens, or vaas key. To use this feature, a vault will need to be created. You can use [SecretStore](https://github.com/PowerShell/SecretStore) provided by the PowerShell team or any other vault type. All of this functionality has been added to `New-VenafiSession`. To prepare your environment, execute the following: +- `Install-Module Microsoft.PowerShell.SecretManagement` +- `Install-Module Microsoft.PowerShell.SecretStore` or whichever vault you would like to use +- `Register-SecretVault -Name VenafiPS -ModuleName Microsoft.PowerShell.SecretStore`. If you are using a different vault type, replace the value for `-ModuleName`. +- If using the vault Microsoft.PowerShell.SecretStore, execute `Set-SecretStoreConfiguration -Authentication None -Confirm:$false`. Note, although the vault authentication is set to none, this just turns off the password required to access the vault, it does not mean your secrets are not encrypted. This is required for automation purposes. If using a different vault type, ensure you turn off any features which inhibit automation. + +Note, extension vaults are registered to the current logged in user context, and will be available only to that user (unless also registered to other users). + ## Usage As the module supports both TPP and Venafi as a Service, you will note different names for the functions. Functions with `-Tpp` are for TPP only, `-Vaas` are for Venafi as a Service only, and `-Venafi` are for both. @@ -35,6 +45,12 @@ Start a new PowerShell prompt (even if you have one from the Install Module step ```powershell $cred = Get-Credential New-VenafiSession -Server 'venafi.mycompany.com' -Credential $cred -ClientId 'MyApp' -Scope @{'certificate'='manage'} + +# to store access token for later use +New-VenafiSession -Server 'venafi.mycompany.com' -Credential $cred -ClientId 'MyApp' -Scope @{'certificate'='manage'} -VaultAccessTokenName TppAccessToken + +# to store refresh token for later use +New-VenafiSession -Server 'venafi.mycompany.com' -Credential $cred -ClientId 'MyApp' -Scope @{'certificate'='manage'} -VaultRefreshTokenName TppRefreshToken ``` This will create a session which will be used by default in other functions. diff --git a/RELEASE.md b/RELEASE.md index d9a821aa..ddf0fa43 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,2 @@ -- Add support for token refresh to `New-VenafiSession` and `New-TppToken`. Auto-refresh $VenafiSession when token expires and we have a refresh token. [#33](https://github.com/gdbarron/VenafiPS/issues/33) -- Fix invalid grant details in `Test-TppToken`, [#32](https://github.com/gdbarron/VenafiPS/issues/32) -- Update Version in VenafiSession object, from `Get-TppVersion`, to be of type Version. Drop Revision from version so now only 3 octets. This assists in performing version validation. -- Update `New-TppToken` to account for a bug in pre 21.3 which expected the client_id to be lowercase -- Update `Test-TppToken` to validate the tpp version is supported \ No newline at end of file +- Add support for local token/key storage with [PowerShell SecretManagement](https://devblogs.microsoft.com/powershell/secretmanagement-and-secretstore-are-generally-available/). Store your access or refresh token securely and have VenafiPS use it to create a new session. +- Add `Get-TppClassAttribute` to list all attributes for a specific class. Helpful for attribute validation and getting values for all attributes. \ No newline at end of file diff --git a/VenafiPS/Public/Get-TppAttribute.ps1 b/VenafiPS/Public/Get-TppAttribute.ps1 index 06f9656b..dede2373 100644 --- a/VenafiPS/Public/Get-TppAttribute.ps1 +++ b/VenafiPS/Public/Get-TppAttribute.ps1 @@ -26,7 +26,7 @@ Get the effective values of the attribute Session object created from New-VenafiSession method. The value defaults to the script session object $VenafiSession. .INPUTS -InputObject, Path, Guid +Path, Guid .OUTPUTS PSCustomObject with properties Name, Value, IsCustomField, and CustomName @@ -60,15 +60,12 @@ https://docs.venafi.com/Docs/20.4SDK/TopNav/Content/SDK/WebSDK/r-SDK-POST-Config #> function Get-TppAttribute { - [CmdletBinding(DefaultParameterSetName = 'ByObject')] + [CmdletBinding(DefaultParameterSetName = 'ByPath')] param ( - [Parameter(Mandatory, ParameterSetName = 'EffectiveByObject', ValueFromPipeline)] - [Parameter(Mandatory, ParameterSetName = 'ByObject', ValueFromPipeline)] - [TppObject] $InputObject, - - [Parameter(Mandatory, ParameterSetName = 'EffectiveByPath', ValueFromPipeline)] - [Parameter(Mandatory, ParameterSetName = 'ByPath', ValueFromPipeline)] + [Parameter(Mandatory, ParameterSetName = 'EffectiveByPath', ValueFromPipeline, ValueFromPipelineByPropertyName)] + [Parameter(Mandatory, ParameterSetName = 'ByPath', ValueFromPipeline, ValueFromPipelineByPropertyName)] + [Parameter(Mandatory, ParameterSetName = 'AllByPath', ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateNotNullOrEmpty()] [ValidateScript( { if ( $_ | Test-TppDnPath ) { @@ -86,8 +83,6 @@ function Get-TppAttribute { [ValidateNotNullOrEmpty()] [guid[]] $Guid, - [Parameter(Mandatory, ParameterSetName = 'EffectiveByObject')] - [Parameter(ParameterSetName = 'ByObject')] [Parameter(Mandatory, ParameterSetName = 'EffectiveByPath')] [Parameter(ParameterSetName = 'ByPath')] [Parameter(Mandatory, ParameterSetName = 'EffectiveByGuid')] @@ -95,7 +90,6 @@ function Get-TppAttribute { [ValidateNotNullOrEmpty()] [String[]] $Attribute, - [Parameter(Mandatory, ParameterSetName = 'EffectiveByObject')] [Parameter(Mandatory, ParameterSetName = 'EffectiveByPath')] [Parameter(Mandatory, ParameterSetName = 'EffectiveByGuid')] [Alias('EffectivePolicy')] @@ -134,10 +128,6 @@ function Get-TppAttribute { process { switch -Wildcard ($PSCmdlet.ParameterSetName) { - '*Object' { - $pathToProcess = $InputObject.Path - } - '*Path' { $pathToProcess = $Path } @@ -151,6 +141,7 @@ function Get-TppAttribute { $baseParams.Body['ObjectDN'] = $thisPath + # if specifying attribute name(s), it's a different rest api if ( $PSBoundParameters.ContainsKey('Attribute') ) { diff --git a/VenafiPS/Public/Get-TppClassAttribute.ps1 b/VenafiPS/Public/Get-TppClassAttribute.ps1 new file mode 100644 index 00000000..fb535414 --- /dev/null +++ b/VenafiPS/Public/Get-TppClassAttribute.ps1 @@ -0,0 +1,62 @@ +<# +.SYNOPSIS + List all attributes for a specified class +.DESCRIPTION + List all attributes for a specified class, helpful for validation or to pass to Get-TppAttribute +.EXAMPLE + Get-TppClassAttribute -ClassName 'X509 Server Certificate' + Get all attributes for the specified class +.INPUTS + ClassName +.OUTPUTS + PSCustomObject +#> +function Get-TppClassAttribute { + [CmdletBinding()] + param ( + [Parameter(Mandatory, ValueFromPipeline)] + [string] $ClassName, + + [Parameter()] + [VenafiSession] $VenafiSession = $script:VenafiSession + ) + + begin { + $allAttributes = [System.Collections.Generic.List[object]]::new() + } + + process { + + Write-Verbose "Processing $ClassName" + + $params = @{ + VenafiSession = $VenafiSession + Method = 'Post' + UriLeaf = 'configschema/class' + Body = @{ + 'Class' = $ClassName + } + } + $classDetails = Invoke-VenafiRestMethod @params | Select-Object -ExpandProperty 'ClassDefinition' + + if ($ClassName -ne 'Top') { + $recurseAttribs = $classDetails.SuperClassNames | Get-TppClassAttribute + foreach ($item in $recurseAttribs) { + $allAttributes.Add($item) + } + } + + foreach ($item in ($classDetails.OptionalNames)) { + $allAttributes.Add( + [pscustomobject] @{ + 'Name' = $item + 'Class' = $classDetails.Name + } + ) + } + } + + end { + $allAttributes | Sort-Object -Property 'Name', 'Class' -Unique + } +} diff --git a/VenafiPS/Public/New-TppToken.ps1 b/VenafiPS/Public/New-TppToken.ps1 index a981dc0e..448a96d1 100644 --- a/VenafiPS/Public/New-TppToken.ps1 +++ b/VenafiPS/Public/New-TppToken.ps1 @@ -242,7 +242,7 @@ function New-TppToken { Server = $params.ServerUrl AccessToken = New-Object System.Management.Automation.PSCredential('AccessToken', ($response.access_token | ConvertTo-SecureString -AsPlainText -Force)) RefreshToken = $null - Scope = $response.scope + Scope = $Scope Identity = $response.identity TokenType = $response.token_type ClientId = $params.Body.client_id diff --git a/VenafiPS/Public/New-VenafiSession.ps1 b/VenafiPS/Public/New-VenafiSession.ps1 index 7258750f..640a1cb8 100644 --- a/VenafiPS/Public/New-VenafiSession.ps1 +++ b/VenafiPS/Public/New-VenafiSession.ps1 @@ -5,7 +5,8 @@ Create a new Venafi TPP or Venafi as a Service session .DESCRIPTION Authenticate a user and create a new session with which future calls can be made. Key based username/password and windows integrated are supported as well as token-based integrated, oauth, and certificate. -Note, key-based authentication will be fully deprecated in v20.4. +By default, a session variable will be created and automatically used with other functions unless -PassThru is used. +Tokens and VaaS keys can be saved in a vault for future calls. .PARAMETER Server Server or url to access vedsdk, venafi.company.com or https://venafi.company.com. @@ -23,7 +24,7 @@ Hashtable with Scopes and privilege restrictions. The key is the scope and the value is one or more privilege restrictions separated by commas, @{'certificate'='delete,manage'}. Scopes include Agent, Certificate, Code Signing, Configuration, Restricted, Security, SSH, and statistics. For no privilege restriction or read access, use a value of $null. -For a scope to privilege mapping, see https://docs.venafi.com/Docs/20.4SDK/TopNav/Content/SDK/AuthSDK/r-SDKa-OAuthScopePrivilegeMapping.php?tocpath=Auth%20SDK%20reference%20for%20token%20management%7C_____5 +For a scope to privilege mapping, see https://docs.venafi.com/Docs/current/TopNav/Content/SDK/AuthSDK/r-SDKa-OAuthScopePrivilegeMapping.php .PARAMETER State A session state, redirect URL, or random string to prevent Cross-Site Request Forgery (CSRF) attacks @@ -31,14 +32,27 @@ A session state, redirect URL, or random string to prevent Cross-Site Request Fo .PARAMETER AccessToken PSCredential object with the access token as the password. +.PARAMETER VaultAccessTokenName +Name of the SecretManagement vault entry for the access token; the name of the vault must be VenafiPS. +This value can be provided standalone or with credentials. First time use requires it to be provided with credentials to retrieve the access token to populate the vault. +With subsequent uses, it can be provided standalone and the access token will be retrieved without the need for credentials. +See -VaultMetadata to store server and clientid with the token. + .PARAMETER RefreshToken PSCredential object with the refresh token as the password. An access token will be retrieved and a new session created. +.PARAMETER VaultRefreshTokenName +Name of the SecretManagement vault entry for the refresh token; the name of the vault must be VenafiPS. +This value can be provided standalone or with credentials. Each time this is used, a new access and refresh token will be obtained. +First time use requires it to be provided with credentials to retrieve the refresh token and populate the vault. +With subsequent uses, it can be provided standalone and the refresh token will be retrieved without the need for credentials. +See -VaultMetadata to store server and clientid with the token. + .PARAMETER Certificate Certificate for token-based authentication .PARAMETER AuthServer -If you host your authentication service, vedauth, on a separate server than vedsdk, use this parameter to specify the url eg., venafi.company.com or https://venafi.company.com. +If you host your authentication service, vedauth, is on a separate server than vedsdk, use this parameter to specify the url eg., venafi.company.com or https://venafi.company.com. If AuthServer is not provided, the value provided for Server will be used. If just the server name is provided, https:// will be appended. @@ -47,6 +61,17 @@ Api key from your Venafi as a Service instance. The api key can be found under Provide a credential object with the api key as the password. https://docs.venafi.cloud/DevOpsACCELERATE/API/t-cloud-api-key/ +.PARAMETER VaultVaasKeyName +Name of the SecretManagement vault entry for the Venafi as a Service key. +First time use requires it to be provided with -VaasKey to populate the vault. +With subsequent uses, it can be provided standalone and the key will be retrieved with the need for -VaasKey. + +.PARAMETER VaultMetadata +When a token vault entry, access or refresh, is created with -VaultAccessTokenName or -VaultRefreshTokenName, store the server and clientid with it so this doesn't need to be provided each time. +Once used, the server and clientid will continue to be stored with updated vault entries regardless if -VaultMetadata was provided again. +To clear the metadata, reauthenticate with this function with a credential and without providing -VaultMetadata. +To use this parameter, the SecretManagement vault must support it. + .PARAMETER PassThru Optionally, send the session object to the pipeline instead of script scope. @@ -85,6 +110,14 @@ Create session using an access token obtained outside this module New-VenafiSession -Server venafitpp.mycompany.com -RefreshToken $refreshCred -ClientId MyApp Create session using a refresh token +.EXAMPLE +New-VenafiSession -Server venafitpp.mycompany.com -RefreshToken $refreshCred -ClientId MyApp -VaultRefreshTokenName TppRefresh +Create session using a refresh token and store the newly created refresh token in the vault + +.EXAMPLE +New-VenafiSession -Server venafitpp.mycompany.com -RefreshToken $refreshCred -ClientId MyApp -VaultRefreshTokenName TppRefresh -VaultMetadata +Create session using a refresh token, store the newly created refresh token in the vault, and store the server and clientid with the secret + .EXAMPLE New-VenafiSession -VaasKey $cred Create session against Venafi as a Service @@ -109,6 +142,12 @@ https://docs.venafi.com/Docs/current/TopNav/Content/SDK/AuthSDK/r-SDKa-POST-Auth .LINK https://docs.venafi.com/Docs/current/TopNav/Content/SDK/AuthSDK/r-SDKa-POST-AuthorizeCertificate.php?tocpath=Platform%20SDK%7CAuth%20REST%20for%20token%20management%7C_____9 + +.LINK +https://github.com/PowerShell/SecretManagement + +.LINK +https://github.com/PowerShell/SecretStore #> function New-VenafiSession { @@ -122,6 +161,8 @@ function New-VenafiSession { [Parameter(Mandatory, ParameterSetName = 'TokenCertificate')] [Parameter(Mandatory, ParameterSetName = 'AccessToken')] [Parameter(Mandatory, ParameterSetName = 'RefreshToken')] + [Parameter(ParameterSetName = 'VaultAccessToken')] + [Parameter(ParameterSetName = 'VaultRefreshToken')] [ValidateScript( { if ( $_ -match '^(https?:\/\/)?(((?!-))(xn--|_{1,1})?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9][a-z0-9\-]{0,60}|[a-z0-9-]{1,30}\.[a-z]{2,})$' ) { $true @@ -142,11 +183,14 @@ function New-VenafiSession { [Parameter(Mandatory, ParameterSetName = 'TokenOAuth')] [Parameter(Mandatory, ParameterSetName = 'TokenCertificate')] [Parameter(ParameterSetName = 'RefreshToken', Mandatory)] + [Parameter(ParameterSetName = 'VaultRefreshToken')] [string] $ClientId, [Parameter(Mandatory, ParameterSetName = 'TokenIntegrated')] [Parameter(Mandatory, ParameterSetName = 'TokenOAuth')] [Parameter(Mandatory, ParameterSetName = 'TokenCertificate')] + [Parameter(ParameterSetName = 'VaultAccessToken')] + [Parameter(ParameterSetName = 'VaultRefreshToken')] [hashtable] $Scope, [Parameter(ParameterSetName = 'TokenIntegrated')] @@ -162,6 +206,29 @@ function New-VenafiSession { [Parameter(Mandatory, ParameterSetName = 'TokenCertificate')] [X509Certificate] $Certificate, + [Parameter(Mandatory, ParameterSetName = 'VaultAccessToken')] + [Parameter(ParameterSetName = 'AccessToken')] + [Parameter(ParameterSetName = 'TokenIntegrated')] + [Parameter(ParameterSetName = 'TokenOAuth')] + [Parameter(ParameterSetName = 'TokenCertificate')] + [string] $VaultAccessTokenName, + + [Parameter(Mandatory, ParameterSetName = 'VaultRefreshToken')] + [Parameter(ParameterSetName = 'RefreshToken')] + [Parameter(ParameterSetName = 'TokenIntegrated')] + [Parameter(ParameterSetName = 'TokenOAuth')] + [Parameter(ParameterSetName = 'TokenCertificate')] + [string] $VaultRefreshTokenName, + + [Parameter(ParameterSetName = 'TokenIntegrated')] + [Parameter(ParameterSetName = 'TokenOAuth')] + [Parameter(ParameterSetName = 'TokenCertificate')] + [Parameter(ParameterSetName = 'AccessToken')] + [Parameter(ParameterSetName = 'RefreshToken')] + [Parameter(ParameterSetName = 'VaultAccessToken')] + [Parameter(ParameterSetName = 'VaultRefreshToken')] + [switch] $VaultMetadata, + [Parameter(ParameterSetName = 'TokenOAuth')] [Parameter(ParameterSetName = 'TokenIntegrated')] [Parameter(ParameterSetName = 'TokenCertificate')] @@ -178,8 +245,22 @@ function New-VenafiSession { [string] $AuthServer, [Parameter(Mandatory, ParameterSetName = 'Vaas')] + [ValidateScript( { + try { + [guid] $_.GetNetworkCredential().password + $true + } + catch { + throw 'The value for -VaasKey is invalid and should be of the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + } + } + )] [PSCredential] $VaasKey, + [Parameter(ParameterSetName = 'Vaas')] + [Parameter(Mandatory, ParameterSetName = 'VaultVaasKey')] + [string] $VaultVaasKeyName, + [Parameter()] [switch] $PassThru ) @@ -192,18 +273,41 @@ function New-VenafiSession { $serverUrl = 'https://{0}' -f $serverUrl } + $authServerUrl = $serverUrl + if ( $AuthServer ) { + $authServerUrl = $AuthServer + if ( $authServerUrl -notlike 'https://*') { + $authServerUrl = 'https://{0}' -f $authServerUrl + } + } + $newSession = [VenafiSession] @{ ServerUrl = $serverUrl } + # use this to know if we need to re-store vault entry metadata when it already exists and -VaultMetadata not provided + $metadataStored = $false + Write-Verbose ('Parameter set: {0}' -f $PSCmdlet.ParameterSetName) + if ( $PSCmdlet.ParameterSetName -like 'Vault*') { + # ensure the appropriate setup has been performed + if ( -not (Get-Module -Name Microsoft.PowerShell.SecretManagement)) { + throw 'The module Microsoft.PowerShell.SecretManagement is required as well as a vault named ''VenafiPS''. See the github readme for guidance, https://github.com/gdbarron/VenafiPS#tokenkey-secret-storage.' + } + + $vault = Get-SecretVault -Name 'VenafiPS' -ErrorAction SilentlyContinue + if ( -not $vault ) { + throw 'A SecretManagement vault named ''VenafiPS'' could not be found' + } + } + if ( $PSCmdlet.ShouldProcess($Server, 'New session') ) { Switch ($PsCmdlet.ParameterSetName) { { $_ -in 'KeyCredential', 'KeyIntegrated' } { - Write-Warning 'Key-based authentication will be deprecated in release 20.4 in favor of token-based' + Write-Warning 'Key-based authentication will be deprecated in release 21.4 in favor of token-based. Get started with token authentication today, https://docs.venafi.com/Docs/current/TopNav/Content/SDK/AuthSDK/t-SDKa-Setup-OAuth.php.' if ( $PsCmdlet.ParameterSetName -eq 'KeyCredential' ) { $newSession.Connect($Credential) @@ -217,16 +321,11 @@ function New-VenafiSession { { $_ -in 'TokenOAuth', 'TokenIntegrated', 'TokenCertificate' } { $params = @{ - AuthServer = $serverUrl + AuthServer = $authServerUrl ClientId = $ClientId Scope = $Scope } - # in case the auth server isn't the same as vedsdk... - if ( $AuthServer ) { - $params.AuthServer = $AuthServer - } - if ($Credential) { $params.Credential = $Credential } @@ -246,6 +345,7 @@ function New-VenafiSession { 'AccessToken' { $newSession.Token = [PSCustomObject]@{ + Server = $authServerUrl AccessToken = $AccessToken } # we don't have the expiry so create one @@ -253,15 +353,86 @@ function New-VenafiSession { $newSession.Expires = (Get-Date).AddMonths(12) } + 'VaultAccessToken' { + $tokenSecret = Get-Secret -Name $VaultAccessTokenName -Vault 'VenafiPS' -ErrorAction SilentlyContinue + if ( -not $tokenSecret ) { + throw "'$VaultAccessTokenName' secret not found in vault VenafiPS." + } + + # check if metadata was stored or we should get from params + $secretInfo = Get-SecretInfo -Name $VaultAccessTokenName -Vault 'VenafiPS' -ErrorAction SilentlyContinue + + if ( $secretInfo.Metadata.Count -gt 0 ) { + $newSession.ServerUrl = $secretInfo.Metadata.Server + $newSession.Expires = $secretInfo.Metadata.Expires + $newSession.Token = [PSCustomObject]@{ + Server = $secretInfo.Metadata.AuthServer + AccessToken = $tokenSecret + ClientId = $secretInfo.Metadata.ClientId + } + + $metadataStored = $true + } + else { + # need to check params as not mandatory + if ( -not $Server -or -not $ClientId ) { + throw '-Server and -ClientId are required parameters as they weren''t stored with -VaultMetadata' + } + + $newSession.Token = [PSCustomObject]@{ + Server = $authServerUrl + AccessToken = $tokenSecret + } + # we don't have the expiry so create one + # rely on the api call itself to fail if access token is invalid + $newSession.Expires = (Get-Date).AddMonths(12) + } + } + 'RefreshToken' { $params = @{ - AuthServer = $serverUrl + AuthServer = $authServerUrl ClientId = $ClientId RefreshToken = $RefreshToken } - if ( $AuthServer ) { - $params.AuthServer = $AuthServer + + $newToken = New-TppToken @params + $newSession.Token = $newToken + $newSession.Expires = $newToken.Expires + } + + 'VaultRefreshToken' { + $tokenSecret = Get-Secret -Name $VaultRefreshTokenName -Vault 'VenafiPS' -ErrorAction SilentlyContinue + if ( -not $tokenSecret ) { + throw "'$VaultRefreshTokenName' secret not found in vault VenafiPS." + } + + # check if metadata was stored or we should get from params + $secretInfo = Get-SecretInfo -Name $VaultRefreshTokenName -Vault 'VenafiPS' -ErrorAction SilentlyContinue + + if ( $secretInfo.Metadata.Count -gt 0 ) { + $params = @{ + AuthServer = $secretInfo.Metadata.AuthServer + ClientId = $secretInfo.Metadata.ClientId + } + + $metadataStored = $true + + } + else { + # need to check params as not mandatory + if ( -not $Server -or -not $ClientId ) { + throw '-Server and -ClientId are required parameters as they weren''t stored with -VaultMetadata' + } + + $params = @{ + AuthServer = $authServerUrl + ClientId = $ClientId + } } + + $params.RefreshToken = $tokenSecret + $newToken = New-TppToken @params $newSession.Token = $newToken $newSession.Expires = $newToken.Expires @@ -272,16 +443,65 @@ function New-VenafiSession { $newSession.Key = $VaasKey } + 'VaultVaasKey' { + $newSession.ServerUrl = $script:CloudUrl + $keySecret = Get-Secret -Name $VaultVaasKeyName -Vault 'VenafiPS' -ErrorAction SilentlyContinue + if ( -not $keySecret ) { + throw "'$VaultVaasKeyName' secret not found in vault VenafiPS." + } + $newSession.Key = $keySecret + } + Default { throw ('Unknown parameter set {0}' -f $PSCmdlet.ParameterSetName) } } + if ( $VaultAccessTokenName ) { + # set new access token in vault + Set-Secret -Name $VaultAccessTokenName -Secret $newSession.Token.AccessToken -Vault 'VenafiPS' + } + + if ( $VaultRefreshTokenName ) { + # set new refresh token in vault + if ( $newSession.Token.RefreshToken ) { + Set-Secret -Name $VaultRefreshTokenName -Secret $newSession.Token.RefreshToken -Vault 'VenafiPS' + } + else { + Write-Warning 'Refresh token not provided by server and will not be saved in the vault' + } + } - # will fail if user is on an older version - # this isn't required so bypass on failure + if ( $VaultVaasKeyName ) { + # set new vaas key in vault + Set-Secret -Name $VaultVaasKeyName -Secret $newSession.Key -Vault 'VenafiPS' + } + + if ( $VaultMetadata.IsPresent -or $metadataStored ) { + if ( -not $VaultAccessTokenName -and -not $VaultRefreshTokenName) { + throw 'Vaulting metadata requires either -VaultAccessTokenName or -VaultRefreshTokenName is provided' + } + $metadata = @{ + Server = $newSession.ServerUrl + AuthServer = $newSession.Token.Server + ClientId = $newSession.Token.ClientId + Expires = $newSession.Expires + } + + $metadata | ConvertTo-Json | Write-Verbose + + if ( $VaultAccessTokenName ) { + Set-SecretInfo -Name $VaultAccessTokenName -Vault 'VenafiPS' -Metadata $metadata + } + + if ( $VaultRefreshTokenName ) { + Set-SecretInfo -Name $VaultRefreshTokenName -Vault 'VenafiPS' -Metadata $metadata + } + } - if ( $PSCmdlet.ParameterSetName -ne 'VaasKey' ) { + # will fail if user is on an older version. this isn't required so bypass on failure + # only applicable to tpp + if ( $PSCmdlet.ParameterSetName -notin 'VaasKey', 'VaultVaasKey' ) { $newSession.Version = (Get-TppVersion -VenafiSession $newSession -ErrorAction SilentlyContinue) $certFields = Get-TppCustomField -VenafiSession $newSession -Class 'X509 Certificate' -ErrorAction SilentlyContinue $deviceFields = Get-TppCustomField -VenafiSession $newSession -Class 'Device' -ErrorAction SilentlyContinue diff --git a/VenafiPS/VenafiPS.psd1 b/VenafiPS/VenafiPS.psd1 index 8db695a7..7d0f88fd 100644 --- a/VenafiPS/VenafiPS.psd1 +++ b/VenafiPS/VenafiPS.psd1 @@ -12,7 +12,7 @@ RootModule = 'VenafiPS.psm1' # Version number of this module. -ModuleVersion = '3.2.0' +ModuleVersion = '3.3' # Supported PSEditions # CompatiblePSEditions = @() @@ -69,26 +69,26 @@ PowerShellVersion = '5.1' # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = 'Add-TppCertificateAssociation', 'ConvertTo-TppGuid', - 'ConvertTo-TppPath', 'Export-VenafiCertificate', - 'Find-TppCertificate', 'Find-TppCodeSignEnvironment', - 'Find-TppCodeSignProject', 'Find-TppCodeSignTemplate', - 'Find-TppIdentity', 'Find-TppObject', 'Get-TppAttribute', - 'Get-TppCodeSignConfig', 'Get-TppCodeSignEnvironment', - 'Get-TppCodeSignProject', 'Get-TppCustomField', 'Get-TppIdentity', - 'Get-TppIdentityAttribute', 'Get-TppObject', 'Get-TppPermission', - 'Get-TppSystemStatus', 'Get-TppVersion', 'Get-TppWorkflowTicket', - 'Get-VaasApplication', 'Get-VaasOrgUnit', 'Get-VenafiCertificate', - 'Import-TppCertificate', 'Invoke-TppCertificatePush', - 'Invoke-TppCertificateRenewal', 'Invoke-VenafiRestMethod', - 'Move-TppObject', 'New-TppCapiApplication', 'New-TppCertificate', - 'New-TppCodeSignProject', 'New-TppDevice', 'New-TppObject', - 'New-TppPolicy', 'New-TppToken', 'New-VenafiSession', 'Read-TppLog', - 'Remove-TppCertificate', 'Remove-TppCertificateAssociation', - 'Remove-TppCodeSignEnvironment', 'Remove-TppCodeSignProject', - 'Remove-TppPermission', 'Rename-TppObject', 'Revoke-TppCertificate', - 'Revoke-TppToken', 'Set-TppAttribute', 'Set-TppCodeSignProjectStatus', - 'Set-TppPermission', 'Set-TppWorkflowTicketStatus', 'Test-ModuleHash', +FunctionsToExport = 'Add-TppCertificateAssociation', 'ConvertTo-TppGuid', + 'ConvertTo-TppPath', 'Export-VenafiCertificate', + 'Find-TppCertificate', 'Find-TppCodeSignEnvironment', + 'Find-TppCodeSignProject', 'Find-TppCodeSignTemplate', + 'Find-TppIdentity', 'Find-TppObject', 'Get-TppAttribute', + 'Get-TppCodeSignConfig', 'Get-TppCodeSignEnvironment', + 'Get-TppCodeSignProject', 'Get-TppCustomField', 'Get-TppIdentity', + 'Get-TppIdentityAttribute', 'Get-TppObject', 'Get-TppPermission', + 'Get-TppSystemStatus', 'Get-TppVersion', 'Get-TppWorkflowTicket', + 'Get-VaasApplication', 'Get-VaasOrgUnit', 'Get-VenafiCertificate', + 'Import-TppCertificate', 'Invoke-TppCertificatePush', + 'Invoke-TppCertificateRenewal', 'Invoke-VenafiRestMethod', + 'Move-TppObject', 'New-TppCapiApplication', 'New-TppCertificate', + 'New-TppCodeSignProject', 'New-TppDevice', 'New-TppObject', + 'New-TppPolicy', 'New-TppToken', 'New-VenafiSession', 'Read-TppLog', + 'Remove-TppCertificate', 'Remove-TppCertificateAssociation', + 'Remove-TppCodeSignEnvironment', 'Remove-TppCodeSignProject', + 'Remove-TppPermission', 'Rename-TppObject', 'Revoke-TppCertificate', + 'Revoke-TppToken', 'Set-TppAttribute', 'Set-TppCodeSignProjectStatus', + 'Set-TppPermission', 'Set-TppWorkflowTicketStatus', 'Test-ModuleHash', 'Test-TppIdentity', 'Test-TppObject', 'Test-TppToken', 'Write-TppLog' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.