理系学生日記

おまえはいつまで学生気分なのか

Azure上のTerraform Backendに対してAD認証を行う

AzureをTerraformで管理する場合、TerraformのRemote Stateとして Azure Blob Storageを設定することになります。

ここで問題になるのはAzure Blob Storageに対する認証でしょう。

Azure Blob Storageの認証方法は大きく分けて2つあります。

  • 共有キー認証
  • Azure Active Directory (Azure AD)認証

共有キー

Azureのドキュメントの中では「アクセスキー」とも呼ばれているもので、512 bitから構成されます。 実はアクセスキーという名前から受ける印象ほど軽い存在ではなく、Storage Accountから見るとrootパスワードに等しいものです。

ストレージ アカウントのアクセス キーは、ストレージ アカウントの root パスワードに似ています。 アクセス キーは常に慎重に保護してください。

Azure Storage の接続文字列を構成する

アクセスキー自体は、以下のようなコマンドで得ることができます。1つのStorage Accountに対して2つ設定されます。

$ az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $STORAGE_ACCOUNT_NAME --query '[].value' --output tsv

もちろん、TerraformでもBackendとなるBlob Storageにアクセスするため、こちらの共通キー認証にも当然対応しています。

ただし、.tfファイルにこのような秘匿性の高い情報を露出させるわけにもいきません。このため、環境変数ARM_ACCESS_KEYに設定するのがスタンダードでしょう。

This can also be sourced from the ARM_ACCESS_KEY environment variable.

access_key

Azure Active Directory (Azure AD)認証

UNIXにおいてrootパスワードを通常は利用しないのと同様、Azureにおいても共通キー認証よりもAzure AD認証の方を推奨しています。

BLOB およびキューのデータに対する要求を承認するには、共有キーではなく、可能であれば Azure Active Directory (Azure AD) を使用することをお勧めします。 Azure AD では、共有キーよりも優れたセキュリティと使いやすさが実現されます。

Azure Storage の接続文字列を構成する

Azure AD認証では、Azure AD上に登録されたプリンシパルであるかどうかを認証し、当該プリンシパルが適切な権限を持っているかを確認(認可)します。 Terraformという文脈で考えると、Terraformを実行するユーザーがこれらの条件を満たせるかが鍵です。

それでは、Terraform実行ユーザーに渡すべき権限は何なのでしょうか。答えから記述すると以下になります。

  1. Backendが構築されるStorage Accountに対するReaderロール
  2. Blobへのアクセスを可能とするロール

後者である2.については、Backend(tfstate)に対して何をするかによって左右されます。 読み取りだけでよければStorage Blob Data Readerで良いでしょう。 一方で、通常のTerraform実行ではtfstateを書き換えるので、 Storage Blob Data Contributorあたりが妥当です。

このあたりの詳細については以下をご参照ください。

Terraformでこれらのロールを割りつける場合は以下のようになるでしょう。

# Terraform Backend用のStorage Accountに対し、Terraform 実行ユーザがAzure AD認証でアクセスできるようにする。
# このためユーザに対し、ストレージアカウントに対する Reader、ストレージ BLOB データ共同作成者ロールを付与する
# see: https://docs.microsoft.com/ja-jp/azure/storage/blobs/authorize-data-operations-portal#use-your-azure-ad-account
resource "azurerm_role_assignment" "reader" {
  for_each = toset(["Reader", "Storage Blob Data Contributor"])

  scope                = azurerm_storage_account.backend.id
  role_definition_name = each.key
  principal_id         = azuread_group.terraformer.object_id
}

TerraformからAD認証を指定する

TerraformでBackendアクセス時にAD認証を要求する場合は、use_azuread_authを使用します。 以下のようにbackendブロックの中で指定することになります。

terraform {
  required_version = "~> 1.0.0"

  (略)

  backend "azurerm" {
    resource_group_name  = "rg_kiririmodestaging_tfstate"
    storage_account_name = "stkiririmodestaging"
    container_name       = "tfstate"
    key                  = "terraform.tfstate"

    use_azuread_auth = true
  }
}

注意すべきはARM_ACCESS_KEYをunsetしておくことです。 この環境変数が有効な場合、use_azuread_authを指定していたとしてもTerraformは共通キー認証を選択する挙動になっていました。

$ unset ARM_ACCESS_KEY