---
title: "TerraformでAzureを構築する手順｜azurerm 5系の認証とbackend設計"
url: "https://www.issoh.co.jp/tech/details/16542/"
published: 2026-08-14
updated: 2026-09-27
categories: ["Azure"]
publisher: "株式会社一創"
---

# TerraformでAzureを構築する手順｜azurerm 5系の認証とbackend設計

AzureをTerraformで扱うとき、最初に詰まるのはHCLの書き方ではありません。認証をどの方式で通すか、tfstateをどこに置くか、リソースグループをどの単位で切るか。この3点は最初のapplyより前に決まってしまい、後から変えると作り直しが必要です。この記事では、2026年8月14日時点のazurermプロバイダ5.0.1と、Microsoft LearnおよびHashiCorp公式のbackendドキュメントを突き合わせて、決め方を条件付きで示します。5.0で入った破壊的変更と、BicepではなくTerraformを選ぶ条件までを扱います。

## まとめ：先に決める認証方式・tfstateの置き場・RG境界

結論から示します。CIから流すTerraformの認証はOIDC（ワークロードID連携）に寄せ、クライアントシークレットを保持しない構成にしてください。tfstateはAzure Storageに置き、backendの認証はアクセスキーではなくEntra ID認証（`use_azuread_auth`）を使います。リソースグループは「同時に破棄できる範囲」で切り、stateの分割単位と揃えます。

azurermは5.0.1が2026年7月30日公開の最新です。5.0.0（2026年7月27日公開）でリソースプロバイダーの自動登録が既定で行われなくなり、地域とリソースプロバイダーの検証もplan時から外れました。4.x環境からそのまま上げると、planでは通ってapplyで落ちる構成が出ます。そしてAzureだけを対象にし、tfstateの保管と権限設計を担う人を置けないなら、Terraformではなく状態ファイルを持たないBicepのほうが運用は軽くなります。

## azurermプロバイダの初期設定とAzure側で先に決める前提条件

azurermは他のプロバイダと違い、空でも書かなければならないブロックと、4.0以降に必須化された引数があります。ここを飛ばすとinitの直後に止まります。

### features空ブロックとsubscription\_id指定が必須になる理由

azurermの`provider`ブロックには`features {}`が必要です。中身が空でも省略できません。このブロックは、リソース削除時の挙動などプロバイダ全体の振る舞いを切り替える場所として用意されており、5.0では後述する検証設定もこの中へ移動しました。

もう1つが`subscription_id`です。4.0のアップグレードガイドは、プロバイダインスタンスの設定時にAzureサブスクリプションIDの指定が必須になったと明記しています。渡し方は`provider`ブロックの引数か、環境変数`ARM_SUBSCRIPTION_ID`のどちらか。複数サブスクリプションを持つ組織では、ローカルのAzure CLIが向いているサブスクリプションと環境変数の値がずれ、意図しない側にリソースが作られる事故が起きます。[IaCとは？Infrastructure as Codeの仕組み・メリットと導入判断](https://www.issoh.co.jp/column/details/13004/)で整理した宣言的管理の前提は、この「どこに向いているか」が固定されて初めて成立します。applyの前に`az account show`で向き先を確認する運用を、手順書の1行目に置いてください。

### 5.0でリソースプロバイダー登録の既定がnoneへ変わった影響

4.xまでのazurermは、初期化時に約60のリソースプロバイダーを順番に登録しようとしていました。5.0で`resource_provider_registrations`の既定が`legacy`から`none`に変わり、`skip_provider_registration`は削除されています。公式が理由に挙げるのは、起動時の遅延と、サブスクリプションへの権限が絞られた利用者で発生する権限エラーです。

既定がnoneになったということは、未登録のリソースプロバイダーを使う構成はapply時にAzure側から拒否されるということでもあります。対処は2つ。必要なものだけを`resource_providers_to_register`に列挙するか、旧挙動に戻すため`resource_provider_registrations`に`legacy`を明示するかです。新規構築なら前者を選び、Microsoft.Compute・Microsoft.Network・Microsoft.Storageのように使うものだけを書く方針です。既存構成を5.0へ上げる作業では、まず`legacy`で挙動を揃えてから列挙へ絞り込むほうが切り分けやすくなります。プロバイダ版の固定方針そのものは[terraform providerのバージョン制約とalias設計](https://www.issoh.co.jp/tech/details/16540/)で扱っています。

### 拡張バリデーションがfeatures内へ移り既定で無効になった扱い

もう1つの behavioural change が拡張バリデーションです。Azure MetaData Serviceから対応リージョンとリソースプロバイダーの一覧を取得し、`location`などをplan時に検証する機能でしたが、5.0で`features`ブロック内へ移動し、既定は無効になりました。公式の説明は明快で、有効ならplan時に、無効ならapply時にAzureが拒否した時点でエラーになります。

環境変数も変わりました。`ARM_PROVIDER_ENHANCED_VALIDATION`は削除され、`ARM_PROVIDER_ENHANCED_VALIDATION_LOCATIONS`と`ARM_PROVIDER_ENHANCED_VALIDATION_RESOURCE_PROVIDERS`に分かれています。CIでレビュー前に弾きたいなら、`features`内の`enhanced_validation`で`locations`と`resource_providers`をtrueへ戻してください。加えて5.0では`preflight_enabled`が追加され、plan時にAzureのPreflight Validation APIを呼んでポリシー違反やクォータ超過を先に出せます。ただし対応はazurerm\_service\_planやazurerm\_nginx\_deploymentなど6リソースに限られ、plan時に有効な資格情報が要り、他リソースの出力を参照する`(known after apply)`の値は検証要求に含まれません。全面的な安全網ではなく、対象リソースを含む構成での追加確認と考えるのが実態に合います。

## Azureへの認証をローカル実行とCI実行で分ける4方式の選び分け

azurermが対応する認証は、Azure CLI、マネージドID、サービスプリンシパル（クライアントシークレット／クライアント証明書）、OpenID Connectの5系統です。公式の推奨は「非対話実行はサービスプリンシパルかマネージドID、ローカル実行はAzure CLI」。ここに、シークレットを持つか持たないかの軸を足して選びます。

### サービスプリンシパルを作成しARM\_環境変数で安全に渡す手順

Microsoft Learnの手順は、`az ad sp create-for-rbac`に`--role Contributor`とサブスクリプションスコープを指定してサービスプリンシパルを作り、出力された`appId`・`password`・`tenant`を環境変数へ移す流れです。渡す変数は`ARM_SUBSCRIPTION_ID`・`ARM_TENANT_ID`・`ARM_CLIENT_ID`・`ARM_CLIENT_SECRET`の4つ。同ページは資格情報をプロバイダブロックへ書かないよう明記しており、コード内に書く例は完全性とテスト目的に限ると断っています。

- パスワードは作成時の出力からしか取得できず、紛失時はリセットが必要
- Contributorはサブスクリプション全体に及ぶため、対象が限定的ならリソースグループスコープへ絞る
- Git Bashで作成する場合は`MSYS_NO_PATHCONV`を設定しないとスコープのパスが変換される

実務で効くのは2番目です。検証用のサブスクリプションならContributorで構いませんが、本番と共有しているサブスクリプションに全体権限のSPを1つ置くと、そのシークレットの管理コストが構成全体のリスクになります。

### CIの認証をOIDCへ寄せてシークレットを保持しない実践構成

HashiCorpのbackendドキュメントは、Entra ID認証のなかでもOpenID Connect（ワークロードID連携）を最も推奨し、クライアントシークレットとクライアント証明書については秘密の管理と回転が必要だとして非推奨に置いています。GitHub ActionsやAzure Pipelinesから流すなら、この方式が既定の選択になります。

設定は`use_oidc`（環境変数は`ARM_USE_OIDC`）で有効化し、Entra ID側でアプリ登録にフェデレーション資格情報を追加して、リポジトリとブランチを信頼の条件に含めます。CI変数に置くのはクライアントIDとテナントIDとサブスクリプションIDだけになり、有効期限のあるシークレットが構成から消えます。新規にCIを組むなら、クライアントシークレットを秘密変数へ登録する構成は選ばないでください。回転漏れで止まるか、漏洩時の影響範囲が読めないかのどちらかに向かいます。

### マネージドIDとAzure CLI認証を使い分ける条件の整理

Azure上のVMやセルフホストランナーからTerraformを流すなら、マネージドIDが素直です。`use_msi`（`ARM_USE_MSI`）で有効化し、システム割り当てなら`client_id`の指定は不要、ユーザー割り当てなら対象のクライアントIDを指定します。認証情報がホスト側に紐づくため、リポジトリにもCI変数にも秘密が残りません。実行基盤を[Azure Virtual Machines](https://www.issoh.co.jp/tech/details/15643/)に置く構成では、この方式が管理の手数を最も減らします。

Azure CLI認証はローカル開発向けです。`az login`した人の権限でそのまま動くため、planを回して差分を読む用途には手軽さがあります。裏を返せば、個人の権限で本番へapplyできる状態が残るということでもあります。ローカルからのapplyを禁止し、planまでに限る。この線引きを守れないなら、Azure CLI認証は本番サブスクリプションへ向けないでください。

## tfstateをAzure Storageへ置くbackendの設定と認証の切り替え

stateの置き場はAzure Storageのblobコンテナーが標準です。ここでの選択は、置くかどうかではなく、どの認証で読み書きするかに移っています。

### backend azurermの必須引数とBLOBリースによる排他制御

backendの必須引数は3つだけです。残りは認証方式と環境の指定で、用途に応じて足します。

| 引数                     | 要否 | 指定する内容          |
| ---------------------- | -- | --------------- |
| storage\_account\_name | 必須 | ストレージアカウント名     |
| container\_name        | 必須 | BLOBコンテナー名      |
| key                    | 必須 | stateファイルのBLOB名 |
| resource\_group\_name  | 任意 | アカウントが属するRG名    |
| use\_azuread\_auth     | 任意 | Entra ID認証の有効化  |
| snapshot               | 任意 | 更新前のBLOB退避      |

ロックはDynamoDBのような別テーブルを要しません。Blob Storageのネイティブ機能で排他制御と一貫性チェックが行われ、Microsoft Learnも書き込み操作の前に自動でロックされると説明しています。ロック状態はポータルでBLOBを見れば確認できます。暗号化も保存前に自動で行われ、Terraformは取得したstateをローカルメモリに保持するのでディスクへは書かれません。tfstateそのものの構造や、ローカルからリモートへ移すときの手順は[Terraform stateとは？tfstateの構造とバックエンド移行の安全手順](https://www.issoh.co.jp/tech/details/16525/)で扱っています。

### アクセスキー方式からEntra ID認証へ切り替える判断基準

ここが日本語の情報で最も食い違う箇所です。Microsoft Learnの「Terraform状態をAzure Storageに格納する」は`ARM_ACCESS_KEY`にストレージアクセスキーを入れる手順で書かれており、ページの更新日は2023年5月8日のまま。一方HashiCorpのbackendドキュメントは、アクセスキーとSASトークンを後方互換のために残しているだけの方式と位置づけ、新しいワークロードには推奨しないと明記しています。

手順書をそのまま写すとキー方式になります。新規に組むなら`use_azuread_auth`を有効にし（環境変数は`ARM_USE_AZUREAD`）、実行主体にストレージBLOBデータ共同作成者相当のロールを割り当ててください。キーが構成から消えれば、ストレージアカウント側でキーによるアクセス自体を無効化でき、tfstateへ到達できる経路がEntra IDのロール割り当てだけに収まります。既存構成でキー方式を使っている場合も、切り替え自体は`init -reconfigure`で完結し、stateの中身には触れません。移行の難易度は低く、先送りする理由のほうが見つかりにくい変更です。

### state用ストレージのネットワーク制限と機密値の安全な取り扱い

tfstateは平文で保存され、リソースによっては接続文字列やパスワードがそのまま載る状態です。Microsoft Learnも、状態が適切に保護されない場合はシステムへの不正アクセスやデータ損失につながると書いています。同ページのサンプルはパブリックネットワークアクセスを許可したままで、本番ではストレージファイアウォール、サービスエンドポイント、プライベートエンドポイントのいずれかで制限するよう注意書きが添えられています。

state用ストレージアカウントは、他の用途と相乗りさせない。これが最初の線引きです。そのうえでプライベートエンドポイントを引き、CIランナーからの経路だけを許可する構成です。アプリケーションが使うシークレットは[Azure Key Vaultによるシークレット・キー・証明書の一元管理](https://www.issoh.co.jp/tech/details/15531/)側へ寄せ、Terraformからは参照だけを行う形にすると、stateに載る機密の量そのものを減らせます。値をコードへ書かない工夫より、stateに残る値を減らす設計のほうが効きます。

## リソースグループとサブスクリプションの境界を決める設計判断基準

AWSにはない判断がリソースグループです。すべてのリソースがいずれかのRGに属し、RG自体もロケーションを持ちます。この境界の切り方が、後のstate分割と権限設計を決めます。

### リソースグループをライフサイクル単位で切る具体的な判定基準の整理

基準は1つ、同時に破棄できるかどうかです。アプリケーションのWebアプリとその前段、専用のデータベースのように、まとめて作り直せるものは同じRGに収める設計です。逆に、共有ネットワークやstate用ストレージ、Key Vaultのように寿命が違うものは別RGへ出します。「環境ごと」「チームごと」といった組織図に沿った分け方は、破棄の単位と一致しないので後で崩れます。

RGの境界はstateの分割単位と揃えてください。1つのstateが複数RGにまたがると、片方だけ作り直したいときにplanの影響範囲が読めなくなります。開発・検証・本番の分け方そのものは、ディレクトリ分割かworkspaceかで運用が変わるため、[terraform workspaceの使い方と環境分離の判断基準](https://www.issoh.co.jp/tech/details/16529/)の比較を先に通してから、RGの命名に落としたほうが手戻りがありません。

### RG削除を止める既定フラグと片付けの順序で詰まる典型的な場面

`features`ブロックの`resource_group`には`prevent_deletion_if_contains_resources`があり、既定値はtrueです。RG内にリソースが残っている状態で`azurerm_resource_group`を削除しようとすると、Terraformが先にチェックして失敗させます。

これが効いてくるのは、Terraform管理外のリソースがRGに紛れ込んだときです。ポータルから誰かが足したVM、Azure側が自動生成する付随リソース、削除に時間のかかる論理削除つきのリソース。destroyがRGの手前で止まり、原因がコードに見当たらないという形で現れます。切り分けは、ポータルでRGの中身を一覧して管理外のものを特定するところから始めてください。フラグをfalseにすれば通りますが、それはTerraformが知らないリソースごと消す挙動です。検証環境の使い捨てRGに限って許容し、本番では既定のtrueのまま運用してください。ここを緩めた構成は、いつか他チームのリソースを巻き込みます。

### azurermに未対応のリソースをazapiで補うときの線引き

azurermはリソース種別ごとにスキーマを実装するため、Azure側で新機能が出てからプロバイダが追随するまで時間差があります。Bicepが新しいAPIバージョンを即日使えるのと対照的な弱点です。この差を埋めるのがazapiプロバイダ（azure/azapi、2026年8月10日公開の2.12.0が最新）で、ARMのAPIを直接叩いてリソースを定義できます。

使う条件を狭く決めてください。プレビュー段階の機能、azurermに未実装のプロパティ、特定リージョン限定の設定。この3つに限り、azurermへ実装された時点で書き換える前提で入れます。恒久的にazapiで書くと、ARMのJSONスキーマをHCLで手書きし続けることになり、azurermが提供する検証も既定値の補完も効きません。プロジェクトのコード内でazapiが占める割合が1割を超えたら、そもそもTerraformで書く必然性を疑うほうが早い段階です。

## BicepとTerraformの使い分けをAzure単独か否かで言い切る

「TerraformとBicepのどちらが優れているか」には答えがありません。答えが出るのは、対象がAzureだけか、状態を運用できる体制があるか、という2つの条件を先に置いたときです。

### Azure専用ならBicepを選ぶ条件と状態管理が不要になる利点

Bicepは宣言型のAzure専用言語で、デプロイ時にBicep CLIがARMテンプレートのJSONへ変換します。公式が挙げる特徴のうち、Terraformとの比較で決定的なのは3つです。すべてのリソース種類とAPIバージョンを即座にサポートすること、What-If操作で適用前に変更をプレビューできること、そして「管理する状態または状態ファイルがない」こと。状態はAzure側にすべて格納されます。

tfstateがないという性質は、この記事でここまで積み上げてきた設計判断をまるごと不要にします。stateの置き場も、backendの認証方式も、stateに載る機密値の扱いも考えなくてよい。費用もかからず、Microsoftのサポート対象です。対象がAzureのみで、Azure Policyやテンプレートスペックとつなぎたいなら、Bicepを選んでください。Terraformを入れる理由が「IaCといえばTerraformだから」しかないなら、それは理由になっていません。

### Terraformを採用する条件と見送るべき体制上の具体的な場面

Terraformを選ぶ条件は3つです。Azure以外のクラウドやSaaSを同じ手順で扱いたいこと、planの差分をレビュー材料として使いたいこと、moduleとして構成を再利用したいこと。とくに2番目は、Bicepのwhat-ifが持たない「宣言した期待値と現物の差」という形式でレビューできる点で、変更頻度の高い環境では効きます。Google Cloud側を同じ手順で扱う場合の認証とbackendの違いは[TerraformでGCPを構築する手順とgoogle 7系の認証・GCSバックエンド設計](https://www.issoh.co.jp/tech/details/16544/)にまとめています。

見送る条件も条件付きで言い切ります。対象がAzure単独で、インフラ変更が月に数回で、tfstateの保管と権限設計を継続的に担う人を置けない。この3つが揃うなら、Terraformを入れないでください。壊れるのはコードではなくstateで、state破損は担当者不在の組織では復旧できません。判断がつかない、あるいは既存環境の棚卸しから始めたい場合は、[AWS・Google Cloud・Azureのインフラ構築](https://www.issoh.co.jp/service/system/aws/)で扱っている構成設計と運用引き継ぎの範囲から相談してください。

### BicepからTerraformへ移す場合の作業量とimportの見積り

すでにBicepやポータルで作ったAzure環境をTerraform管理下に入れるには、importが要ります。作業はリソースを書き写すだけでは終わりません。リソース種別ごとにAzureのリソースIDの形式を調べ、importしたうえで、planが「変更なし」に落ち着くまで実物の属性をコードへ書き戻す。この最後の工程が全体の時間を決めます。

5.0へ上げるタイミングでの移行なら、削除済みリソースへの対応も同時に必要です。`azurerm_app_service`は`azurerm_linux_web_app`と`azurerm_windows_web_app`へ、`azurerm_app_service_plan`は`azurerm_service_plan`へ、`azurerm_ai_services`は`azurerm_cognitive_account`へ置き換わっています。古い記事のコードをそのまま持ち込むと5.0では動きません。現実的な進め方は一括移行を避けることです。新しいサブスクリプションか新しいRGから Terraform で作り、既存はBicepのまま据え置く。境界をRG単位で切っておけば、同じ環境に両方が存在しても衝突しません。

## よくある質問

TerraformでAzureを扱うときに問い合わせの多い5点をまとめました。

### azurermのバージョンはどう固定すればよいですか？

`required_providers`の`version`で桁を決め、実際の版は`.terraform.lock.hcl`に記録させます。2026年8月14日時点の最新は5.0.1（2026年7月30日公開）です。4.xから上げる場合は、リソースプロバイダー登録と拡張バリデーションの既定変更を先に確認してください。桁の決め方とlockファイルの運用は、terraform providerの記事で詳しく扱っています。

### Azure CLIでログインしていればTerraformは動きますか？

動きます。azurermはAzure CLI認証に対応しており、公式もローカル実行ではこの方式を推奨する立場です。ただし4.0以降は`subscription_id`の指定が別途必須で、CLIが向いているサブスクリプションと一致しているかは自分で確認する必要があります。CIサーバーでの実行にはサービスプリンシパルかマネージドIDを使ってください。

### tfstateはローカルとAzure Storageのどちらに置くべきですか？

1人で使う場合でもAzure Storageに置いてください。理由はロックと消失対策です。Blob Storageのネイティブ機能で書き込み前に自動ロックがかかり、保存前に暗号化されます。ローカルstateは端末の紛失や誤削除でそのまま復旧不能になり、チームに人が増えた時点で必ず移行作業が発生します。

### Terraformで作ったリソースをポータルから変更してもよいですか？

次回のplanで差分として現れます。緊急対応で触った場合は、変更内容をコードへ反映してplanが空になる状態まで戻してください。放置するとapplyのたびに元へ戻され、意図しない切り戻しが起きます。リソースグループ内に管理外のリソースを足した場合は、既定でRGの削除が失敗するようになる点にも注意が必要です。

### BicepとTerraformを同じプロジェクトで併用できますか？

併用できます。条件は、同じリソースを両方から書かないことです。境界はリソースグループ単位で切るのが最も安全で、共有ネットワークはBicep、アプリケーション基盤はTerraformといった分け方になります。同一リソースを両方の管理下に置くと、片方の適用がもう片方の差分を生み続けます。

## 関連記事

- [IaCとは？Infrastructure as Codeの仕組み・メリットと導入判断を解説](https://www.issoh.co.jp/column/details/13004/)：宣言的な構成管理の考え方と導入判断。
- [terraform providerのバージョン制約とalias設計｜lockファイルの運用判断](https://www.issoh.co.jp/tech/details/16540/)：版の固定方針とlockファイルの運用。
- [Terraform stateとは？tfstateの構造とS3バックエンド・移動削除の安全手順](https://www.issoh.co.jp/tech/details/16525/)：stateの構造とバックエンド移行。
- [terraform workspaceの使い方と環境分離の判断基準｜分割方式の比較](https://www.issoh.co.jp/tech/details/16529/)：環境をどう分けるかの方式比較。
- [Azure Virtual Machinesとは？仕組み・VMシリーズ・料金モデルと可用性設計](https://www.issoh.co.jp/tech/details/15643/)：Terraformで扱うAzure側の代表リソース。

---

出典: [TerraformでAzureを構築する手順｜azurerm 5系の認証とbackend設計](<https://www.issoh.co.jp/tech/details/16542/>)（株式会社一創）
