TL;DR
Terraformは、IaC(Infrastructure as Code)を実現するためのオープンソースツールであり、インフラストラクチャの構築、変更、バージョン管理をコードで行うことができます。
自作のインフラの内容を提供する場合、Terraform Providerを作成することで、Terraformのエコシステムに統合できます。この記事では、Terraform Providerの基本的な構造と作成手順について説明します。
作成したコードはこちらです。
動作確認済ですが、認証認可周りが緩かったりテストがなかったりするので、
参考程度にお願いします。
はじめに
TerraformはHashiCorpによって開発されたIaCツールであり、宣言的な設定ファイルを使用してインフラストラクチャを管理します。
Terraform Providerは、特定のサービスやプラットフォームとTerraformを連携させるためのプラグインです。これにより、ユーザーはTerraformを使用して様々なリソースを管理できます。
Terraform Providerの基本構造
Terraform ProviderはPublic RegistryとPrivate Registryの両方でホストできます。
- Public: Publish to the Terraform registry | Terraform | HashiCorp Developer
- Private: Private registry in HCP Terraform | Terraform | HashiCorp Developer
ローカル環境でProviderを作ってみる
今回はPrivateのRegistryをローカル環境で構築し、Providerを作成して、実際に動作させてみます。
Terraform Providerの仕組み
Providerとは
Terraform Providerは、Terraformと特定のサービス・プラットフォームを橋渡しするプラグインです。
Terraformのコア部分は抽象的なリソース管理のみを担当し、実際のAPI呼び出しやリソース操作はProviderが担当します。
Terraform Architecture Overview — Structure and Workflow | by Pradeep Raj | Medium
┌──────────────┐
│ Terraform │ ← 抽象的なリソース管理
│ Core │ (plan, apply, state管理)
└──────┬───────┘
│ gRPC/Plugin Protocol
▼
┌──────────────┐
│ Provider │ ← 具体的なAPI実装
│ (Plugin) │ (AWS, Azure, GCP等)
└──────┬───────┘
│ HTTP/API
▼
┌──────────────┐
│ Service │
│ API │
└──────────────┘
Plugin Protocol
TerraformとProviderはgRPCベースのPlugin Protocolで通信します。Terraform起動時に:
- Providerプロセスを子プロセスとして起動
- gRPC経由でスキーマ情報を取得
- CRUD操作のリクエストを送信
- Providerが実際のAPI呼び出しを実行
Providerの開発者は以下を利用することで、こちらを意識せずに開発ができます。
Private Registryの仕組み
Registry Protocolの概要
Terraform RegistryはProviderのバージョン管理とダウンロードを提供するHTTP APIです。
公式資料に従うことで、独自のPrivate Registryを構築できます。
- Provider registry protocol reference | Terraform | HashiCorp Developer
- Remote service discovery protocol reference | Terraform | HashiCorp Developer
主要なエンドポイント
1. Service Discovery
GET /.well-known/terraform.json
レジストリが提供するサービスのエンドポイントを返します。
公式資料:https://developer.hashicorp.com/terraform/internals/remote-service-discovery#discovery-process
2. Provider Versions
GET /v1/providers/{namespace}/{type}/versions
利用可能なProviderのバージョンリストを返します。
公式資料:https://developer.hashicorp.com/terraform/internals/provider-registry-protocol#list-available-versions
3. Download Metadata
GET /v1/providers/{namespace}/{type}/{version}/download/{os}/{arch}
バイナリのダウンロードURL、SHA256ハッシュ、GPG署名情報を返します。
公式資料:https://developer.hashicorp.com/terraform/internals/provider-registry-protocol#find-a-provider-package
4. Binary Download
実際のProviderバイナリ(ZIP形式)をダウンロード。
署名と検証
セキュリティのため、ProviderバイナリはGPG署名を使用して検証される必要があります(ローカルでも同様)。
- SHA256SUMSファイル作成(バイナリのハッシュ)
- GPG秘密鍵で署名(SHA256SUMS.sig作成)
- Registry経由で公開鍵を配布
- Terraform実行時に署名を検証
認証の2つのレイヤー
Terraform環境では2種類の独立した認証が存在します。これらは目的と設定方法が異なります。
Layer 1: Registry認証
目的: Providerバイナリをダウンロードする際の認証
設定場所: .terraformrc
credentials "registry.example.com" {
token = "registry-access-token"
}
タイミング: terraform init 実行時
公式資料:
- https://developer.hashicorp.com/terraform/cli/config/config-file#credentials-1
- https://developer.hashicorp.com/terraform/enterprise/api-docs/private-registry/modules#sample-registry-request-private-module
通信: HTTPヘッダー Authorization: Bearer <token>
Layer 2: Provider認証
目的: 実際のリソース操作を行う際の認証
設定場所: Provider blockまたは環境変数
provider "aws" {
access_key = "***"
secret_key = "***"
}
または環境変数:
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
通信: ProviderがAPI固有の認証方式を使用
タイミング: terraform plan/apply 実行時
Providerの実装
基本構造
Plugin Development - Schemas | Terraform | HashiCorp Developer
リソースの実装
各リソースはCRUD操作を実装します
開発からデプロイまでの流れ
- Provider実装 - SDK使用してCRUD操作を実装
- ビルド - プラットフォーム別バイナリをビルド
- 署名 - GPGで署名してSHA256SUMSを作成
- Registry配置 - Private Registryにアップロード
- 利用 -
.terraformrcで認証設定し、terraform init
実装例
上記の内容を踏まえて、実際にローカル環境で動作するProvider + Private Registryを実装しました。
make cleanとmake devで基本的な動作確認はできると思います。
ローカル環境でhttps通信をする必要があるためmkcertを利用しています。
ただ、上記についてProviderの内容をRegistryへ反映させる認証認可は何も実装していません。
本番へ導入する際は、適切な認証認可を実装してください。
また、一部コードは非常に簡素な認証認可になっているため、あくまで参考実装としてご覧ください。
おわりに
Terraform Providerの作成は、IaCのエコシステムを拡張し、独自のインフラストラクチャをコードで管理する強力な方法です。
この記事では、Providerの基本構造と作成手順について説明しました。ぜひ、自分のプロジェクトに適用してみてください。