modules/Azure/Infrastructure/Tests/E2E/Azure/Authentication/certificate.Tests.ps1

BeforeAll {
    $projectRoot = Resolve-Path (Join-Path $PSScriptRoot '..' '..' '..' '..' '..' '..' '..' '..')
    . (Join-Path $projectRoot 'psu-app' 'Tests' 'E2E' 'PesterE2EHelper.ps1')
    Initialize-PesterE2E -ProjectRoot $projectRoot

    # Test data constants — all prefixed for cleanup
    $script:TestPrefix = '_E2E_TEST_'
    $script:ProfileId1 = "_E2E_TEST_cert_$(Get-Random -Maximum 99999)"
    $script:ProfileId2 = "_E2E_TEST_cert2_$(Get-Random -Maximum 99999)"
    $script:FakeTenantId = '00000000-0000-0000-0000-000000000000'
    $script:FakeClientId = '11111111-1111-1111-1111-111111111111'

    # Verify PSU is reachable and CIEM module is loaded
    $script:psuPing = Run-OnPSU 'Get-Command Get-CIEMAzureAuthenticationProfile -ErrorAction Stop | Select-Object -ExpandProperty Name'
    if ($script:psuPing -ne 'Get-CIEMAzureAuthenticationProfile') {
        throw "Local PSU not reachable or CIEM module not loaded. Start with: ./scripts/setup-local-psu.sh start"
    }

    # Discover real cert profile or the cert secret for connection tests
    # The cert PFX is stored in PSU vault — we need the TenantId/ClientId from an existing profile
    $realProfile = Run-OnPSU @'
        $certProfile = @(Get-CIEMAzureAuthenticationProfile -Method 'ServicePrincipalCertificate') | Select-Object -First 1
        if ($certProfile) {
            $certProfile | Select-Object Id, Name, Method, TenantId, ClientId, SecretName
        } else {
            # Fall back: check if a cert PFX exists in vault and reuse SP profile's tenant/client
            $hasCertPfx = $null -ne (Get-PSUVariable -Name 'CIEM_Azure_azure-default_CertPfx' -ErrorAction SilentlyContinue)
            $spProfile = @(Get-CIEMAzureAuthenticationProfile -Method 'ServicePrincipalSecret') | Select-Object -First 1
            if ($hasCertPfx -and $spProfile) {
                [PSCustomObject]@{
                    Id = $null
                    Name = $null
                    Method = 'ServicePrincipalCertificate'
                    TenantId = $spProfile.TenantId
                    ClientId = $spProfile.ClientId
                    SecretName = 'CIEM_Azure_azure-default_CertPfx'
                }
            } else {
                $null
            }
        }
'@


    if (-not $realProfile -or -not $realProfile.TenantId) {
        throw "No certificate credentials found. Local PSU must have a CertPfx secret in vault and a profile with TenantId/ClientId."
    }

    $script:realCertTenantId = $realProfile.TenantId
    $script:realCertClientId = $realProfile.ClientId
    $script:realCertSecretName = if ($realProfile.SecretName) { $realProfile.SecretName } else { 'CIEM_Azure_azure-default_CertPfx' }
    $script:realCertProfileId = $realProfile.Id  # may be null if no dedicated cert profile exists

    # Save the original active profile so we can restore it
    $activeProfile = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -IsActive `$true | Select-Object -First 1 | Select-Object Id"
    $script:originalActiveProfileId = if ($activeProfile) { $activeProfile.Id } else { $null }
}

AfterAll {
    $prefix = $script:TestPrefix
    try {
        Run-OnPSU @"
            @(Get-CIEMAzureAuthenticationProfile) | Where-Object { `$_.Id -like '${prefix}*' } | ForEach-Object {
                Remove-CIEMAzureAuthenticationProfile -Id `$_.Id -Confirm:`$false
            }
            'cleanup_done'
"@

    }
    catch { Write-Warning "E2E cleanup failed: $_" }

    # Restore original active profile
    if ($script:originalActiveProfileId) {
        try { Run-OnPSU "Set-CIEMAzureAuthenticationProfileActive -Id '$($script:originalActiveProfileId)'" }
        catch { Write-Warning "Failed to restore active profile: $_" }
    }
}

Describe 'Azure ServicePrincipalCertificate Authentication E2E' -Skip {

    Context 'PSU health check' {
        It 'CIEM module is loaded and functions are available' {
            $script:psuPing | Should -Be 'Get-CIEMAzureAuthenticationProfile'
        }
    }

    Context 'Profile Create' {
        BeforeAll {
            $id = $script:ProfileId1
            $tenantId = $script:FakeTenantId
            $clientId = $script:FakeClientId
            $prefix = $script:TestPrefix

            $script:created = Run-OnPSU @"
                New-CIEMAzureAuthenticationProfile ``
                    -Id '$id' ``
                    -ProviderId 'Azure' ``
                    -Name '${prefix}Cert Profile' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' ``
                    -ClientId '$clientId' ``
                    -SecretName 'test_cert_pfx' ``
                    -IsActive `$false
"@

        }

        AfterAll {
            $id = $script:ProfileId1
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '$id' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'Returns a profile object' {
            $script:created | Should -Not -BeNullOrEmpty
        }

        It 'Profile Id matches requested value' {
            $script:created.Id | Should -Be $script:ProfileId1
        }

        It 'Profile Name matches requested value' {
            $script:created.Name | Should -Be "${script:TestPrefix}Cert Profile"
        }

        It 'Profile Method is ServicePrincipalCertificate' {
            $script:created.Method | Should -Be 'ServicePrincipalCertificate'
        }

        It 'Profile TenantId matches' {
            $script:created.TenantId | Should -Be $script:FakeTenantId
        }

        It 'Profile SecretName matches' {
            $script:created.SecretName | Should -Be 'test_cert_pfx'
        }
    }

    Context 'Profile Get by Id' {
        BeforeAll {
            $id = $script:ProfileId1
            $tenantId = $script:FakeTenantId
            $clientId = $script:FakeClientId
            $prefix = $script:TestPrefix

            Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile ``
                    -Id '$id' -ProviderId 'Azure' ``
                    -Name '${prefix}Cert Get Test' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' -ClientId '$clientId' ``
                    -SecretName 'test_cert_pfx' ``
                    -IsActive `$false
                'seeded'
"@

            $script:byId = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id' | Select-Object Id, Name, Method, SecretName"
        }

        AfterAll {
            $id = $script:ProfileId1
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '$id' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'Retrieves profile by Id' {
            $script:byId | Should -Not -BeNullOrEmpty
        }

        It 'Retrieved profile has correct Id' {
            $script:byId.Id | Should -Be $script:ProfileId1
        }

        It 'Retrieved profile has correct Method' {
            $script:byId.Method | Should -Be 'ServicePrincipalCertificate'
        }

        It 'Retrieved profile has correct SecretName' {
            $script:byId.SecretName | Should -Be 'test_cert_pfx'
        }
    }

    Context 'Profile Update' {
        BeforeAll {
            $id = $script:ProfileId1
            $tenantId = $script:FakeTenantId
            $prefix = $script:TestPrefix

            Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile ``
                    -Id '$id' -ProviderId 'Azure' ``
                    -Name '${prefix}Cert Before Update' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' -ClientId '$($script:FakeClientId)' ``
                    -SecretName 'old_cert_pfx' ``
                    -IsActive `$false
                'seeded'
"@

            $script:updated = Run-OnPSU "Update-CIEMAzureAuthenticationProfile -Id '$id' -SecretName 'new_cert_pfx' -PassThru | Select-Object Id, Name, Method, SecretName"
        }

        AfterAll {
            $id = $script:ProfileId1
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '$id' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'Returns updated profile with -PassThru' {
            $script:updated | Should -Not -BeNullOrEmpty
        }

        It 'SecretName was updated' {
            $script:updated.SecretName | Should -Be 'new_cert_pfx'
        }

        It 'Partial update preserves Method' {
            $script:updated.Method | Should -Be 'ServicePrincipalCertificate'
        }
    }

    Context 'Profile Save (Upsert)' {
        AfterAll {
            $id = $script:ProfileId1
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '$id' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'Inserts when profile does not exist' {
            $id = $script:ProfileId1
            $tenantId = $script:FakeTenantId
            $prefix = $script:TestPrefix

            Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile ``
                    -Id '$id' -ProviderId 'Azure' ``
                    -Name '${prefix}Cert Save Insert' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' -SecretName 'test_cert_pfx' ``
                    -IsActive `$false
                'saved'
"@

            $result = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id' | Select-Object Id, Name, Method"
            $result | Should -Not -BeNullOrEmpty
            $result.Name | Should -Be "${prefix}Cert Save Insert"
            $result.Method | Should -Be 'ServicePrincipalCertificate'
        }

        It 'Upserts when profile already exists' {
            $id = $script:ProfileId1
            $tenantId = $script:FakeTenantId
            $prefix = $script:TestPrefix

            Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile ``
                    -Id '$id' -ProviderId 'Azure' ``
                    -Name '${prefix}Cert Save Upserted' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' -SecretName 'test_cert_pfx' ``
                    -IsActive `$false
                'saved'
"@

            $result = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id' | Select-Object Id, Name"
            $result.Name | Should -Be "${prefix}Cert Save Upserted"
        }
    }

    Context 'Profile Activation' {
        BeforeAll {
            $id1 = $script:ProfileId1
            $id2 = $script:ProfileId2
            $tenantId = $script:FakeTenantId
            $clientId = $script:FakeClientId
            $prefix = $script:TestPrefix

            Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile -Id '$id1' -ProviderId 'Azure' -Name '${prefix}Cert Activate A' -Method 'ServicePrincipalCertificate' -TenantId '$tenantId' -ClientId '$clientId' -SecretName 'cert_a' -IsActive `$false
                Save-CIEMAzureAuthenticationProfile -Id '$id2' -ProviderId 'Azure' -Name '${prefix}Cert Activate B' -Method 'ServicePrincipalCertificate' -TenantId '$tenantId' -ClientId '$clientId' -SecretName 'cert_b' -IsActive `$false
                'seeded'
"@


            Run-OnPSU "Set-CIEMAzureAuthenticationProfileActive -Id '$id1'; 'activated'"
            $script:p1after1 = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id1' | Select-Object Id, IsActive"
            $script:p2after1 = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id2' | Select-Object Id, IsActive"

            Run-OnPSU "Set-CIEMAzureAuthenticationProfileActive -Id '$id2'; 'activated'"
            $script:p1after2 = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id1' | Select-Object Id, IsActive"
            $script:p2after2 = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id2' | Select-Object Id, IsActive"
        }

        AfterAll {
            $id1 = $script:ProfileId1
            $id2 = $script:ProfileId2
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '$id1' -Confirm:`$false; 'ok'" } catch {}
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '$id2' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'Profile 1 is active after first activation' {
            $script:p1after1.IsActive | Should -BeTrue
        }

        It 'Profile 2 is inactive after first activation' {
            $script:p2after1.IsActive | Should -BeFalse
        }

        It 'Profile 2 is active after second activation' {
            $script:p2after2.IsActive | Should -BeTrue
        }

        It 'Profile 1 is deactivated after second activation' {
            $script:p1after2.IsActive | Should -BeFalse
        }
    }

    Context 'Profile Remove' {
        It 'Removes profile by Id' {
            $id = $script:ProfileId1
            $tenantId = $script:FakeTenantId
            $prefix = $script:TestPrefix

            Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile -Id '$id' -ProviderId 'Azure' -Name '${prefix}Cert Remove Me' -Method 'ServicePrincipalCertificate' -TenantId '$tenantId' -SecretName 'cert_rm' -IsActive `$false
                'seeded'
"@

            Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '$id' -Confirm:`$false; 'removed'"
            $result = Run-OnPSU "Get-CIEMAzureAuthenticationProfile -Id '$id' | Select-Object Id"
            $result | Should -BeNullOrEmpty
        }

        It 'No-ops when removing nonexistent Id' {
            { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id 'nonexistent_cert_99999' -Confirm:`$false; 'ok'" } | Should -Not -Throw
        }
    }

    Context 'Connection with real certificate credentials' {
        BeforeAll {
            $certProfileId = '_E2E_TEST_cert_connect'
            $tenantId = $script:realCertTenantId
            $clientId = $script:realCertClientId
            $secretName = $script:realCertSecretName

            # Create a cert profile with real credentials and activate it
            Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile ``
                    -Id '$certProfileId' -ProviderId 'Azure' ``
                    -Name '_E2E_TEST_Cert Connection' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' -ClientId '$clientId' ``
                    -SecretName '$secretName' ``
                    -IsActive `$false
                Set-CIEMAzureAuthenticationProfileActive -Id '$certProfileId'
                'activated'
"@


            $script:connectionInfo = Run-OnPSU 'Connect-CIEMAzure | Select-Object TenantId, SubscriptionIds, AccountId, AccountType, ConnectedAt' -TimeoutSeconds 120
        }

        AfterAll {
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '_E2E_TEST_cert_connect' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'Connect-CIEMAzure returns connection info' {
            $script:connectionInfo | Should -Not -BeNullOrEmpty
        }

        It 'Connection has a TenantId' {
            $script:connectionInfo.TenantId | Should -Not -BeNullOrEmpty
        }

        It 'Connection has SubscriptionIds' {
            $script:connectionInfo.SubscriptionIds | Should -Not -BeNullOrEmpty
        }

        It 'Connection has an AccountId' {
            $script:connectionInfo.AccountId | Should -Not -BeNullOrEmpty
        }

        It 'AccountType is ServicePrincipal' {
            $script:connectionInfo.AccountType | Should -Be 'ServicePrincipal'
        }
    }

    Context 'Auth context state after certificate connection' {
        BeforeAll {
            $certProfileId = '_E2E_TEST_cert_ctx'
            $tenantId = $script:realCertTenantId
            $clientId = $script:realCertClientId
            $secretName = $script:realCertSecretName

            $script:authCtx = Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile ``
                    -Id '$certProfileId' -ProviderId 'Azure' ``
                    -Name '_E2E_TEST_Cert Context' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' -ClientId '$clientId' ``
                    -SecretName '$secretName' ``
                    -IsActive `$false
                Set-CIEMAzureAuthenticationProfileActive -Id '$certProfileId'
                Connect-CIEMAzure | Out-Null
                `$mod = (Get-Command Connect-CIEMAzure).Module
                `$ctx = & `$mod { `$script:AzureAuthContext }
                [PSCustomObject]@{
                    IsConnected = [bool]`$ctx.IsConnected
                    HasARMToken = (`$null -ne `$ctx.ARMToken -and `$ctx.ARMToken.Length -gt 0)
                    HasGraphToken = (`$null -ne `$ctx.GraphToken -and `$ctx.GraphToken.Length -gt 0)
                    Method = `$ctx.Method
                }
"@
 -TimeoutSeconds 120
        }

        AfterAll {
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '_E2E_TEST_cert_ctx' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'Auth context is connected' {
            $script:authCtx.IsConnected | Should -BeTrue
        }

        It 'Auth context has ARM token' {
            $script:authCtx.HasARMToken | Should -BeTrue
        }

        It 'Auth context has Graph token' {
            $script:authCtx.HasGraphToken | Should -BeTrue
        }

        It 'Auth method is ServicePrincipalCertificate' {
            $script:authCtx.Method | Should -Be 'ServicePrincipalCertificate'
        }
    }

    Context 'Invoke-AzureApi with certificate tokens' {
        BeforeAll {
            $certProfileId = '_E2E_TEST_cert_api'
            $tenantId = $script:realCertTenantId
            $clientId = $script:realCertClientId
            $secretName = $script:realCertSecretName

            $script:armResult = Run-OnPSU @"
                Save-CIEMAzureAuthenticationProfile ``
                    -Id '$certProfileId' -ProviderId 'Azure' ``
                    -Name '_E2E_TEST_Cert API' ``
                    -Method 'ServicePrincipalCertificate' ``
                    -TenantId '$tenantId' -ClientId '$clientId' ``
                    -SecretName '$secretName' ``
                    -IsActive `$false
                Set-CIEMAzureAuthenticationProfileActive -Id '$certProfileId'
                Connect-CIEMAzure | Out-Null
                `$response = Invoke-AzureApi -Api ARM -Path 'subscriptions?api-version=2022-12-01' -ResourceName 'Subscriptions'
                [PSCustomObject]@{
                    HasValue = (`$null -ne `$response)
                    Count = @(`$response.value).Count
                }
"@
 -TimeoutSeconds 120
        }

        AfterAll {
            try { Run-OnPSU "Remove-CIEMAzureAuthenticationProfile -Id '_E2E_TEST_cert_api' -Confirm:`$false; 'ok'" } catch {}
        }

        It 'ARM API call returns data' {
            $script:armResult | Should -Not -BeNullOrEmpty
            $script:armResult.HasValue | Should -BeTrue
        }

        It 'ARM API returns at least one subscription' {
            $script:armResult.Count | Should -BeGreaterThan 0
        }
    }
}