Posh-HIBP.psm1
#region Setup function Get-HibpCredential { [CmdletBinding()] Param () $aKeyPtr = [IntPtr]::Zero try { $secureKey = $env:HibpApiKey | ConvertTo-SecureString -ErrorAction SilentlyContinue if (-not $secureKey) { return $null } $aKeyPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($secureKey) $aKey = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($aKeyPtr) } catch { return $null } finally { # Always free the unmanaged memory to reduce exposure of sensitive data. if ($aKeyPtr -ne [IntPtr]::Zero) { [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($aKeyPtr) } } return $aKey } function Remove-HibpCredential { [CmdletBinding()] Param () $apiKeyVarName = 'HibpApiKey' if (Test-Path -Path ('env:{0}' -f $apiKeyVarName)) { Remove-Item -Path ('env:{0}' -f $apiKeyVarName) } if (Test-Path "HKCU:\Environment\$apiKeyVarName") { Remove-ItemProperty -Path "HKCU:\Environment" -Name $apiKeyVarName } } function Save-HibpCredential { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [string]$ApiKey ) $apiKeyVarName = 'HibpApiKey' # Securely stores the API key as an encrypted string in a user-level environment variable. $secureKey = ConvertTo-SecureString -String $ApiKey -AsPlainText -Force $encryptedKey = ConvertFrom-SecureString -SecureString $secureKey # Set for future sessions for the current user [System.Environment]::SetEnvironmentVariable($apiKeyVarName, $encryptedKey, 'User') # Setting for use in the current process, as it is necessary to reload the profile to make environmental variables available. $env:HibpApiKey = $encryptedKey } #endregion #region Private Functions function Initialize-HibpRequirements { # Ensures TLS 1.2 is enabled for web requests. # This relies on the 'core' module being available. if (-not ([System.Net.ServicePointManager]::SecurityProtocol.HasFlag([System.Net.SecurityProtocolType]::Tls12))) { try { Set-WebSecurityProtocol -Protocols 'TLS1.2' -Append -Quiet } catch { Write-Warning "Failed to set TLS 1.2. API calls may fail. Error: $_" } } } function Invoke-HibpRequest { [CmdletBinding()] Param( [Parameter(Mandatory = $true)] [string]$Endpoint, [System.Collections.IDictionary]$QueryParameter, [string]$ApiKey = (Get-HibpCredential) ) Initialize-HibpRequirements if (-not $ApiKey) { throw 'HIBP API key not found. Provide the key using the -ApiKey parameter or by running Save-HibpCredential.' } $headers = @{ 'hibp-api-key' = $ApiKey 'user-agent' = 'Posh-HIBP-PowerShell-Module' } $baseUri = 'https://haveibeenpwned.com/api/v3' $uri = '{0}/{1}' -f $baseUri, $Endpoint if ($QueryParameter) { $query = $QueryParameter.GetEnumerator() | ForEach-Object { '{0}={1}' -f $_.Key, ([System.Web.HttpUtility]::UrlEncode($_.Value)) } $uri = '{0}?{1}' -f $uri, ($query -join '&') } try { Invoke-RestMethod -Uri $uri -Method Get -Headers $headers -ErrorAction Stop } catch { $response = $_.Exception.Response if ($null -ne $response) { $statusCode = $response.StatusCode.value__ Write-Error ('API request failed with status code {0}. Message: {1}' -f $statusCode, $_.Exception.Message) } else { Write-Error ('An unknown error occurred: {0}' -f $_.Exception.Message) } } } #endregion #region Public Functions $publicFunctionPath = Join-Path -Path $PSScriptRoot -ChildPath 'Public' $publicFunctions = @() if (Test-Path -Path $publicFunctionPath) { $functionFiles = Get-ChildItem -Path $publicFunctionPath -Filter *.ps1 foreach ($file in $functionFiles) { try { . $file.FullName $publicFunctions += $file.BaseName Write-Verbose "Imported function $($file.BaseName)" } catch { Write-Error "Failed to import function $($file.FullName): $_" } } } else { Write-Warning "No Public functions directory found at $publicFunctionPath" } Export-ModuleMember -Function $publicFunctions #endregion |