理系学生日記

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

TerraformでMSI認証を使うというのはどういうことか

Terraformに関するAzureの認証方法はいくつかあります。これはAzure Providerのページにもまとめられています。

  • Authenticating to Azure using the Azure CLI
  • Authenticating to Azure using Managed Service Identity
  • Authenticating to Azure using a Service Principal and a Client Certificate
  • Authenticating to Azure using a Service Principal and a Client Secret

これだけの選択肢があると実体としてどの認証方法がベストなのか、ということになります。 まだAzureについてほとんど何も分かっていない状態ですが、MSI認証が有望そうです。このエントリはMSI認証とは果たしてなんなのかをまとめてみます。

マネージドID

MSIというのはManaged Service IDの略なのですが、これは現在「マネージドID」と呼ばれるものです1

Managed identities for Azure resources is the new name for the service formerly known as Managed Service Identity (MSI).

Managed identities for Azure resources | Microsoft Docs

マネージドID自体は、開発者がAzure上のリソースへアクセスする際にクレデンシャルを利用しなくて済むことを目的としたIDです。

(マネージドIDに対応しているサービスの)リソースを作成する際、Azure AD上にマネージドIDが作成されます。 マネージドIDには紐づくリソースに対し誰がアクセスできるのかというような権限を付与でき、これもAzure ADにて管理されます。

いざ当該リソースにアクセスする必要が出た場合、Azure ADに対して認可判断が行われ、認可OKとなった場合はAzure ADからトークンが返却されます。このトークンを使ってリソースへのアクセスを行えます。

Azure リソースのマネージド ID と Azure 仮想マシンの連携にあるこの図が非常にわかりやすく、この流れを説明しています。

このフローでは、クレデンシャルは全く露出せず安全にリソースアクセスが可能になります。

AWSで言えば、EC2に与えるInstance Profileのようなものですね。

TerraformでMSI認証を行うには

TerraformでMSI認証する場合、Terraformを実行するVMやAzure Functionに対してマネージドIDを作成し、そこにリソースを作成するだけの協力な権限を与える流れになります。 つまり、VMやAzure FunctionといったAzure内リソースからTerraformを実行する場合にのみ、この方法が取れるということになるでしょう。

実際に公式のサンプルがAzure Provider: Authenticating using managed identities for Azure resourcesにあります。ここでは、Azure VMにContributorロールを与える定義になっています。

data "azurerm_subscription" "current" {}

resource "azurerm_virtual_machine" "example" {
  # ...

  identity {
    type = "SystemAssigned"
  }
}

data "azurerm_role_definition" "contributor" {
  name = "Contributor"
}

resource "azurerm_role_assignment" "example" {
  name               = azurerm_virtual_machine.example.name
  scope              = data.azurerm_subscription.primary.id
  role_definition_id = "${data.azurerm_subscription.subscription.id}${data.azurerm_role_definition.contributor.id}"
  principal_id       = azurerm_virtual_machine.example.identity[0]["principal_id"]
}

  1. Azureはこういった名称変更が頻繁に行われるので、なかなか全体像を掴むのがつらい。