TerraformをAzure ARMで使う時の認証
高まってまいりました
全国10,000人のTerraformファンのみなさま、こんにちは。applyしてますか。
Terraformのマイナーバージョンアップのたびに、Azure Resource Manager Providerのリソースが追加されているので、ぼちぼちClassic(Service Management)からの移行を考えよう、という人もいるのでは。VMリソースが追加されたら、いよいよ、ですかね。
そこで、Classicとは認証方式が変わっているので、ご注意を、という話です。
client_id/client_secret って何よ
以下がARM向けのProvider設定です。
# Configure the Azure Resource Manager Provider
provider "azurerm" {
subscription_id = "..."
client_id = "..."
client_secret = "..."
tenant_id = "..."
}
subscription_idは、いつものあれ。tenant_idは普段使わないけどどこかで見た気がする。でも、client_id/client_secret って何よ。ためしにポータルログインで使うID/パスワード指定したら、盛大にコケた。
"The provider needs to be configured with the credentials needed to generate OAuth tokens for the ARM API."
おっとそういうことか。OAuth。
サービスプリンシパルを使おう
Terraformをアプリケーションとして登録し、そのサービスプリンシパルを作成し権限を付与すると、使えるようになります。
“アプリケーション オブジェクトおよびサービス プリンシパル オブジェクト”
“Azure リソース マネージャーでのサービス プリンシパルの認証”
以下、Azure CLIでの実行結果をのせておきます。WindowsでもMacでもLinuxでも手順は同じです。
まずは、Terraformをアプリとして登録します。–identifier-urisの存在チェックはないですが、ユニークにしなければいけません。また、–passwordはclient_secretになるので、おぼえておきましょう。
$ azure ad app create --name "My Terraform" --home-page "http://tftest.makabe.info" --identifier-uris "http://tftest.makabe.info" --password pAssw0rd%
info: Executing command ad app create
+ Creating application My Terraform
data: AppId: AppId-AppId-AppId-AppId-AppId
data: ObjectId: AppObjId-AppObjId-AppObjId-AppObjId
data: DisplayName: My Terraform
data: IdentifierUris: 0=http://tftest.makabe.info
data: ReplyUrls:
data: AvailableToOtherTenants: False
data: AppPermissions:
data: claimValue: user_impersonation
data: description: Allow the application to access My Terraform on behalf of the signed-in user.
data: directAccessGrantTypes:
data: displayName: Access My Terraform
data: impersonationAccessGrantTypes: impersonated=User, impersonator=Application
data: isDisabled:
data: origin: Application
data: permissionId: AppPermID-AppPermID-AppPermID-AppPermID
data: resourceScopeType: Personal
data: userConsentDescription: Allow the application to access My Terraform on your behalf.
data: userConsentDisplayName: Access My Terraform
data: lang:
info: ad app create command OK
次にサービスプリンシパルを作ります。AppIdは先ほどアプリを登録した際に生成されたものです。
$ azure ad sp create AppId-AppId-AppId-AppId-AppId
info: Executing command ad sp create
+ Creating service principal for application AppId-AppId-AppId-AppId-AppId
data: Object Id: SpObjId-SpObjId-SpObjId-SpObjId
data: Display Name: My Terraform
data: Service Principal Names:
data: AppId-AppId-AppId-AppId-AppId
data: http://tftest.makabe.info
info: ad sp create command OK
サービスプリンシパルの役割を設定します。–objectIdは、サービスプリンシパルのObject Idなのでご注意を。アプリのObject Idではありません。
この例では、サブスクリプションのContributorとして位置づけました。権限設定は慎重に。
$ azure role assignment create --objectId SpObjId-SpObjId-SpObjId-SpObjId-SpObjId -o Contributor -c /subscriptions/SubId-SubId-SubId-SubId-SubId/
info: Executing command role assignment create
+ Finding role with specified name
/data: RoleAssignmentId : /subscriptions/SubId-SubId-SubId-SubId-SubId/providers/Microsoft.Authorization/roleAssignments/RoleAsId-RoleAsId-RoleAsId-RoleAsId
data: RoleDefinitionName : Contributor
data: RoleDefinitionId : RoleDefId-RoleDefId-RoleDefId-RoleDefId-RoleDefId
data: Scope : /subscriptions/SubId-SubId-SubId-SubId-SubId
data: Display Name : My Terraform
data: SignInName :
data: ObjectId : SpObjId-SpObjId-SpObjId-SpObjId-SpObjId
data: ObjectType : ServicePrincipal
data:
+
info: role assignment create command OK
サービスプリンシパルまわりの設定は以上です。
テナントIDを確認しておきましょう。
$ azure account list --json
[
{
"id": "SubId-SubId-SubId-SubId-SubId",
"name": "Your Subscription Name",
"user": {
"name": "abc@microsoft.com",
"type": "user"
},
"tenantId": "TenantId-TenantId-TenantId-TenantId-TenantId",
"state": "Enabled",
"isDefault": true,
"registeredProviders": [],
"environmentName": "AzureCloud"
}
]
これでようやく.tfファイルが書けます。さくっとリソースグループでも作ってみましょう。
# Configure the Azure Resource Manager Provider
provider "azurerm" {
subscription_id = "SubId-SubId-SubId-SubId-SubId"
client_id = "AppId-AppId-AppId-AppId-AppId"
client_secret = "pAssw0rd%"
tenant_id = "TenantId-TenantId-TenantId-TenantId-TenantId"
}
# Create a resource group
resource "azurerm_resource_group" "test" {
name = "test"
location = "Japan West"
}
apply。もちろんplanしましたよ。
$ terraform apply
azurerm_resource_group.test: Creating...
location: "" => "japanwest"
name: "" => "test"
azurerm_resource_group.test: Creation complete
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
これで、ARM認証難民がうまれなくなりますように。