Private/Client.psm1
|
#!/usr/bin/env pwsh using namespace System using namespace System.Threading.Tasks using namespace System.Collections.Generic using module ./Api.psm1 using module ./Model.psm1 using module ./Util.psm1 using module ./Exceptions.psm1 #Requires -Modules clihelper.xconvert class UniversalAuth { hidden [ValidateNotNullOrEmpty()][ApiClient] $_apiClient hidden [ValidateNotNullOrEmpty()][scriptblock] $_setAccessTokenFunc UniversalAuth([ApiClient]$apiClient, [scriptblock]$setAccessTokenFunc) { $this._apiClient = $apiClient $this._setAccessTokenFunc = $setAccessTokenFunc } [Task[MachineIdentityCredential]] LoginAsync([string]$clientId) { return $this.LoginAsync($clientId, $this._apiClient.clientSecret) } [Task[MachineIdentityCredential]] LoginAsync([string]$clientId, [securestring]$clientSecret) { try { $loginRequest = [UniversalAuthLoginRequest]::new($clientId, $clientSecret) $responseObject = $this._apiClient.PostAsync([MachineIdentityCredential], "/api/v1/auth/universal-auth/login", $loginRequest).GetAwaiter().GetResult() $response = [MachineIdentityCredential]$responseObject $this._apiClient.SetAccessToken($response.AccessToken) return [Task]::FromResult($response) } catch { throw [InfisicalException]::new("Failed to login", $_.Exception) } } } class LdapAuth { hidden [ApiClient] $_apiClient hidden [scriptblock] $_setAccessTokenFunc LdapAuth([ApiClient]$apiClient, [scriptblock]$setAccessTokenFunc) { $this._apiClient = $apiClient $this._setAccessTokenFunc = $setAccessTokenFunc } [Task[MachineIdentityCredential]] LoginAsync([string]$identityId, [string]$username, [securestring]$password) { try { $loginRequest = [LdapAuthLoginRequest]::new($identityId, $username, $password) $responseObject = $this._apiClient.PostAsync([MachineIdentityCredential], "/api/v1/auth/ldap-auth/login", $loginRequest).GetAwaiter().GetResult() $response = [MachineIdentityCredential]$responseObject $this._apiClient.SetAccessToken($response.AccessToken) return [Task]::FromResult($response) } catch { throw [InfisicalException]::new("Failed to login", $_.Exception) } } } class AuthClient { hidden [ApiClient] $_apiClient hidden [UniversalAuth] $_universalAuth hidden [LdapAuth] $_ldapAuth hidden [scriptblock] $_setAccessTokenFunc AuthClient([ApiClient]$apiClient, [scriptblock]$setAccessTokenFunc) { $this._apiClient = $apiClient $this._setAccessTokenFunc = $setAccessTokenFunc $this._universalAuth = [UniversalAuth]::new($this._apiClient, $this._setAccessTokenFunc) $this._ldapAuth = [LdapAuth]::new($this._apiClient, $this._setAccessTokenFunc) } [UniversalAuth] UniversalAuth() { return $this._universalAuth } [LdapAuth] LdapAuth() { return $this._ldapAuth } } class Subscribers { hidden [ApiClient] $_apiClient Subscribers([ApiClient]$apiClient) { $this._apiClient = $apiClient } [Task[CertificateBundle]] RetrieveLatestCertificateBundleAsync([RetrieveLatestCertificateBundleOptions]$options) { try { $options.Validate() $dict = [ObjectToDictionaryConverter]::ToDictionary($options, $false) $responseObject = $this._apiClient.GetAsync([CertificateBundle], "/api/v1/pki/subscribers/$($options.SubscriberName)/latest-certificate-bundle", $dict).GetAwaiter().GetResult() $response = [CertificateBundle]$responseObject return [Task]::FromResult($response) } catch { throw [InfisicalException]::new("Failed to retrieve latest certificate bundle", $_.Exception) } } [Task[SubscriberIssuedCertificate]] IssueCertificateAsync([IssueCertificateOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([SubscriberIssuedCertificate], "/api/v1/pki/subscribers/$($options.SubscriberName)/issue-certificate", $options, $true).GetAwaiter().GetResult() $response = [SubscriberIssuedCertificate]$responseObject return [Task]::FromResult($response) } catch { throw [InfisicalException]::new("Failed to issue certificate", $_.Exception) } } } class PkiClient { hidden [ApiClient] $_apiClient hidden [Subscribers] $_subscribers PkiClient([ApiClient]$apiClient) { $this._apiClient = $apiClient $this._subscribers = [Subscribers]::new($this._apiClient) } [Subscribers] Subscribers() { return $this._subscribers } } class SecretsClient { hidden [ApiClient] $_apiClient SecretsClient([ApiClient]$apiClient) { $this._apiClient = $apiClient } [Task[InfisicalSecret[]]] ListAsync([ListSecretsOptions]$options) { try { $options.Validate() $dict = [ObjectToDictionaryConverter]::ToDictionary($options, $false) $dict.Remove("tagSlugs") | Out-Null if ($null -ne $options.TagSlugs -and $options.TagSlugs.Length -gt 0) { $dict["tagSlugs"] = [string]::Join(",", $options.TagSlugs) } $responseObject = $this._apiClient.GetAsync([ListSecretsResponse], "/api/v3/secrets/raw", $dict).GetAwaiter().GetResult() $response = [ListSecretsResponse]$responseObject $secretsList = [System.Collections.Generic.List[InfisicalSecret]]::new() if ($null -ne $response.Secrets) { foreach ($s in $response.Secrets) { $secretsList.Add($s) } } if ($options.Recursive -eq $true) { [SecretsUtil]::EnsureUniqueSecretsByKey($secretsList) } if ($options.IncludeImports -eq $true -and $null -ne $response.Imports -and $response.Imports.Length -gt 0) { foreach ($import in $response.Imports) { if ($null -ne $import.Secrets -and $import.Secrets.Length -gt 0) { foreach ($importSecret in $import.Secrets) { $found = $false foreach ($s in $secretsList) { if ($s.SecretKey -eq $importSecret.SecretKey) { $found = $true break } } if (!$found) { if ($null -ne $options.ProjectId) { $importSecret.ProjectId = $options.ProjectId } $importSecret.SecretPath = $import.SecretPath $secretsList.Add($importSecret) } } } } } if ($options.SetSecretsAsEnvironmentVariables -eq $true) { foreach ($secret in $secretsList) { if ($null -eq [Environment]::GetEnvironmentVariable($secret.SecretKey)) { [Environment]::SetEnvironmentVariable($secret.SecretKey, $secret.SecretValue) } } } return [Task]::FromResult($secretsList.ToArray()) } catch { throw [InfisicalException]::new("Failed to list secrets", $_.Exception) } } [Task[InfisicalSecret]] GetAsync([GetSecretOptions]$options) { try { $options.Validate() $dict = [ObjectToDictionaryConverter]::ToDictionary($options, $false) $responseObject = $this._apiClient.GetAsync([GetSecretResponse], "/api/v3/secrets/raw/$($options.SecretName)", $dict).GetAwaiter().GetResult() $response = [GetSecretResponse]$responseObject if ([string]::IsNullOrEmpty($response.Secret.SecretPath)) { $response.Secret.SecretPath = $options.SecretPath } return [Task]::FromResult($response.Secret) } catch { throw [InfisicalException]::new("Failed to get secret", $_.Exception) } } [Task[InfisicalSecret]] CreateAsync([CreateSecretOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([CreateSecretResponse], "/api/v3/secrets/raw/$($options.SecretName)", $options, $true).GetAwaiter().GetResult() $response = [CreateSecretResponse]$responseObject return [Task]::FromResult($response.Secret) } catch { throw [InfisicalException]::new("Failed to create secret", $_.Exception) } } [Task[InfisicalSecret]] UpdateAsync([UpdateSecretOptions]$options) { try { $options.Validate() # Use ToSerializableHashtable() to exclude null/empty optional fields. # Direct JSON serialization would coerce $null strings to "" in PowerShell, # causing the API to return 422 (e.g. newSecretName must be >= 1 char). $bodyHashtable = $options.ToSerializableHashtable() $responseObject = $this._apiClient.PatchAsync([UpdateSecretResponse], "/api/v3/secrets/raw/$($options.SecretName)", $bodyHashtable, $true).GetAwaiter().GetResult() $response = [UpdateSecretResponse]$responseObject return [Task]::FromResult($response.Secret) } catch { throw [InfisicalException]::new("Failed to update secret", $_.Exception) } } [Task[InfisicalSecret]] DeleteAsync([DeleteSecretOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.DeleteAsync([DeleteSecretResponse], "/api/v3/secrets/raw/$($options.SecretName)", $options, $true).GetAwaiter().GetResult() $response = [DeleteSecretResponse]$responseObject return [Task]::FromResult($response.Secret) } catch { throw [InfisicalException]::new("Failed to delete secret", $_.Exception) } } } class IdentitiesClient { hidden [ApiClient] $_apiClient IdentitiesClient([ApiClient]$apiClient) { $this._apiClient = $apiClient } [Task[System.Text.Json.JsonElement]] AddProjectAdditionalPrivilegeAsync([AddIdentityProjectAdditionalPrivilegeOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([IdentityProjectAdditionalPrivilegeResponse], "/api/v2/identity-project-additional-privilege", $options, $true).GetAwaiter().GetResult() $response = [IdentityProjectAdditionalPrivilegeResponse]$responseObject return [Task]::FromResult($response.Privilege) } catch { $innerMessage = if ($null -ne $_.Exception) { $_.Exception.Message } else { $_.ToString() } throw [InfisicalException]::new("Failed to add additional privilege: $innerMessage", $_.Exception) } } } class KmsClient { hidden [ApiClient] $_apiClient KmsClient([ApiClient]$apiClient) { $this._apiClient = $apiClient } [Task[object[]]] ListKeysAsync([ListKmsKeysOptions]$options) { try { $dict = [ObjectToDictionaryConverter]::ToDictionary($options, $false) $responseObject = $this._apiClient.GetAsync([KmsKeysResponse], "/api/v1/kms/keys", $dict).GetAwaiter().GetResult() $response = [KmsKeysResponse]$responseObject return [Task]::FromResult($response.Keys) } catch { throw [InfisicalException]::new("Failed to list KMS keys", $_.Exception) } } [Task[object]] GetKeyByIdAsync([GetKmsKeyByIdOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.GetAsync([KmsKeyResponse], "/api/v1/kms/keys/$($options.KeyId)", @{}).GetAwaiter().GetResult() $response = [KmsKeyResponse]$responseObject return [Task]::FromResult($response.Key) } catch { throw [InfisicalException]::new("Failed to get KMS key by ID", $_.Exception) } } [Task[object]] GetKeyByNameAsync([GetKmsKeyByNameOptions]$options) { try { $options.Validate() $queryParams = [System.Collections.Generic.Dictionary[string,string]]::new() $queryParams["projectId"] = $options.ProjectId $responseObject = $this._apiClient.GetAsync([KmsKeyResponse], "/api/v1/kms/keys/key-name/$($options.KeyName)", $queryParams).GetAwaiter().GetResult() $response = [KmsKeyResponse]$responseObject return [Task]::FromResult($response.Key) } catch { throw [InfisicalException]::new("Failed to get KMS key by name", $_.Exception) } } [Task[object]] CreateKeyAsync([CreateKmsKeyOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([KmsKeyResponse], "/api/v1/kms/keys", $options, $true).GetAwaiter().GetResult() $response = [KmsKeyResponse]$responseObject return [Task]::FromResult($response.Key) } catch { throw [InfisicalException]::new("Failed to create KMS key", $_.Exception) } } [Task[object]] UpdateKeyAsync([UpdateKmsKeyOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PatchAsync([KmsKeyResponse], "/api/v1/kms/keys/$($options.KeyId)", $options, $true).GetAwaiter().GetResult() $response = [KmsKeyResponse]$responseObject return [Task]::FromResult($response.Key) } catch { throw [InfisicalException]::new("Failed to update KMS key", $_.Exception) } } [Task[object]] DeleteKeyAsync([DeleteKmsKeyOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.DeleteAsync([KmsKeyResponse], "/api/v1/kms/keys/$($options.KeyId)", $options, $true).GetAwaiter().GetResult() $response = [KmsKeyResponse]$responseObject return [Task]::FromResult($response.Key) } catch { throw [InfisicalException]::new("Failed to delete KMS key", $_.Exception) } } [Task[string]] RetrievePublicKeyAsync([RetrieveKmsPublicKeyOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.GetAsync([KmsPublicKeyResponse], "/api/v1/kms/keys/$($options.KeyId)/public-key", @{}).GetAwaiter().GetResult() $response = [KmsPublicKeyResponse]$responseObject return [Task]::FromResult($response.PublicKey) } catch { throw [InfisicalException]::new("Failed to retrieve KMS public key", $_.Exception) } } [Task[string]] ExportPrivateKeyAsync([ExportKmsPrivateKeyOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.GetAsync([KmsPrivateKeyResponse], "/api/v1/kms/keys/$($options.KeyId)/private-key", @{}).GetAwaiter().GetResult() $response = [KmsPrivateKeyResponse]$responseObject return [Task]::FromResult($response.PrivateKey) } catch { throw [InfisicalException]::new("Failed to export KMS private key", $_.Exception) } } [Task[object[]]] BulkExportPrivateKeysAsync([BulkExportPrivateKeysOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([KmsBulkExportPrivateKeysResponse], "/api/v1/kms/keys/bulk-export-private-keys", $options, $true).GetAwaiter().GetResult() $response = [KmsBulkExportPrivateKeysResponse]$responseObject return [Task]::FromResult($response.Keys) } catch { throw [InfisicalException]::new("Failed to bulk export KMS private keys", $_.Exception) } } [Task[string]] EncryptDataAsync([EncryptKmsDataOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([KmsEncryptResponse], "/api/v1/kms/keys/$($options.KeyId)/encrypt", $options, $true).GetAwaiter().GetResult() $response = [KmsEncryptResponse]$responseObject return [Task]::FromResult($response.Ciphertext) } catch { throw [InfisicalException]::new("Failed to encrypt KMS data", $_.Exception) } } [Task[string]] DecryptDataAsync([DecryptKmsDataOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([KmsDecryptResponse], "/api/v1/kms/keys/$($options.KeyId)/decrypt", $options, $true).GetAwaiter().GetResult() $response = [KmsDecryptResponse]$responseObject return [Task]::FromResult($response.Plaintext) } catch { throw [InfisicalException]::new("Failed to decrypt KMS data", $_.Exception) } } [Task[string]] SignDataAsync([SignKmsDataOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([KmsSignResponse], "/api/v1/kms/keys/$($options.KeyId)/sign", $options, $true).GetAwaiter().GetResult() $response = [KmsSignResponse]$responseObject return [Task]::FromResult($response.Signature) } catch { throw [InfisicalException]::new("Failed to sign KMS data", $_.Exception) } } [Task[bool]] VerifySignatureAsync([VerifyKmsSignatureOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.PostAsync([KmsVerifyResponse], "/api/v1/kms/keys/$($options.KeyId)/verify", $options, $true).GetAwaiter().GetResult() $response = [KmsVerifyResponse]$responseObject return [Task]::FromResult($response.IsValid) } catch { throw [InfisicalException]::new("Failed to verify KMS signature", $_.Exception) } } [Task[string[]]] ListSigningAlgorithmsAsync([ListKmsSigningAlgorithmsOptions]$options) { try { $options.Validate() $responseObject = $this._apiClient.GetAsync([KmsSigningAlgorithmsResponse], "/api/v1/kms/keys/$($options.KeyId)/signing-algorithms", @{}).GetAwaiter().GetResult() $response = [KmsSigningAlgorithmsResponse]$responseObject return [Task]::FromResult($response.SigningAlgorithms) } catch { throw [InfisicalException]::new("Failed to list KMS signing algorithms", $_.Exception) } } } |