こんにちは、ACS 事業部の埜下です。
年の瀬にあまり前向きな話ではないのですが、今回は Terraform Cloud のノーコードプロビジョニングにまつわるエトセトラです。
ノーコードプロビジョニングとは
Terraform Cloud の Plus プランでは「ノーコードプロビジョニング」と呼ばれる機能を使えます。 ノーコードプロビジョニングを使うと、あらかじめ Terraform Cloud プライベートレジストリに登録しておいた Terraform モジュールを Terraform Cloud 上から実行できます。
従来の手順で Terraform モジュールを実行しようとした場合、ルートモジュールとして以下のような Terraform モジュールを参照する記述が必要です。
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" } } } provider "azurerm" { features {} } module "enterprise_scale" { source = "Azure/caf-enterprise-scale/azurerm" # <- module ブロックで実行する Terraform モジュールを指定 (snip) }
Terraform のコードを書ける方なら Terraform モジュールを組み合わせて柔軟に IaC コードを作成できますが、Terraform 未経験者や特定の Terraform モジュール 1 つだけ実行したい方には上記のコードを書くだけでもハードルが上がってしまいますよね。
ノーコードプロビジョニングを使うことで上記のコードが不要になります。
プラットフォームの IaC コードを Terraform で提供するメンバーが Terraform モジュールを作成して、Terraform Cloud のプライベートレジストリに「ノーコードプロビジョニング用モジュール」として登録しておきます。 利用者は Terraform Cloud から実行したい Terraform モジュールを選択してワークスペースを作成します。 ワークスペース作成と同時に Terraform Plan と Apply が実行され、Terraform モジュールが定義したリソースが作られます。
「ワークスペースを作成する」ところが今回のポイントです。 ノーコードプロビジョニングを利用するにはワークスペースの作成が必須、かつワークスペース名は利用者が任意で付けられます。 つまり、Terraform モジュール提供側がハンドリングできない部分になり、ここが Dynamic Provider Credentials に影響してきます。
Dynamic Provider Credentials とは
つづいて Dynamic Provider Credentials ですが、こちらは Terraform の各プロバイダがクラウドプラットフォームに接続する際の資格情報を動的に生成する機能になります。 Dynamic Provider Credentials はクラウドプラットフォーム毎に仕様や設定方法が異なり、本記事では Azure 用の Dynamic Provider Credentials を「Dynamic Provider Credentials for Azure」と記載しています。
AzureRM/AzureAD プロバイダの場合、Terraform Cloud から Azure に接続するには事前にサービスプリンシパルを作成しておく必要があります。 従来の方法ではサービスプリンシパルのクライアントシークレットを作成して Terraform Cloud ワークスペースの環境変数に登録して利用していました。 クライアントシークレットは「有効期限が最大 24 ヶ月」であること、「ローテーションされるまでシークレット値は静的な情報」であることが運用、セキュリティ面での課題となります。
Dynamic Provider Credentials for Azure はクライアントシークレットの代わりにサービスプリンシパルに対して「フェデレーション ID 資格情報」を作成することになります。 フェデレーション ID 資格情報には Terraform Cloud 上の組織 (Organization)、プロジェクト (Project)、ワークスペース (Workspace) の情報を含んだ識別子を登録します。 これにより Terraform Cloud が発行した OpenID Connect (OIDC) 準拠のトークンが認証され、Terraform Cloud で AzureRM/AzureAD プロバイダ実行中のみ使用できる資格情報が作られます。 クライアントシークレットと比べると運用、セキュリティ面で有利な点が多いため是非とも使いたい機能です。
そんな Dynamic Provider Credentials にも制約があります。
それは「フェデレーション ID 資格情報は Terraform Cloud のワークスペースまで指定が必須」ということです。
フェデレーション ID 資格情報の識別子 (Subject identifier) には organization:<ORGANIZATION>:project:<PROJECT>:workspace:<WORKSPACE>:run_phase:<RUN_PHASE>
というフォーマットを使うことが決まっているのですが、ここでワイルドカードは使用できません。
例えば、「プロジェクト A 内のワークスペース α と β」で Dynamic Provider Credentials を利用したい場合、[workspace] には workspace-alpha
と workspace-beta
を分ける必要があります。
また、[run_phase] も plan
と apply
をそれぞれ分けなければなないので、サービスプリンシパルのフェデレーション ID 資格情報は 4 つ作成することになります。
- organization:example-org:project:project-a:workspace:workspace-alpha:run_phase:plan
- organization:example-org:project:project-a:workspace:workspace-alpha:run_phase:apply
- organization:example-org:project:project-a:workspace:workspace-beta:run_phase:plan
- organization:example-org:project:project-a:workspace:workspace-beta:run_phase:apply
他にも「1 つのサービスプリンシパルに作成できるフェデレーション ID 資格情報は最大 20 個」という制約もありますが、今回のノーコードプロビジョニングにフェデレーション ID 資格情報の個数は大きく影響しませんので軽く紹介するだけに留めておきます。
Dynamic Provider Credentials は対象となるプロバイダ毎に少し仕様が異なりますので、詳しくは公式ドキュメントを参照ください。
なぜ相性が良くないのか
それでは本題、なぜ Terraform Cloud のノーコードプロビジョニングは Dynamic Provider Credentials for Azure と相性が良くないのか説明します。
前章でノーコードプロビジョニングと Dynamic Provider Credentials の特徴について説明しました。 特に次の仕様が影響してきます。
- ノーコードプロビジョニング利用時はワークスペースが新規作成される
- Dynamic Provider Credentials for Azure はフェデレーション ID 資格情報にワークスペース名の指定が必須
上記の特徴から導き出されるのは「 AzureRM/AzureAD プロバイダを使うノーコードプロビジョニングのワークスペースは Dynamic Provider Credentials による認証がむずかしい」ということです。
ノーコードプロビジョニングで作られたワークスペースは利用者が任意の名前をつけられます。 それ故に、そのワークスペース名がフェデレーション ID 資格情報に登録されて Dynamic Provider Credentials で認証エラーとなってしまうことが多くなります。
もちろん、事前にワークスペース名を指定したフェデレーション ID 資格情報を作成しておく、ワークスペース作成直後のエラーは見逃して後追いでアプリケーション管理者にフェデレーション ID 資格情報を作ってもらう、等の運用でカバーすることも可能です。 しかし、これでは利用者側の負担が増えてノーコードプロビジョニングのメリットが減ってしまいます。
そのため、「認証ができない」ではなく「認証がむずかしい」と表現しました。
ということで、現時点では AzureRM/AzureAD プロバイダを使うノーコードプロビジョニングはワークスペースの認証情報にクライアントシークレットを使うのが望ましいのでは?と考えます。 前章でも述べたようにクライアントシークレットにも運用、セキュリティ面での課題がありますので Dynamic Provider Credentials とはトレードオフの関係になります。
ノーコードプロビジョニングで「クライアントシークレット」と「Dynamic Provider Credentials」のどちらを採用するかは組織内で十分に検討したうえで決めてください。
AWS ではフェデレーション ID 資格情報のワークスペース部分にワイルドカードを指定できるようです。 Azure もワイルドカードを使えるようになってワークスペース名の指定が不要になれば、ノーコードプロビジョニングでも Dynamic Provider Credentials for Azure を使った認証が最適解になりそうです。 今後に期待ですね。
ちなみに、Terraform Cloud には Variable sets という機能あって、組織全体またはプロジェクト/ワークスペース単位に変数群を展開することが可能です。
Variable sets にテナント ID などの接続先情報を変数として登録しておくことで、ノーコードプロビジョニングで作られるワークスペースにも接続先情報をあらかじめ設定できるので利用者が意識する必要がなくなります
ノーコードプロビジョニングを利用する場合は利用者の認知負荷が下がるような構成を考えてみてください。