OIDC login to US Gov Cloud fails when AzPSSession is enabled
I am opening this ticket to combine the requests of a couple of previously closed tickets.
The first issue #248 was raised over a year ago reporting the exact same behavior as what I am seeing currently. Specifically, I am attempting to log in a federated credential on a user-managed identity. I'm getting the same set of errors shown in the screenshot on that image. Specifically
Issue #248 was closed because this action did not support OIDC login to Government clouds at that time. However, pull request #321 has since resolved that incompatibility.
The second issue is #298, which was closed in May of this year due to pr #321 being merged. However, as was called out by @danelson after #298 was closed, pr #321 does not add support for OIDC login with enable-AzPSSession: true. I can confirm #321 does seem to log in when enable-AzPSSession: false or left at default when using the same credentials.
Workflow code:
name: Test Azure powershell login with OIDC
on:
workflow_dispatch:
permissions:
id-token: write
contents: read
jobs:
test-oidc-login-ps:
runs-on: ubuntu-latest
environment: beta # valid environment
steps:
- name: OIDC Login to Azure
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
environment: 'AzureUSGovernment'
enable-AzPSSession: true # works if this is not included
Hi @TylerWhitaker-USDA ,
Let me confirm your issue. It only happens when login with OIDC (with user-assigned managed identity) and
- environment: 'AzureUSGovernment'
- enable-AzPSSession: true
Is it correct?
I have not had the chance to do extensive testing on other configurations. I have only had the chance to test OIDC and 'AzureUSGovernment' as a constant while varying enable-AzPSSession. While 'true', login fails. While 'false', login succeeds.
I can also confirm that behavior. @TylerWhitaker-USDA I don't know if it helps you but as a workaround I am doing the following (note the Get sp secret step is untested because I do this in an internal action). Since I use user/password auth in other places this allows me to remove the need to store the credential in a github secret.
login:
runs-on: ubuntu-latest
environment: my_environment
steps:
- uses: azure/login@v1
with:
client-id: ${{ vars.SP_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
allow-no-subscriptions: true
environment: ${{ vars.AZURE_ENVIRONMENT }}
# https://github.com/Azure/get-keyvault-secrets/issues/33#issuecomment-1219146161
- name: Get sp secret
id: keyvault
run: |
value=$(az keyvault secret show --name sp-secret --vault-name ${{ vars.KEY_VAULT }} --query value --output tsv)
echo "::add-mask::$value"
echo "::set-output name=sp-secret::$value"
- uses: azure/login@v1
with:
creds: |
{
"clientId": "${{ vars.SP_CLIENT_ID }}",
"clientSecret": "${{ steps.keyvault.outputs.sp-secret}}",
"subscriptionId": "${{ vars.AZURE_SUBSCRIPTION_ID }}",
"tenantId": "${{ vars.AZURE_TENANT_ID }}"
}
environment: ${{ vars.AZURE_ENVIRONMENT }}
enable-AzPSSession: true
Hi @TylerWhitaker-USDA , I don't have an account for US Gov Cloud. Could you help me run the test workflow file and copy the output debug log to me?
@danelson I saw your workflow file is without subscription id but it's similar. Could you update my test workflow file accordingly and copy your output to me too?
name: Test OIDC
on: [push, workflow_dispatch]
permissions:
id-token: write
contents: read
jobs:
test-oidc:
runs-on: ubuntu-latest
steps:
- name: GetToken
uses: actions/github-script@v3
with:
script: |
const idToken = await core.getIDToken('api://AzureADTokenExchange')
core.exportVariable('idToken', idToken)
- name: Run Azure PowerShell
uses: azure/[email protected]
env:
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
with:
azPSVersion: "latest"
inlineScript: |
$AZURE_TENANT_ID = $env:AZURE_TENANT_ID
$AZURE_SUBSCRIPTION_ID = $env:AZURE_SUBSCRIPTION_ID
$AZURE_CLIENT_ID = $env:AZURE_CLIENT_ID
$idToken = $env:idToken
Clear-AzContext -Scope Process
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
Connect-AzAccount -ServicePrincipal -ApplicationId $AZURE_CLIENT_ID -Tenant $AZURE_TENANT_ID -FederatedToken $idToken -Environment 'AzureUSGovernment'
Set-AzContext -SubscriptionId $AZURE_SUBSCRIPTION_ID -TenantId $AZURE_TENANT_ID
Get-AzContext
@YanaXu I was able to run your test script with some modifications (like installing the Az.Account module). It ran into the same error when executing Connect-AzAccount:
AADSTS900382: Confidential Client is not supported in Cross Cloud request. Trace ID: xxx Correlation ID: xxx Timestamp: 2023-11-29 21:16:03Z Could not find tenant id for provided tenant domain 'my-us-gov-azure-tenant-id'.
Hi @samanthawalter, could you share your workflow file and the debug log with me? Which step throws the error? GetToken or Run Azure PowerShell?
@YanaXu I ran the following script and ran into the same error as @samanthawalter
- name: GetToken
uses: actions/github-script@v3
with:
script: |
const idToken = await core.getIDToken('api://AzureADTokenExchange')
core.exportVariable('idToken', idToken)
- name: Run Azure PowerShell
uses: azure/[email protected]
env:
AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }}
AZURE_SUBSCRIPTION_ID: ${{ inputs.azure-subscription-id }}
AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
with:
azPSVersion: "latest"
inlineScript: |
$AZURE_TENANT_ID = $env:AZURE_TENANT_ID
$AZURE_SUBSCRIPTION_ID = $env:AZURE_SUBSCRIPTION_ID
$AZURE_CLIENT_ID = $env:AZURE_CLIENT_ID
$idToken = $env:idToken
Clear-AzContext -Scope Process
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
Connect-AzAccount -ServicePrincipal -ApplicationId $AZURE_CLIENT_ID -Tenant $AZURE_TENANT_ID -FederatedToken $idToken -Environment 'AzureUSGovernment'
Set-AzContext -SubscriptionId $AZURE_SUBSCRIPTION_ID -TenantId $AZURE_TENANT_ID
Get-AzContext
It looks like it failed on the line
Connect-AzAccount -ServicePrincipal -ApplicationId $AZURE_CLIENT_ID -Tenant $AZURE_TENANT_ID -FederatedToken $idToken -Environment 'AzureUSGovernment'
Error Message:
Line |
10 | Connect-AzAccount -ServicePrincipal -ApplicationId $AZURE_CLIENT_ID - …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| AADSTS900382: Confidential Client is not supported in Cross Cloud
| request. Trace ID: {GUID} Correlation ID:
| {GUID} Timestamp: {TS}
| Could not find tenant id for provided tenant domain
| '***'.
Here is the uploaded debug output: DebugOutput.txt
Hi @tajatassi , thanks for your help. I've reported an issue in Azure PowerShell repo: [Az.Accounts] Connect-AzAccount -- Failed login to AzureUSGovernment with OIDC
Hey @YanaXu, I saw the fix was merged in. Do you know what the release process is like and how long until this will be available for the github action?
Hi @tajatassi ,so glad to find you're watching the issue created in Azure PowerShell repo. Yes, it's merged and preview version of Az.Accounts is released yesterday. I'm testing the preview version now and will provide the test steps for you very soon to check if it works in your env. The official release of Azure PowerShell will be on 2024-01-09. It may take a few days for GitHub Action Runners to apply it. I'll keep you updated on this.
Hi @tajatassi , could you help to run the following test workflow again? We'll see if the Az.Accounts 2.14.0-preview works for OIDC login to US Gov Cloud.
In the following test workflow file, the key update is to install Az.Accounts 2.14.0-preview and import it before running Connect-AzAccount.
I also update the Azure PowerShell action version from v1.3.0 to v1, combine the Connect-AzAccount and Set-AzContext to Connect-AzAccount. But they do not make big differences.
- name: GetToken
uses: actions/github-script@v3
with:
script: |
const idToken = await core.getIDToken('api://AzureADTokenExchange')
core.exportVariable('idToken', idToken)
- name: Run Azure PowerShell
uses: azure/powershell@v1
env:
AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }}
AZURE_SUBSCRIPTION_ID: ${{ inputs.azure-subscription-id }}
AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
with:
azPSVersion: "11.1.0"
inlineScript: |
$AZURE_TENANT_ID = $env:AZURE_TENANT_ID
$AZURE_SUBSCRIPTION_ID = $env:AZURE_SUBSCRIPTION_ID
$AZURE_CLIENT_ID = $env:AZURE_CLIENT_ID
$idToken = $env:idToken
Install-Module -Name Az.Accounts -Repository PSGallery -AllowPrerelease -Force
Import-Module Az.Accounts -Version 2.14.0
Clear-AzContext -Scope Process
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
Connect-AzAccount -ServicePrincipal -ApplicationId $AZURE_CLIENT_ID -Tenant $AZURE_TENANT_ID -SubscriptionId $AZURE_SUBSCRIPTION_ID -FederatedToken $idToken -Environment 'azurecloud'
Get-AzContext
I'm running into a handful of failures here:
-
Install-Module is not recognized as a command - I think this is an issue with the runner. It doesn't happen consistently.
-
I'm getting an error related to Import-Module like this:
Assembly with same name is already loadedI've tried various changes with importing the module, removing the old one, etc. Here is the workflow file:
- name: GetToken
uses: actions/github-script@v3
with:
script: |
const idToken = await core.getIDToken('api://AzureADTokenExchange')
core.exportVariable('idToken', idToken)
- name: Run Azure PowerShell
uses: azure/powershell@v1
env:
AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }}
AZURE_SUBSCRIPTION_ID: ${{ inputs.azure-subscription-id }}
AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
with:
azPSVersion: "11.1.0"
inlineScript: |
$AZURE_TENANT_ID = $env:AZURE_TENANT_ID
$AZURE_SUBSCRIPTION_ID = $env:AZURE_SUBSCRIPTION_ID
$AZURE_CLIENT_ID = $env:AZURE_CLIENT_ID
$idToken = $env:idToken
Clear-AzContext -Scope Process
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
Install-Module -Name Az.Accounts -Repository PSGallery -AllowPrerelease -Force
Get-InstalledModule -Name Az.Accounts -RequiredVersion 2.14.0
Remove-Module Az.Accounts -Force
Import-Module Az.Accounts -Version 2.14.0 -Force
Connect-AzAccount -ServicePrincipal -ApplicationId $AZURE_CLIENT_ID -Tenant $AZURE_TENANT_ID -SubscriptionId $AZURE_SUBSCRIPTION_ID -FederatedToken $idToken -Environment 'AzureUSGovernment'
Get-AzContext
Here's debug file DebugOutput.txt
@tajatassi ,
The 1st error means there is no PowerShellGet cmdlets. It could not happen since you're using GitHub-hosted ubuntu runner and running Azure PowerShell Action.
And I'm sorry for the 2nd error. I copied the workflow file content by mistake. Here is the entire workflow file.
I'll update my last comment to avoid misunderstanding.
name: Test OIDC
on: [push, workflow_dispatch]
permissions:
id-token: write
contents: read
jobs:
test-oidc:
runs-on: ubuntu-latest
steps:
- name: TestGetToken
uses: actions/github-script@v3
with:
script: |
const idToken = await core.getIDToken('api://AzureADTokenExchange')
core.exportVariable('idToken', idToken)
- name: Run Azure PowerShell
uses: azure/powershell@v1
env:
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
with:
azPSVersion: "11.1.0"
inlineScript: |
$AZURE_TENANT_ID = $env:AZURE_TENANT_ID
$AZURE_SUBSCRIPTION_ID = $env:AZURE_SUBSCRIPTION_ID
$AZURE_CLIENT_ID = $env:AZURE_CLIENT_ID
$idToken = $env:idToken
Install-Module -Name Az.Accounts -Repository PSGallery -AllowPrerelease -Force
Import-Module Az.Accounts -Version 2.14.0
Clear-AzContext -Scope Process
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
Connect-AzAccount -ServicePrincipal -ApplicationId $AZURE_CLIENT_ID -Tenant $AZURE_TENANT_ID -SubscriptionId $AZURE_SUBSCRIPTION_ID -FederatedToken $idToken -Environment 'AzureUSGovernment'
Get-AzContext
Get-AzResourceGroup
Get-Module | Select-Object Name,Version
I see the difference. It is now working on my end :)