OneTimeSecret.psm1
<#
____ _______ _ _____ _ / __ \ |__ __(_) / ____| | | | | | |_ __ ___| | _ _ __ ___ ___| (___ ___ ___ _ __ ___| |_ | | | | '_ \ / _ \ | | | '_ ` _ \ / _ \\___ \ / _ \/ __| '__/ _ \ __| | |__| | | | | __/ | | | | | | | | __/____) | __/ (__| | | __/ |_ \____/|_| |_|\___|_| |_|_| |_| |_|\___|_____/ \___|\___|_| \___|\__| #> $ExecutionContext.SessionState.Module.OnRemove = { } <# - Function: ConvertFrom-UnixTime #> function ConvertFrom-UnixTime { <# .SYNOPSIS Convert UNIX Time to a readable format .DESCRIPTION Convert UNIX Time to a readable format .PARAMETER UnixTime Unix Time .INPUTS System.String .OUTPUTS System.TimeZone .EXAMPLE ConvertFromUnixTime -UnixTime 777777 #> [CmdletBinding()][OutputType('System.DateTime')] Param ( [Parameter(Mandatory=$true, Position=0)] [ValidateNotNullOrEmpty()] [String]$UnixTime ) # --- Changed to Get-Date to support Core. This function will die soon. #[System.TimeZone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').` AddSeconds($UnixTime)) (Get-Date -Date 1/1/1970).AddSeconds($UnixTime) } <# - Function: Invoke-OTSRestMethod #> function Invoke-OTSRestMethod { <# .SYNOPSIS A module specific wrapper for Invoke-ResetMethod .DESCRIPTION A module specific wrapper for Invoke-ResetMethod .PARAMETER Method METHOD: GET, POST, PUT, DELETE .PARAMETER URI Service URI .PARAMETER QueryStringParameters A hashtable of query string parameters .PARAMETER Body Payload for the request, if applicable .PARAMETER Headers Optional Headers to send. This will override the default set provided .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE InvokeOTSRestMethod -Method POST -URI /v1/generate?passphrase=1234" .EXAMPLE $QueryStringParameters = @{ passphrase = "1234" } InvokeOTSRestMethod -Method POST -URI /v1/generate -QueryStringParameters $QueryStringParameters #> [CmdletBinding()][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory = $true)] [ValidateSet("GET", "POST", "PUT", "DELETE")] [String]$Method, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$URI, [Parameter(Mandatory = $false)] [Hashtable]$QueryStringParameters, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$Body, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Collections.IDictionary]$Headers ) try { # --- Grab the SessionState variable Test for connection variable if (!$Script:OTSConnectionInformation) { throw "Could not find OTSConnectionInformation. Please run Set-OTSConnectionInformation first" } # --- Build Uri $BaseUrl = $Script:OTSConnectionInformation.BaseUrl if (!$BaseUrl) { $BaseUrl = "https://onetimesecret.com/" } $UriBuilder = [System.UriBuilder]::new($BaseUrl) $UriBuilder.Path = "api/$URI" # --- Add query parameters $QueryString = [System.Web.HttpUtility]::ParseQueryString([string]::Empty) if ($PSBoundParameters.ContainsKey("QueryStringParameters")) { foreach ($Parameter in $QueryStringParameters.GetEnumerator()) { $QueryString.Add($Parameter.Key, $Parameter.Value) } } $UriBuilder.Query = $QueryString.ToString() # --- Get full Uri $FullURI = $UriBuilder.Uri # --- Build headers $Headers = @{ "Authorization" = "Basic $($Script:OTSConnectionInformation.Authorization)" } Write-Verbose -Message "Invoking request with headers $($Headers)" if ($PSBoundParameters.ContainsKey("Body")) { $Response = Invoke-RestMethod -Method $Method -Headers $Headers -Uri $FullURI -Body $Body -Verbose:$VerbosePrefernce } else { $Response = Invoke-RestMethod -Method $Method -Headers $Headers -Uri $FullURI -Verbose:$VerbosePreference } Write-Output $Response } catch [Exception] { throw $_ } finally { if (($PSVersionTable.PSEdition -eq "Desktop") -and $Script:OTSConnectionInformation) { $ServicePoint = "$($UriBuilder.Scheme)://$($UriBuilder.Host)" $ServicePoint = [System.Net.ServicePointManager]::FindServicePoint($ServicePoint) $ServicePoint.CloseConnectionGroup("") | Out-Null } } } <# - Function: Test-WebAddress #> function Test-WebAddress { <# .SYNOPSIS Validate a web address .DESCRIPTION Validate a web address .PARAMETER Address The address to validate .EXAMPLE Test-WebAddress -Address https://google.com #> [CmdletBinding()] Param( [Parameter(Mandatory = $true)] [String]$Address ) try { $URI = $Address -as [System.URI] $null -ne $URI.AbsoluteURI -and (($URI.Scheme -eq "http") -or ($URI.Scheme -eq "https")) } catch { Write-Error -Message "$_" -ErrorAction Stop } } <# - Function: Get-OTSAuthorizationToken #> function Get-OTSAuthorizationToken { <# .SYNOPSIS Retrieve the authorization token variable set by Set-OTSAuthorizationToken .DESCRIPTION Retrieve the authorization token variable set by Set-OTSAuthorizationToken .INPUTS None .OUTPUTS System.Management.Automation.PSObject .Example Get-OTSAuthorizationToken #> [CmdletBinding()][OutputType('System.Management.Automation.PSObject')] Param () try { # --- Grab the SessionState variable Test for connection variable if (!$Script:OTSConnectionInformation) { throw "Could not find OTSConnectionInformation. Please run Set-OTSAuthorizationToken first" } Write-Output $Script:OTSConnectionInformation } catch { throw $_ } } <# - Function: Get-OTSRecentMetadata #> function Get-OTSRecentMetadata { <# .SYNOPSIS Return recent secret metadata .DESCRIPTION Return recent secret metadata .OUTPUTS System.Management.Automation.PSObject .Example Get-OTSRecentMetadata #> [CmdletBinding()][OutputType('System.Management.Automation.PSObject')] Param () # --- Set URI with mandatory query parameters $URI = "v1/private/recent" try { $Response = Invoke-OTSRestMethod -Method GET -URI $URI -Verbose:$VerbosePreference foreach ($Metadata in $Response) { [PSCustomObject]@{ Custid = $Metadata.custid MetadataKey = $Metadata.metadata_key SecretKey = $Metadata.secret_key Ttl = $Metadata.ttl MetadataTtl = $Metadata.metadata_ttl SecretTtl = $Metadata.secret_ttl State = $Metadata.state Updated = (ConvertFrom-UnixTime -UnixTime $Metadata.updated).ToString() Created = (ConvertFrom-UnixTime -UnixTime $Metadata.created).ToString() Recipient = $Metadata.recipient PassphraseRequired = $Metadata.passphrase_required } } } catch { throw $_ } } <# - Function: Get-OTSSecret #> function Get-OTSSecret { <# .SYNOPSIS Retrieve a secret .DESCRIPTION Retrieve a secret .PARAMETER SecretKey The unique key for this secret .PARAMETER Passphrase The passphrase is required only if the secret was create with one .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .Example Get-OTSSecret -SecretKey qqevnp70b4uoiax4knzhwlhros6ne7x -Passphrase 1234 #> [CmdletBinding()][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateNotNullOrEmpty()] [String]$SecretKey, [Parameter(Mandatory=$false, Position=1)] [ValidateNotNullOrEmpty()] [String]$Passphrase ) # --- Set URI with mandatory query parameters $URI = "v1/secret/$($SecretKey)" try { $QueryStringParameters = @{} if ($PSBoundParameters.ContainsKey("Passphrase")) { Write-Verbose -Message "Adding Passphrase Query Parameter" $QueryStringParameters.Add("passphrase", $Passphrase) } $Response = Invoke-OTSRestMethod -Method POST -URI $URI -QueryStringParameters $QueryStringParameters -Verbose:$VerbosePreference [PSCustomObject]@{ SecretKey = $Response.secret_key Value = $Response.value } } catch { throw $_ } } <# - Function: Get-OTSSecretMetadata #> function Get-OTSSecretMetadata { <# .SYNOPSIS Retrieve metadata of a secret .DESCRIPTION Every secret also has associated metadata. The metadata is intended to be used by the creator of the secret (i.e. not the recipient) and should generally be kept private. You can safely use the metadata key to retrieve basic information about the secret itself (e.g. if or when it was viewed) since the metadata key is different from the secret key. .PARAMETER MetadataKey The unique key for the metadata .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .Example Get-OTSSecretMetaData -MetaDataKey allrfe8gf7edstynihtvrblgfuhbbuz #> [CmdletBinding()][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateNotNullOrEmpty()] [String]$MetadataKey ) # --- Set URI with mandatory query parameters $URI = "v1/private/$($MetadataKey)" try { $Response = Invoke-OTSRestMethod -Method POST -URI $URI -Verbose:$VerbosePreference [PSCustomObject]@{ CustId = $Response.custid MetadataKey = $Response.metadata_key SecretKey = $Response.secret_key Ttl = $Response.ttl MetadataTtl = $Response.metadata_ttl SecretTtl = $Response.secret_ttl State = $Response.state Updated = (ConvertFrom-UnixTime -UnixTime $Response.updated).ToString() Created = (ConvertFrom-UnixTime -UnixTime $Response.created).ToString() Recipient = $Response.recipient PassphraseRequired = $Response.passphrase_required } } catch { throw $_ } } <# - Function: Get-OTSSystemStatus #> function Get-OTSSystemStatus { <# .SYNOPSIS Get the current status of OneTimeSecret.com .DESCRIPTION Get the current status of OneTimeSecret.com .INPUTS None .OUTPUTS System.Management.Automation.PSObject .Example Get-OTSSystemStatus #> [CmdletBinding()][OutputType('System.Management.Automation.PSObject')] Param () # --- Set URI with mandatory query parameters $URI = "v1/status" try { $Response = Invoke-OTSRestMethod -Method GET -URI $URI -Verbose:$VerbosePreference [PSCustomObject]@{ Status = $Response.status } } catch { throw $_ } } <# - Function: New-OTSSecret #> function New-OTSSecret { <# .SYNOPSIS Generate a short, unique secret. This is useful for temporary passwords, one-time pads, salts, etc. .DESCRIPTION Generate a short, unique secret. This is useful for temporary passwords, one-time pads, salts, etc. .PARAMETER Passphrase A string that the recipient must know to view the secret. This value is also used to encrypt the secret and is bcrypted before being stored so we only have this value in transit. .PARAMETER Ttl The maximum amount of time, in seconds, that the secret should survive (i.e. time-to-live). Once this time expires, the secret will be deleted and not recoverable. .PARAMETER Recipient An email address. We will send a friendly email containing the secret link (NOT the secret itself). .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE New-OTSSecret -Passphrase 1234 -Recipient user@mail.com .EXAMPLE New-OTSSecret -Passphrase 1234 -Ttl 90000 -MetadataTtl 90000 -SecretTtil 90000 -Recipient user@mail.com #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Low")][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory = $false, Position = 0)] [ValidateNotNullOrEmpty()] [String]$Passphrase, [Parameter(Mandatory = $false, Position = 1)] [ValidateNotNullOrEmpty()] [String]$Ttl, [Parameter(Mandatory = $false, Position = 4)] [ValidateNotNullOrEmpty()] [String]$Recipient ) # --- Set URI with mandatory query parameters $URI = "v1/generate" try { $QueryStringParameters = @{} if ($PSBoundParameters.ContainsKey("Passphrase")) { Write-Verbose -Message "Adding Passphrase Query Parameter" $QueryStringParameters.Add("passphrase", $Passphrase) } if ($PSBoundParameters.ContainsKey("Ttl")) { Write-Verbose -Message "Adding Ttl Query Parameter" $QueryStringParameters.Add("ttl", $Ttl) } if ($PSBoundParameters.ContainsKey("Recipient")) { Write-Verbose -Message "Adding Recipient Parameter" $QueryStringParameters.Add("recipient", $Recipient) } if ($PSCmdlet.ShouldProcess("onetimesecret.com")) { $Response = Invoke-OTSRestMethod -Method POST -URI $URI -QueryStringParameters $QueryStringParameters -Verbose:$VerbosePreference [PSCustomObject]@{ CustId = $Response.custid MetadataKey = $Response.metadata_key SecretKey = $Response.secret_key Ttl = $Response.ttl MetadataTtl = $Response.metadata_ttl SecretTtl = $Response.secret_ttl State = $Response.state Updated = (ConvertFrom-UnixTime -UnixTime $Response.updated).ToString() Created = (ConvertFrom-UnixTime -UnixTime $Response.created).ToString() Recipient = $Response.recipient Value = $Response.value PassphraseRequired = $Response.passphrase_required } } } catch { throw $_ } } <# - Function: New-OTSSharedSecret #> function New-OTSSharedSecret { <# .SYNOPSIS Store and share a secret value .DESCRIPTION Store and share a secret value .PARAMETER Secret The secret value which is encrypted before being stored. There is a maximum length based on your plan that is enforced (1k-10k .PARAMETER Passphrase A string that the recipient must know to view the secret. This value is also used to encrypt the secret and is bcrypted before being stored so we only have this value in transit. .PARAMETER Ttl The maximum amount of time, in seconds, that the secret should survive (i.e. time-to-live). Once this time expires, the secret will be deleted and not recoverable. .PARAMETER Recipient An email address. We will send a friendly email containing the secret link (NOT the secret itself). .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE New-OTSSharedSecret -Secret "Very Secret" -Passphrase 12334 .EXAMPLE New-OTSSharedSecret -Secret "Very Secret" -Passphrase 1234 -Ttl 90000 -Recipient user@mail.com #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Low")][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [String]$Secret, [Parameter(Mandatory = $false, Position = 1)] [ValidateNotNullOrEmpty()] [String]$Passphrase, [Parameter(Mandatory = $false, Position = 2)] [ValidateNotNullOrEmpty()] [String]$Ttl, [Parameter(Mandatory = $false, Position = 3)] [ValidateNotNullOrEmpty()] [String]$Recipient ) # --- Set URI with mandatory query parameters $URI = "v1/share" try { $QueryStringParameters = @{} Write-Verbose -Message "Adding Secret Query Parameter" $QueryStringParameters.Add("secret", $Secret) if ($PSBoundParameters.ContainsKey("Passphrase")) { Write-Verbose -Message "Adding Passphrase Query Parameter" $QueryStringParameters.Add("passphrase", $Passphrase) } if ($PSBoundParameters.ContainsKey("Ttl")) { Write-Verbose -Message "Adding Ttl Query Parameter" $QueryStringParameters.Add("ttl", $Ttl) } if ($PSBoundParameters.ContainsKey("Recipient")) { Write-Verbose -Message "Adding Recipient Parameter" $QueryStringParameters.Add("recipient", $Recipient) } if ($PSCmdlet.ShouldProcess("onetimesecret.com")) { $Response = Invoke-OTSRestMethod -Method POST -URI $URI -QueryStringParameters $QueryStringParameters -Verbose:$VerbosePreference [PSCustomObject]@{ CustId = $Response.custid MetadataKey = $Response.metadata_key SecretKey = $Response.secret_key Ttl = $Response.ttl MetadataTtl = $Response.metadata_ttl SecretTtl = $Response.secret_ttl State = $Response.state Updated = (ConvertFrom-UnixTime -UnixTime $Response.updated).ToString() Created = (ConvertFrom-UnixTime -UnixTime $Response.created).ToString() Recipient = $Response.recipient PassphraseRequired = $Response.passphrase_required } } } catch { throw $_ } } <# - Function: Remove-OTSSecret #> function Remove-OTSSecret { <# .SYNOPSIS Burn a secren that has not been read yet. .DESCRIPTION Burn a secren that has not been read yet. Secrets with passphrases are currently not supported by this function .PARAMETER MetadataKey The unique key for the metadata .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .Example Remove-OTSSecret -MetaDataKey allrfe8gf7edstynihtvrblgfuhbbuz #> [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High")][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateNotNullOrEmpty()] [String]$MetadataKey ) # --- Set URI with mandatory query parameters $URI = "v1/private/$($MetadataKey)/burn" try { if ($PSCmdlet.ShouldProcess("onetimesecret.com")){ $Response = (Invoke-OTSRestMethod -Method POST -URI $URI -Verbose:$VerbosePreference).state [PSCustomObject]@{ CustId = $Response.custid MetadataKey = $Response.metadata_key SecretKey = $Response.secret_key Ttl = $Response.ttl MetadataTtl = $Response.metadata_ttl SecretTtl = $Response.secret_ttl State = $Response.state Updated = (ConvertFrom-UnixTime -UnixTime $Response.updated).ToString() Created = (ConvertFrom-UnixTime -UnixTime $Response.created).ToString() Recipient = $Response.recipient PassphraseRequired = $Response.passphrase_required } } } catch { throw "$_ - This command does not support secrets with passphrases!" } } <# - Function: Set-OTSAuthorizationToken #> function Set-OTSAuthorizationToken { <# .SYNOPSIS Create the Authorization information required to interact with the OneTimeSecret.com API .DESCRIPTION Create the Authorization information required to interact with the OneTimeSecret.com API .PARAMETER Username The Username of the account .PARAMETER APIKey The API key for the account .PARAMETER BaseUrl Use a custom instance of onetimesecret. Defaults to https://onetimesecret.com/ .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Set-OTSAuthorizationToken -Username user@mail.com -APIKey 52302308erf2e799affd33cbc7c85896b4c6a6997 .EXAMPLE Set-OTSAuthorizationToken -Username user@mail.com -APIKey 52302308erf2e799affd33cbc7c85896b4c6a6997 -BaseUrl https://mycustomhost.com/ #> [CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low")][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory=$true, Position=0)] [ValidateNotNullOrEmpty()] [String]$Username, [Parameter(Mandatory=$true, Position=1)] [ValidateNotNullOrEmpty()] [String]$APIKey, [Parameter(Mandatory=$false, Position=2)] [ValidateNotNullOrEmpty()] [String]$BaseUrl = "https://onetimesecret.com/" ) if ($PSCmdlet.ShouldProcess("onetimesecret")){ try { $EncodedAuth = [System.Text.Encoding]::UTF8.GetBytes("$($Username):$($APIKey)") $Script:OTSConnectionInformation = [PSCustomObject]@{ Authorization = [System.Convert]::ToBase64String($EncodedAuth) } if ($PSBoundParameters.ContainsKey("BaseUrl")){ if (!(Test-WebAddress -Address $BaseUrl)) { Write-Error -Message "The url provided was not valid: $BaseUrl" -ErrorAction Stop } if (!$BaseUrl.EndsWith("/")) { $BaseUrl = $BaseUrl + "/" } $Script:OTSConnectionInformation | Add-Member -MemberType NoteProperty -Name BaseUrl -Value $BaseUrl } Write-Output $Script:OTSConnectionInformation } catch { throw $_ } } } |