GitHub Actions から OIDC 認証で各クラウドを Terraform デプロイする – Azure 編

GitHub

今回は GitHub Actions で Terraform を実行する際に、OIDC 認証を用いて Azure にリソースをデプロイします。OIDC を利用することで、GitHub 内に Azure アカウントのシークレットなどを保存しなくて良いため、セキュリティが向上します。

Azure は以前から OIDC 認証に対応していましたが、Terraform で Azure CLI の認証情報を利用したデプロイを実行しようとするときにサービス プリンシパルがサポートされていませんでした。そのため、Terraform で OIDC 認証を利用した Azure へのデプロイができませんでした。

しかし、つい最近サービス プリンシパルでの OIDC 認証がサポートされたため、他のクラウドと同じくシークレットを保持しないデプロイを実現できるようになりました。

Support for OIDC Authentication by SudoSpartanDan · Pull Request #16555 · hashicorp/terraform-provider-azurerm (github.com)

公式ではこちらの手順が参考になります。

Azure Provider: Authenticating via a Service Principal and OpenID Connect | Guides | hashicorp/azurerm | Terraform Registry

スポンサーリンク

Azure でサービス プリンシパルの作成とロールを設定

まずは Azure 側に認証で利用するサービス プリンシパルを作成します。変数に使用する GitHub リポジトリの情報は、次のように設定します。

  • AccountName : GitHub アカウント名 (組織名)
  • RepositoryName : リポジトリ名
https://github.com/<AccountName>/<RepositoryName>

Azure CLI を使ってサービス プリンシパルを作成します。Azure AD での操作は時期に Graph API へと移行する計画が発表されていますので、今後この手順は見直す必要があるかもしれません。が、ひとまず慣れ親しんだ Azure CLI での操作をまとめます。

# 変数の定義
SUBSCRIPTION_ID='********-****-****-****-************'
OIDC_APP_NAME='GitHub Actions OIDC'
GITHUB_ACCOUNT='AccountName'
GITHUB_REPOSITRY='RepositoryName'

# Azure AD アプリの作成
OIDC_APP_ID=$(az ad app create --display-name $OIDC_APP_NAME --query appId -o tsv)
# サービス プリンシパルの作成
ASSIGNEE_OBJECT_ID=$(az ad sp create --id $OIDC_APP_ID --query objectId -o tsv)

# サービス プリンシパルへロールの付与 (例: 共同作成者[contributer])
az role assignment create --role contributor --subscription $SUBSCRIPTION_ID --assignee-object-id  $ASSIGNEE_OBJECT_ID --assignee-principal-type ServicePrincipal

# OIDC 用リポジトリ識別情報の設定
az rest --method POST --uri "https://graph.microsoft.com/beta/applications/${CLIENT_ID}/federatedIdentityCredentials" --body "{\"name\":\"${OIDC_APP_NAME}\",\"issuer\":\"https://token.actions.githubusercontent.com\",\"subject\":\"repo:${GITHUB_ACCOUNT}/${GITHUB_REPOSITRY}:environment:production\",\"description\":\"OIDC\",\"audiences\":[\"api://AzureADTokenExchange\"]}"

# GitHub Actions 設定用パラメーターの取得
CLIENT_ID=$(az ad app show --id $OIDC_APP_ID --query objectId -o tsv)
TENANT_ID=$(az ad sp show --id $OIDC_APP_ID --query appOwnerTenantId -o tsv)

コマンドの中でサービス プリンシパルに対して共同作成者のロールを付与しています。ここは利用したいシチュエーションに合わせて権限をカスタマイズしてください。GitHub 側に設定するため、次の情報を取得しておきます。

  • Azure AD アプリのクライアント ID (App ID)
  • Azure AD テナント ID
  • Azure サブスクリプション ID
export $CLIENT_ID
export $TENANT_ID
export $SUBSCRIPTION_ID

Azure AD アプリ (サービス プリンシパル) あたりの ID は色々と混在していてややこしいのですが、GUI で確認できるものだと [アプリケーション (クライアント) ID]と表示されている部分が今回利用する情報です。

OIDC の認証に関する設定は、[証明書とシークレット]>[フェデレーション資格情報] から行えます。

組織とリポジトリはそれぞれ GITHUB_ACCOUNTGITHUB_REPOSITORY に設定した内容になります。アクセス元を制限するためにエンティティ型と選択範囲を指定します。上述のコード内で言うと subject に示されている部分の後半です。これをゆるくすると不正なアクセスが発生してしまうので注意します。

なお、エンティティには次のものを指定できます。

  • Environment
  • Brunch
  • PullRequest
  • Tag

GitHub Actions ワークフロー

Azure に OIDC 認証するための手順を GitHub Actions ワークフローに組み込みます。

シークレットの作成

GitHub Actions のシークレットに、上述のコードで設定した ID の情報を設定します。シークレットがなくなっても流石にサブスクリプションやテナントの ID からは逃れられませんね。

シークレット名変数名説明
ARM_CLIENT_IDCLIENT_IDAzure AD アプリのクライアント ID (App ID)
ARM_SUBSCRIPTION_IDSUBSCRIPTION_IDAzure サブスクリプション ID
ARM_TENANT_IDTENANT_IDAzure AD テナント ID

権限設定の追記

ワークフローから OIDC トークンのリクエストを行えるように権限の設定を追加します。次のような内容をワークフローに追記します。

permissions:
  id-token: write
  contents: read

Azure アクセス情報の設定

OIDC での Azure への認証には Azure CLI を利用しないため、必要な情報を環境変数に渡しておくだけで大丈夫です。GitHub Actions ワークフロー内での環境変数は、注意しないとステップ間での受け渡しができません。ステップ間を超えて利用できる環境変数を利用するには、$GITHUB_ENV に変数定義の値を送ります。

    steps:
      - name: "Deifne environment variables for Azure"
        run: |
          echo ARM_CLIENT_ID="${{ secrets.ARM_CLIENT_ID }}" >> $GITHUB_ENV
          echo ARM_TENANT_ID="${{ secrets.ARM_TENANT_ID }}" >> $GITHUB_ENV
          echo ARM_SUBSCRIPTION_ID="${{ secrets.ARM_SUBSCRIPTION_ID }}" >> $GITHUB_ENV

ワークフロー ファイルの例

上述の内容を踏まえ、次のような内容になります。

name: 'Terraform'
on:
  push:
    branches:
    - main
  pull_request:
jobs:
  terraform:
    name: 'Terraform'
    runs-on: ubuntu-latest
    environment: production
# 権限設定の追記
    permissions:
      id-token: write
      contents: read
    defaults:
      run:
        shell: bash
    steps:
    - name: Checkout
      uses: actions/checkout@v3
    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}

# Azure での認証情報を定義するステップ
    - name: "Deifne environment variables for Azure"
      run: |
        echo ARM_CLIENT_ID="${{ secrets.ARM_CLIENT_ID }}" >> $GITHUB_ENV
        echo ARM_TENANT_ID="${{ secrets.ARM_TENANT_ID }}" >> $GITHUB_ENV
        echo ARM_SUBSCRIPTION_ID="${{ secrets.ARM_SUBSCRIPTION_ID }}" >> $GITHUB_ENV

    - name: Terraform Init
      run: terraform init
    - name: Terraform Format
      run: terraform fmt -check
    - name: Terraform Plan
      run: terraform plan
    - name: Terraform Apply
      if: github.ref == 'refs/heads/main' && github.event_name == 'push'
      run: terraform apply -auto-approve

Terraform プロバイダーの指定

Terraform プロバイダー側でも少し設定が必要になります。OIDC への対応は 3.7.0 以上の AzureRM プロバイダーなので、required_provides にてバージョンを指定します。

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "= 3.7.0"
    }
  }

}

あとは Terraform ファイルを用意して Azure リソースを作成します。また、プロバイダーの指定は次のようになります。

provider "azurerm" {
  features {}
  use_oidc = true
}

これで Azure・GCP・AWS の主要クラウドに対してGitHub Actions で OIDC 認証できるようになりました!

コメント

タイトルとURLをコピーしました