From f2119795d3d9ec6e8f6b8ec97bd587f728af7c7e Mon Sep 17 00:00:00 2001 From: Benjamin Michaelis Date: Tue, 21 Apr 2026 16:17:52 -0700 Subject: [PATCH] ci: migrate ACR login to OIDC/UAMI managed identity - Replace docker/login-action (admin credentials) with az acr login via OIDC session (azure/login with AZURE_CLIENT_ID) - Add --registry-identity and --user-assigned flags to az containerapp up so identity attachment and registry config happen atomically on create and update, eliminating the chicken-and-egg ordering issue - Replace az config set extension.use_dynamic_install with explicit az extension add --name containerapp --upgrade to ensure the extension version supports --registry-identity on az containerapp up - Remove --registry-username/--registry-password from containerapp up - Update Assign MI step to use WEB_UAMI_RESOURCE_ID and WEB_UAMI_CLIENT_ID --- .github/workflows/Build-Test-And-Deploy.yml | 46 +++++++-------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/.github/workflows/Build-Test-And-Deploy.yml b/.github/workflows/Build-Test-And-Deploy.yml index 803d6929..7c87aaa5 100644 --- a/.github/workflows/Build-Test-And-Deploy.yml +++ b/.github/workflows/Build-Test-And-Deploy.yml @@ -97,7 +97,7 @@ jobs: - name: Azure Login uses: azure/login@v3 with: - client-id: ${{ secrets.ESSENTIALCSHARPDEV_CLIENT_ID }} + client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.ESSENTIALCSHARP_APPIDENTITY_TENANT_ID }} subscription-id: ${{ secrets.ESSENTIALCSHARP_SUBSCRIPTION_ID }} @@ -113,11 +113,9 @@ jobs: docker image ls -a - name: Log in to container registry - uses: docker/login-action@v4 - with: - registry: ${{ vars.DEVCONTAINER_REGISTRY }} - username: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }} - password: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }} + run: | + REGISTRY="${{ vars.DEVCONTAINER_REGISTRY }}" + az acr login --name "${REGISTRY%.azurecr.io}" - name: Push Image to Container Registry run: docker push --all-tags ${{ vars.DEVCONTAINER_REGISTRY }}/essentialcsharpweb @@ -129,12 +127,10 @@ jobs: RESOURCEGROUP: ${{ vars.RESOURCEGROUP }} CONTAINER_REGISTRY: ${{ vars.DEVCONTAINER_REGISTRY }} CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }} - ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }} - ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }} with: inlineScript: | - az config set extension.use_dynamic_install=yes_without_prompt - az containerapp up -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} --environment $CONTAINER_APP_ENVIRONMENT --registry-server $CONTAINER_REGISTRY --ingress external --target-port 8080 --registry-username $ACR_USERNAME --registry-password $ACR_PASSWORD + az extension add --name containerapp --upgrade + az containerapp up -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} --environment $CONTAINER_APP_ENVIRONMENT --registry-server $CONTAINER_REGISTRY --registry-identity ${{ secrets.WEB_UAMI_RESOURCE_ID }} --user-assigned ${{ secrets.WEB_UAMI_RESOURCE_ID }} --ingress external --target-port 8080 - name: Assign Managed Identity to Container App and Set Secrets and Environment Variables uses: azure/CLI@v3 @@ -144,14 +140,11 @@ jobs: CONTAINER_REGISTRY: ${{ vars.DEVCONTAINER_REGISTRY }} CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }} KEYVAULTURI: ${{ secrets.ESSENTIALCSHARP_KEYVAULT_URI }} - MANAGEDIDENTITYID: ${{ secrets.ESSENTIALCSHARP_APPIDENTITY_ID }} - ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }} - ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }} - AZURECLIENTID: ${{ secrets.IDENTITY_CLIENT_ID }} + MANAGEDIDENTITYID: ${{ secrets.WEB_UAMI_RESOURCE_ID }} + AZURECLIENTID: ${{ secrets.WEB_UAMI_CLIENT_ID }} TRYDOTNET_ORIGIN: ${{ vars.TRYDOTNET_ORIGIN }} with: inlineScript: | - az containerapp identity assign -n ${{ vars.CONTAINER_APP_NAME }} -g ${{ vars.RESOURCEGROUP }} --user-assigned ${{ vars.CONTAINER_APP_IDENTITY }} az containerapp secret set -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --secrets github-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientid,identityref:$MANAGEDIDENTITYID \ github-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientsecret,identityref:$MANAGEDIDENTITYID msft-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientid,identityref:$MANAGEDIDENTITYID \ msft-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientsecret,identityref:$MANAGEDIDENTITYID emailsender-apikey=keyvaultref:$KEYVAULTURI/secrets/authmessagesender-apikey,identityref:$MANAGEDIDENTITYID \ @@ -194,7 +187,7 @@ jobs: - name: Azure Login uses: azure/login@v3 with: - client-id: ${{ secrets.ESSENTIALCSHARP_CLIENT_ID }} + client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.ESSENTIALCSHARP_TENANT_ID }} subscription-id: ${{ secrets.ESSENTIALCSHARP_SUBSCRIPTION_ID }} @@ -210,11 +203,9 @@ jobs: docker image ls -a - name: Log in to container registry - uses: docker/login-action@v4 - with: - registry: ${{ vars.PRODCONTAINER_REGISTRY }} - username: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }} - password: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }} + run: | + REGISTRY="${{ vars.PRODCONTAINER_REGISTRY }}" + az acr login --name "${REGISTRY%.azurecr.io}" - name: Push Image to Container Registry run: docker push --all-tags ${{ vars.PRODCONTAINER_REGISTRY }}/essentialcsharpweb @@ -226,12 +217,10 @@ jobs: RESOURCEGROUP: ${{ vars.RESOURCEGROUP }} CONTAINER_REGISTRY: ${{ vars.PRODCONTAINER_REGISTRY }} CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }} - ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }} - ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }} with: inlineScript: | - az config set extension.use_dynamic_install=yes_without_prompt - az containerapp up -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} --environment $CONTAINER_APP_ENVIRONMENT --registry-server $CONTAINER_REGISTRY --ingress external --target-port 8080 --registry-username $ACR_USERNAME --registry-password $ACR_PASSWORD + az extension add --name containerapp --upgrade + az containerapp up -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --image $CONTAINER_REGISTRY/essentialcsharpweb:${{ github.sha }} --environment $CONTAINER_APP_ENVIRONMENT --registry-server $CONTAINER_REGISTRY --registry-identity ${{ secrets.WEB_UAMI_RESOURCE_ID }} --user-assigned ${{ secrets.WEB_UAMI_RESOURCE_ID }} --ingress external --target-port 8080 - name: Assign Managed Identity to Container App and Set Secrets and Environment Variables uses: azure/CLI@v3 @@ -241,14 +230,11 @@ jobs: CONTAINER_REGISTRY: ${{ vars.PRODCONTAINER_REGISTRY }} CONTAINER_APP_ENVIRONMENT: ${{ vars.CONTAINER_APP_ENVIRONMENT }} KEYVAULTURI: ${{ secrets.ESSENTIALCSHARP_KEYVAULT_URI }} - MANAGEDIDENTITYID: ${{ secrets.ESSENTIALCSHARP_APPIDENTITY_ID }} - ACR_USERNAME: ${{ secrets.ESSENTIALCSHARP_ACR_USERNAME }} - ACR_PASSWORD: ${{ secrets.ESSENTIALCSHARP_ACR_PASSWORD }} - AZURECLIENTID: ${{ secrets.IDENTITY_CLIENT_ID }} + MANAGEDIDENTITYID: ${{ secrets.WEB_UAMI_RESOURCE_ID }} + AZURECLIENTID: ${{ secrets.WEB_UAMI_CLIENT_ID }} TRYDOTNET_ORIGIN: ${{ vars.PROD_TRYDOTNET_ORIGIN }} with: inlineScript: | - az containerapp identity assign -n ${{ vars.CONTAINER_APP_NAME }} -g ${{ vars.RESOURCEGROUP }} --user-assigned ${{ vars.CONTAINER_APP_IDENTITY }} az containerapp secret set -n $CONTAINER_APP_NAME -g $RESOURCEGROUP --secrets github-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientid,identityref:$MANAGEDIDENTITYID \ github-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-github-clientsecret,identityref:$MANAGEDIDENTITYID msft-clientid=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientid,identityref:$MANAGEDIDENTITYID \ msft-clientsecret=keyvaultref:$KEYVAULTURI/secrets/authentication-microsoft-clientsecret,identityref:$MANAGEDIDENTITYID emailsender-apikey=keyvaultref:$KEYVAULTURI/secrets/authmessagesender-apikey,identityref:$MANAGEDIDENTITYID \