Search code examples
amazon-web-servicesazureazure-entra-id

Can I Assume a Role After OIDC Authentication in Azure?


I'm currently working on an Azure project where I'm implementing OIDC (OpenID Connect) authentication using Azure Active Directory (Azure AD). My goal is to understand how to manage roles and permissions after a user or application successfully authenticates with GitHub Workflow.

Current Azure CLI Login

name: Run Azure Login with OIDC
on:
  push:
    tags:
      - 'UAT*'  # This will trigger on any tag that starts with "UAT"

permissions:
  id-token: write
  contents: read
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: 'Az CLI login'
        uses: Azure/[email protected]
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          allow-no-subscriptions: true # Add this if you want to proceed even without subscriptions
          auth-type: SERVICE_PRINCIPAL

      - name: 'Run az commands'
        run: |
          az account show
          az group list

In AWS, I can assume a role after authentication, allowing for dynamic permission management.

AWS Workflow sample:

- name: Configure AWS credentials
  uses: aws-actions/[email protected]
  with:
    role-to-assume: ${{ secrets.DEPLOYMENT_ROLE }} #change to reflect your IAM role’s ARN
    role-session-name: GitHub_to_AWS_via_FederatedOIDC
    aws-region: ${{ env.AWS_REGION }}

However, I’m unsure how this works in Azure. Here are my specific questions:

  • Is there an equivalent mechanism in Azure to "assume a role" after OIDC authentication?
  • How can I dynamically manage permissions for users or applications in Azure after they authenticate via OIDC?
  • Are there best practices for assigning roles in Azure AD that I should be aware of?

Any insights, references to documentation, or examples would be greatly appreciated!


Solution

  • I hope that the following updated post can help you.

    Login with OpenID Connect (OIDC) is Recommended

    Before you use Azure Login Action with OIDC, you need to configure a federated identity credential on a service principal or a managed identity.

    I prefer to use a Service Principal:

    Prepare a service principal for Login with OIDC

    • Create a service principal and assign a role to it.
    • Configure a federated identity credential on an service principal.

    Prepare a user-assigned managed identity for Login with OIDC

    • Create a user-assigned managed identity and assign a role to it.
    • Configure a federated identity credential on a user-assigned managed identity.

    It's important to Configure a federated identity credential on the App

    Assign A Role -- is the Key for you.

    As you can see in the above steps for preparing the service principal or managed identity, you need to perform a role assignment. You don't need to do it dynamically in the GitHub action's steps, but rather, perform the Role assignment during the service principal or managed identity preparation steps.

    In Azure Portal,

    • Find the Azure Resource that your workflow is going to act on it.
    • Under IAM, add role assignment for your service principal. For example, add a privileged role Contributor role to this resource. And save the change.
    • After your workflow logging-into Azure, your Service Principal should be able to perform the RBAC-based actions.

    Here are the detailed steps:

    Login with a Service Principal

    Create a GitHub Action secret AZURE_CREDENTIALS with the value like below:

    {
        "clientSecret":  "******",
        "subscriptionId":  "******",
        "tenantId":  "******",
        "clientId":  "******"
    }
    
    • clientSecret: the service principal client secret
    • subscriptionId: the subscription ID
    • tenantId: the tenant ID
    • clientId: the service principal client ID

    Now you can try the workflow to login with a service principal secret.

    # File: .github/workflows/workflow.yml
    
    on: [push]
    
    name: Run Azure Login With a Service Principal Secret
    
    jobs:
    
      build-and-deploy:
        runs-on: ubuntu-latest
        steps:
    
        - uses: azure/login@v2
          with:
            creds: ${{ secrets.AZURE_CREDENTIALS }}
    
        - name: Azure CLI script
          uses: azure/cli@v2
          with:
            azcliversion: latest
            inlineScript: |
              az account show
    

    If you want to pass subscription ID, tenant ID, client ID, and client secret as individual parameters instead of bundling them in a single JSON object to address the security concerns, below snippet can help with the same.

      - uses: azure/login@v2
        with:
          creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'
    

    Reference: