CI/CD Integration

Learn how to integrate Entra Auth Cli into your CI/CD pipelines for automated authentication.


GitHub Actions

Basic Example

  name: Deploy

on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Install Entra Auth Cli
        run: |
          dotnet tool install --global EntraAuthCli
      
      - name: Create Profile
        env:
          CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
        run: |
          # Create profile non-interactively
          cat > profile.json <<EOF
          {
            "name": "cicd",
            "clientId": "$CLIENT_ID",
            "tenantId": "$TENANT_ID",
            "scope": "https://management.azure.com/.default",
            "useClientSecret": true
          }
          EOF
          entra-auth-cli config import -f profile.json
          
          # Store secret (implementation depends on tool capabilities)
      
      - name: Deploy to Azure
        run: |
          TOKEN=$(entra-auth-cli get-token -p cicd --silent)
          
          # Use token for deployment
          curl -X POST \
               -H "Authorization: Bearer $TOKEN" \
               -H "Content-Type: application/json" \
               -d @deployment.json \
               "https://management.azure.com/..."
  

With Matrix Strategy

  name: Multi-Environment Deploy

on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: [dev, staging, prod]
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Entra Auth Cli
        run: dotnet tool install --global EntraAuthCli
      
      - name: Deploy to ${{ matrix.environment }}
        env:
          CLIENT_ID: ${{ secrets[format('{0}_CLIENT_ID', matrix.environment)] }}
          TENANT_ID: ${{ secrets[format('{0}_TENANT_ID', matrix.environment)] }}
          CLIENT_SECRET: ${{ secrets[format('{0}_CLIENT_SECRET', matrix.environment)] }}
        run: |
          # Create environment-specific profile
          entra-auth-cli config create --name ${{ matrix.environment }} \
            --client-id "$CLIENT_ID" \
            --tenant-id "$TENANT_ID"
          
          TOKEN=$(entra-auth-cli get-token -p ${{ matrix.environment }} --silent)
          ./deploy.sh "$TOKEN" "${{ matrix.environment }}"
  

Azure Pipelines

Basic Example

  trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: |
    dotnet tool install --global EntraAuthCli
  displayName: 'Install Entra Auth Cli'

- task: AzureCLI@2
  inputs:
    azureSubscription: 'MyServiceConnection'
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
      # Create profile
      entra-auth-cli config create --non-interactive \
        --name cicd \
        --client-id $(ClientId) \
        --tenant-id $(TenantId) \
        --client-secret $(ClientSecret) \
        --scope "https://management.azure.com/.default"
      
      # Get token
      TOKEN=$(entra-auth-cli get-token -p cicd --silent)
      
      # Deploy
      ./deploy.sh "$TOKEN"
  

With Deployment Job

  trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - script: dotnet build
      displayName: 'Build Application'

- stage: Deploy
  dependsOn: Build
  jobs:
  - deployment: DeployJob
    environment: 'production'
    strategy:
      runOnce:
        deploy:
          steps:
          - script: dotnet tool install --global EntraAuthCli
            displayName: 'Install CLI'
          
          - script: |
              entra-auth-cli config create --name prod \
                --client-id $(ClientId) \
                --tenant-id $(TenantId)
              
              TOKEN=$(entra-auth-cli get-token -p prod --silent)
              ./deploy-to-production.sh "$TOKEN"
            displayName: 'Deploy'
  

GitLab CI

  stages:
  - deploy

deploy:
  stage: deploy
  image: mcr.microsoft.com/dotnet/sdk:8.0
  script:
    - dotnet tool install --global EntraAuthCli
    - export PATH="$PATH:/root/.dotnet/tools"
    
    # Create profile
    - |
      cat > profile.json <<EOF
      {
        "name": "gitlab-ci",
        "clientId": "$AZURE_CLIENT_ID",
        "tenantId": "$AZURE_TENANT_ID",
        "scope": "https://management.azure.com/.default"
      }
      EOF
    - entra-auth-cli config import -f profile.json
    
    # Deploy
    - TOKEN=$(entra-auth-cli get-token -p gitlab-ci --silent)
    - ./deploy.sh "$TOKEN"
  only:
    - main
  

Jenkins

  pipeline {
    agent any
    
    environment {
        CLIENT_ID = credentials('azure-client-id')
        TENANT_ID = credentials('azure-tenant-id')
        CLIENT_SECRET = credentials('azure-client-secret')
    }
    
    stages {
        stage('Setup') {
            steps {
                sh 'dotnet tool install --global EntraAuthCli'
            }
        }
        
        stage('Deploy') {
            steps {
                sh '''
                    # Create profile
                    entra-auth-cli config create --name jenkins \
                      --client-id "$CLIENT_ID" \
                      --tenant-id "$TENANT_ID"
                    
                    # Get token
                    TOKEN=$(entra-auth-cli get-token -p jenkins --silent)
                    
                    # Deploy
                    ./deploy.sh "$TOKEN"
                '''
            }
        }
    }
}
  

Best Practices

Use Service Principals

Create dedicated service principals for CI/CD:

  az ad sp create-for-rbac --name "cicd-deployment" \
  --role "Contributor" \
  --scopes "/subscriptions/YOUR_SUBSCRIPTION_ID"
  

Store Secrets Securely

  • GitHub Actions: Use GitHub Secrets
  • Azure Pipelines: Use Variable Groups
  • GitLab CI: Use CI/CD Variables
  • Jenkins: Use Credentials Plugin

Separate Profiles per Environment

  # Create environment-specific profiles
- name: Configure Dev Profile
  run: entra-auth-cli config create --name dev ...

- name: Configure Prod Profile
  run: entra-auth-cli config create --name prod ...
  

Use Silent Mode

Always use --silent flag in CI/CD to get clean token output:

  TOKEN=$(entra-auth-cli get-token -p cicd --silent)
  

Validate Tokens

Test token validity before use:

  TOKEN=$(entra-auth-cli get-token -p cicd --silent)
if entra-auth-cli inspect <<< "$TOKEN" &>/dev/null; then
  echo "Token valid"
  # Proceed with deployment
else
  echo "Token invalid"
  exit 1
fi
  

Troubleshooting

“Tool not found”

Ensure .NET tools are in PATH:

  export PATH="$PATH:$HOME/.dotnet/tools"
  

“Profile not found”

Profile creation may have failed. Check logs and recreate:

  entra-auth-cli config list
entra-auth-cli config create ...
  

“Authentication failed”

Verify secrets are correctly configured:

  echo "Client ID: $CLIENT_ID"
echo "Tenant ID: $TENANT_ID"
# Don't echo secrets!
  

Next Steps