DEV Community

Sawit M.
Sawit M.

Posted on

Let Github Action Access Azure Resources without password

พอกันที่กับการ rotate secret ของ Service Principal ที่ใช้กับ Github Action ทุก 3 เดือน 6 เดือน
พอกันทีกับโอกาสที่ secret ของ Service Principal จะ leak

วันนี้มีสิ่งที่เรียกว่า "Workload Identity Federation" นำเสนอครับ

Workload Identity Federation

คือการที่เราทำการสร้าง trusted relationship กันระหว่าง Microsoft Identity Platform กับ External Identity Provider (IdP) เช่น GitHub พอ trust กันแล้ว เราจะสามารถใช้ token ของ External IdP ไปแลกเป็น access token ของ Azure เพื่อ access resources ใน Azure ที่ถูก protect ด้วย Azure AD ได้

External Identity Provider (IdP) ที่ support ตอนนี้ เช่น

  • GitHub Actions
  • Google Cloud
  • Workload ใน Kubernetes
  • External Provider อื่นๆ ที่ support OpenID Connect (OIDC)

มาดู flow ดีกว่าว่ามันทำงานยังไง

Workload Identity Federation

  1. External Workload เช่น github action ทำการขอ token จาก IdP ของตัวเอง
  2. External IdP ทำการ generate แล้วให้ token กับ External Workload
  3. External Workload ใช้ token ที่ได้มาเพื่อขอ access token จาก Microsoft identity platform
  4. Microsoft identity platform ทำการตรวจสอบว่ามี trust relationship สร้างไว้อยู่หรือไม่ และ เอา token ที่ได้ไป validate กับ External IdP
  5. ถ้าทุกอย่างเรียบร้อย Microsoft identity platform จะสร้าง access token แล้วส่งให้กับ External Workload
  6. จากนั้น External Workload จะใช้ access token ที่ได้มาเช้าถึง resources ใน Azure โดย access token จะมี permission เท่ากับ service principal ที่ สร้าง trust relationship ไว้

มาลองลงมือทำดีกว่า

สิ่งที่เราจะทำคือสร้าง

  • 1 Github Repos ที่มี 2 Actions และ 2 environments ( develop / production )
  • 2 services principals ( develop / production )
  • trust relationship ระหว่าง Service Principals และ Environment ของ Github
  • 2 resource groups และให้ services principals เป็น Contributors ใน resource groups ( develop / production )
  • สร้าง Github Action Workflow เพื่อทดสอบ storage account ใน resource group ตาม environemnt

สร้าง Github Repos และ environment

  • สร้าง Github Action Repo

Create Github Action Repo

Create Github Action Repo

  • Create Environment ( ชื่อ environemnt จะถูกใช้ในการ สร้าง trust relationship ใน Azure Portal )
    • develop
    • production

Create Environment

Environment

สร้าง service principal

  • ใน Azure Portal > Azure Active Directory > App registrations > + New Registration

App registrations

  • ใส่ชื่อของ service principal เลือก single tenant แล้วกด Register
    • sp-demogithub-az-asse-dev-001 สำหรับ develop
    • sp-demogithub-az-asse-prd-001 สำหรับ production

New Registration Dev

สร้าง Trust Relationship ( Federated credentials )

  • Click ที่ Service Principal ที่เราสร้างขึ้น > Certificates & secrets > Federated credentials > + Add credential

Federated credentials

  • ใส่ข้อมูลของ Github Repo ที่ต้องการสร้าง Trust Relationship ด้วย
    • Organization: ใส่ชื่อ organization ของ ตัวเอง
    • Repository: ชื่อ repo ของ github ที่เราสร้างไว้ก่อนหน้า
    • Entity type: เลือก Environment ค่าอื่นดูต่อที่ Entity type examples
    • Name: ตั้งชื่อขอ Federated credentials นี้ ( FQDN friendly )

Trust Relationship

  • กดที่ overview ของ Service Pricipal แล้วเก็บค่าเหล่านี้ไว้ใช้ add ใน github environment
    • AZURE_CLIENT_ID: Application (client) ID
    • AZURE_TENANT_ID: Directory (tenant) ID
    • AZURE_SUBSCRIPTION_ID: subscription ID ที่จำให้ Github Action Provision storage account

Develop Environment

  • ทำแบบเดียวกันกับ Service Principal ของ Production Environment

Production Environment

สร้าง resource group แล้ว assign Contributor role ให้กับ Service Principal

  • สร้าง resource groups
    • rg-demogithubfed-az-asse-dev-001 สำหรับ develop
    • rg-demogithubfed-az-asse-prd-001 สำหรับ production

resource groups

  • Create Role Assignment ให้
    • sp-demogithub-az-asse-dev-001 เป็น Contributor ใน rg-demogithubfed-az-asse-dev-001

sp-demogithub-az-asse-dev-001

  • sp-demogithub-az-asse-prd-001 เป็น Contributor ใน rg-demogithubfed-az-asse-prd-001

sp-demogithub-az-asse-prd-001

สร้าง Github workflow เพื่อทดสอบสร้าง storage account

  • สร้าง Enviroment secret ใน Github
    • AZURE_CLIENT_ID: Application (client) ID
    • AZURE_TENANT_ID: Directory (tenant) ID
    • AZURE_SUBSCRIPTION_ID: subscription ID ที่จำให้ Github Action Provision storage account

Enviroment secret 1

Enviroment secret 2

Enviroment secret 3

ทำแบบเดียวกัน กับ production enviroment

  • สร้าง Github Workflow สำหรับ create github action

Action ที่ใช้ login คือ Azure Login โดยเราจะทำตามตัวอย่างนี้ Sample workflow that uses Azure login action using OIDC to run az cli (Linux)

github create file

  • สร้าง file สำหรับ develop => .github/workflows/dev-demo.yml
name: DEV - Demo Azure Login with OIDC
on:
   workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    environment: develop
    steps:
      - name: 'Az CLI login'
        uses: azure/login@v1
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: 'Run az commands'
        run: |
          az account show --output table
          az storage account create \
          --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
          --location southeastasia \
          --resource-group rg-githubfed-az-asse-dev-001 \
          --name stdemofeddev001 \
          --sku Standard_LRS \
          --default-action Deny \
          --min-tls-version TLS1_2 \
          --output table
Enter fullscreen mode Exit fullscreen mode
  • สร้าง file สำหรับ production => .github/workflows/prd-demo.yml
name: PRD - Demo Azure Login with OIDC
on:
   workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: 'Az CLI login'
        uses: azure/login@v1
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: 'Run az commands'
        run: |
          az account show --output table
          az storage account create \
          --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
          --location southeastasia \
          --resource-group rg-githubfed-az-asse-prd-001 \
          --name stdemofedprd001 \
          --sku Standard_LRS \
          --default-action Deny \
          --min-tls-version TLS1_2 \
          --output table
Enter fullscreen mode Exit fullscreen mode
  • ทดสอบ run Github Action

Github action run

Github action result

  • ตรวจสอบ storage account ที่ Azure Portal

storage account


References

Latest comments (1)

Collapse
 
marcospopa profile image
Marcos Popa

Great article. Keep teaching, keep learning