Private/Resolve-PCOciIdentity.ps1

function Resolve-PCOciIdentity {
    <#
    .SYNOPSIS
        Resolves the five identity values in the order of D-008, never prompting.

    .DESCRIPTION
        Order: values passed as parameters; the PowerCraft.Secrets entry named 'oci' (when the module is loaded);
        a profile in the OCI config file; the OCI_CLI_* environment variables. Naming -ProfileName or -ConfigFile
        goes straight to the config file, because the caller has said where the identity lives.
        A secret that carries a 'key' property is refused (D-015): the key stays in a file named by 'keyFile'.
    #>

    [CmdletBinding()]
    [OutputType([PowerCraft.OCI.Core.Identity.IdentityValues])]
    param(
        [hashtable]$Values,
        [string]$ProfileName,
        [string]$ConfigFile,
        [scriptblock]$SecretsProvider = {
            if (Get-Command Get-PCSecret -ErrorAction SilentlyContinue) {
                try { Get-PCSecret -Name 'oci' -AsHashtable -ErrorAction Stop } catch { $null }
            }
        }
    )

    if ($Values) {
        $identity = [PowerCraft.OCI.Core.Identity.IdentityValues]::new()
        $identity.Tenancy = [string]$Values.tenancy
        $identity.User = [string]$Values.user
        $identity.Fingerprint = [string]$Values.fingerprint
        $identity.KeyFile = [string]$Values.keyFile
        $identity.Region = [string]$Values.region
        if ($Values.passPhrase) { $identity.PassPhrase = [string]$Values.passPhrase }
        $identity.Source = [PowerCraft.OCI.Core.Identity.IdentityValues]::SourceParameter
        $identity.Validate()
        return $identity
    }

    $explicitConfig = $PSBoundParameters.ContainsKey('ProfileName') -or $PSBoundParameters.ContainsKey('ConfigFile')
    if (-not $explicitConfig) {
        $secret = & $SecretsProvider
        if ($secret) {
            if ($secret.ContainsKey('key')) {
                throw "The PowerCraft.Secrets entry 'oci' carries a 'key' property. PowerCraft.OCI reads the key from a file named by 'keyFile' and never from the secret store (decision D-015)."
            }
            $identity = [PowerCraft.OCI.Core.Identity.IdentityValues]::new()
            $identity.Tenancy = [string]$secret.tenancy
            $identity.User = [string]$secret.user
            $identity.Fingerprint = [string]$secret.fingerprint
            $identity.KeyFile = [string]$secret.keyFile
            $identity.Region = [string]$secret.region
            if ($secret.passPhrase) { $identity.PassPhrase = [string]$secret.passPhrase }
            $identity.Source = [PowerCraft.OCI.Core.Identity.IdentityValues]::SourceSecrets
            $identity.Validate()
            return $identity
        }
    }

    $path = if ($ConfigFile) { $ConfigFile } else { [PowerCraft.OCI.Core.Identity.ConfigProfileReader]::DefaultPath() }
    $profileToRead = if ($ProfileName) { $ProfileName } else { [PowerCraft.OCI.Core.Identity.ConfigProfileReader]::DefaultProfile }
    $fromConfig = [PowerCraft.OCI.Core.Identity.ConfigProfileReader]::Read($path, $profileToRead)
    if ($fromConfig) {
        $fromConfig.Validate()
        return $fromConfig
    }
    if ($explicitConfig) {
        throw "No profile '$profileToRead' in '$path'."
    }

    $getter = [Func[string, string]] { param($name) [Environment]::GetEnvironmentVariable($name) }
    $fromEnvironment = [PowerCraft.OCI.Core.Identity.IdentityValues]::FromEnvironment($getter)
    if ($fromEnvironment) { return $fromEnvironment }

    throw "No OCI identity found. Pass -Tenancy, -User, -Fingerprint, -KeyFile and -Region; or store a PowerCraft.Secrets entry named 'oci' with those properties; or add a profile to '$path'; or set OCI_CLI_TENANCY, OCI_CLI_USER, OCI_CLI_FINGERPRINT, OCI_CLI_KEY_FILE and OCI_CLI_REGION."
}

function Get-PCOciContextOrThrow {
    [CmdletBinding()]
    [OutputType([PowerCraft.OCI.Core.Identity.OciContext])]
    param([PowerCraft.OCI.Core.Identity.OciContext]$Context)

    if ($Context) { return $Context }
    if ($script:PCOciContext) { return $script:PCOciContext }
    throw 'No OCI context. Run Connect-PCOci first, or pass -Context.'
}

function ConvertTo-PCOciPlainText {
    [CmdletBinding()]
    [OutputType([string])]
    param([securestring]$Secure)

    if (-not $Secure) { return $null }
    return [System.Net.NetworkCredential]::new('', $Secure).Password
}