【Azure】Terraform用のサービスプリンシパルを用いてWeb Appsを作成する。

# 1. はじめに
### 1-1 ご挨拶
初めまして、井村と申します。
Terraform用のサービスプリンシパルを用いてWeb Appsを作成しました。
Web Apps作成の解説よりはサービスプリンシパル作成、Terraformの細かい記述をメモする用の記事投稿になります。

### 1-2 対象読者
- Azureに興味がある
- Terrafomに興味がある

### 1-3 成果物を作成する際の前提条件
- [Azureアカウント](https://azure.microsoft.com/ja-jp/free/)がある。
- [Azure CLI](https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli)と[Terraform](https://www.terraform.io/downloads)がインストール済み。
※[Azure CLIとTerraformの初期セットアップ](https://qiita.com/takaki-imura/items/1d1a2132100300d1010c)

### 1-4 成果物
- Terraform用のサービスプリンシパル
- 下図のとおりリソースグループ、Azure App Service Plans、Web Appsを作成。(FreeプランのAzure App Service Plansです。)

![SystemConfiguration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/133b7445-618e-c91b-174d-f29fc5aaf535.png)

### 1-5 Terraformディレクトリ構造

```
.
├── env
│   └── dev
│       ├── main.tf
│       ├── outputs.tf
│       ├── provider.tf
│       ├── terraform.tfvars
│       └── variable.tf
└── modules
    ├── app
    │   ├── main.tf
    │   ├── outputs.tf
    │   └── variables.tf
    ├── asp
    │   ├── main.tf
    │   ├── outputs.tf
    │   └── variables.tf
    └── rg
        ├── main.tf
        ├── outputs.tf
        └── variables.tf
```

ソースコードはGitHubにあります。
[https://github.com/hawk0722/Azure_Terraform_03_webapp](https://github.com/hawk0722/Azure_Terraform_03_webapp)

# 2. 構築
### 2-1 サービスプリンシパルの作成
名前は"sp-terra"としてサービスプリンシパルを作成します。
適用範囲はサブスクリプション、権限は共同作成者になります。

サブスクリプションIDの確認は以下コマンドを実行。
```bash:bash
az account show
```

出力結果のサブスクリプションIDを控える。
```bash:bash
{
  "environmentName": 省略,
  "homeTenantId": 省略,
  "id": "<azure_subscription_id>",
  "isDefault": 省略,
  "managedByTenants": [],
  "name": 省略,
  "state": 省略,
  "tenantId": 省略,
  "user": {
    "name": 省略,
    "type": 省略
  }
```

下記コマンドでサービスプリンシパルを作成。
※[az ad sp create-for-rbacの参考URL](https://learn.microsoft.com/ja-jp/cli/azure/ad/sp?view=azure-cli-latest#az-ad-sp-create-for-rbac)

```bash:bash
az ad sp create-for-rbac --role Contributor --scopes "/subscriptions/<azure_subscription_id>" --name "sp-terra"
```

出力結果のアプリケーション（クライアント）ID、ディレクトリ (テナント) ID、パスワードを控える。
```bash:bash
{
  "appId": "<azure_subscription_tenant_id>",
  "displayName": "sp-terra",
  "password": "<service_principal_password>",
  "tenant": "<service_principal_appid>"
}
```

上記でサービスプリンシパルは作成されました。Terraformに反映させるため、資材をダウンロードします。
```bash:bash
mkidir work
cd work
git clone https://github.com/hawk0722/Azure_Terraform_03_webapp.git
```

下準備はokです。

### 2-2 terraform.tfvarsの修正
本資材は「Azure_Terraform_03_webapp/env/dev/terraform.tfvars」のみ修正します。
2-1で取得した各IDおよび必要な変数を適宜修正します。

```tf:terraform.tfvars
# azure service principal info
subscription_id = "<azure_subscription_id>"
tenant_id       = "<azure_subscription_tenant_id>"
client_id       = "<service_principal_appid>"
client_secret   = "<service_principal_password>"

# common
location = "japaneast"
env      = "dev"
code     = "hawk"

# App Service Plan
asp_os_type  = "Linux"
asp_sku_name = "F1"

# App Service
python_version = "3.9"
```
### 2-3 Azureリソースのデプロイ
以下コマンドを実行してAzureリソースを作成します。
```bash:bash
# ルートモジュールへ移動
cd Azure_Terraform_03_webapp/env/dev

# ワークスペースを初期化する
terraform init

# 実行計画の参照
terraform plan

# リソースのデプロイ
terraform apply

```
### 2-4 動作確認
デプロイされたWeb Appsの動作確認をします。
ローカル端末のブラウザに以下URLを張り付けます。

```
https://<app_name>.azurewebsites.net
※<app_name>はWeb Appsサービスの名前
```

<img width="500" alt="webapp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/aa51bed7-9902-f364-df72-eeae1a86f9dc.png">

# 3. 補足
### 3-1 サービスプリンシパルについて
下図のとおりAzureは階層型になっています。サブスクリプションレイヤにTerraform用のサービスプリンシパルを作成＆権限付与をすると、下位のリソースグループ、Azureリソースを作成することができます。

![layer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/18a3ac10-2866-373c-184e-0b83fd32b44a.png)

[Azure サブスクリプション、管理グループ、リソースの概要](https://learn.microsoft.com/ja-jp/training/modules/azure-architecture-fundamentals/overview)

Azureポータル上では"Azure Active Directory"→"アプリの登録"からサービスプリンシパルを確認することができます。

![app-reg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/4c617418-9e3b-c4e4-0d03-8ab34c8a8769.png)

### 3-2 env/dev/outputs.tf
このファイルにはターミナルの画面に出力したいもの記述します。今回はデプロイされたAzureサービスの名前を出力しています。

```tf:outputs.tf
# Output to terminal screen.
output "rg_name" {
  value = module.rg.rg_name
}

output "app_name" {
  value = module.app.app_name
}

output "asp_name" {
  value = module.asp.asp_name
}

```

```bash:出力結果
# リソースのデプロイ
terraform apply

～ 省略 ～

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

app_name = "app-dev-hawk"
asp_name = "asp-dev-hawk"
rg_name = "rg-dev-hawk"
```

### 3-3 各ファイルの変数受け渡しについて
以前自分が投稿した[記事](https://qiita.com/takaki-imura/items/93f49db3ac604ec37d21)(というかその記事の参考記事)に記載あります。

# 4. おわりに
本記事を最後まで読んで頂きましてありがとうございます。
最近GitHubに自分が作成した成果物をあげてます。理由は参画しているプロジェクトでファイルのバージョン管理をGitLabでしているからです。今まで案件で触ったことが無く、Git詳しい方がメンバーにいたので何とかプロジェクトに影響はなかったのですが。。今時は必須スキルなので、個人で練習がてら触っている感じです。

成果物の修正にてブランチ切って、コード修正して、プッシュして、マージするの楽しいですね。

# 5. 参考記事
- [az ad sp create-for-rbac](https://learn.microsoft.com/ja-jp/cli/azure/ad/sp?view=azure-cli-latest#az-ad-sp-create-for-rbac)
- [Azure Terraform error: Service returned an error. Status=<nil> <nil> when creating an Azure Web App](https://blog.masterwayz.nl/azure-terraform-error-status-nill-nill/)
- [terraform-provider-azurerm/examples/app-service/linux-basic/main.tf](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/examples/app-service/linux-basic/main.tf)
- [azurerm_linux_web_app](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_web_app)