Terraformの実行環境をAzure Cloud Shellでbashを用いて準備する手順をまとめました。 できるだけコマンドをそのまま流し込めばセットアップが完了するように調整しております。
設定の方針
TerraformからAzureへのService Principalを介した接続は証明書による認証としています。
Azure Cloud Shellは検証用途で利用していて定期的に環境を破棄する想定とし、消し忘れたService Principalの不正利用を防ぐために証明書の有効期限を90日としています。
検証時に権限周りの制約に悩まされないようにService Principalに割り当てるRoleは
Contributor
にしています。しかしながら権限の強さに比例して悪用時のリスクが高まるので適宜調整してください。
情報源
Microsoftのドキュメント
Terraformの環境構築自体はMicrosoftのドキュメントを参考にしています。 固有情報のような書き換えが必要な個所があったので、できるだけAzure Cloud Shellからコマンドを流し込めばよい状態に調整しております。
Configure Terraform in Azure Cloud Shell with Bash | Microsoft Learn
https://learn.microsoft.com/en-us/azure/developer/terraform/get-started-cloud-shell-bash?tabs=bash
TerraformのAzure Providerのドキュメント
認証情報に関してはTerraformのAzure Providerのドキュメントを参考にして、証明書認証で設定しております。
Azure Provider: Authenticating via a Service Principal and a Client Certificate | Guides | hashicorp/azurerm | Terraform Registry
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_certificate.html
設定方法
Terraformの最新バージョンのダウンロード (任意)
- Azure Cloud Shellで現在インストールされているTerraformのバージョンを確認します。
terraform version
- 筆者が検証時のAzure Cloud ShellではTerraformのバージョンが
v1.3.2
だったので、検証時の最新版をインストールする方針としました。
sysadmin [ ~ ]$ terraform version Terraform v1.3.2 on linux_amd64 Your version of Terraform is out of date! The latest version is 1.5.5. You can update by downloading from https://www.terraform.io/downloads.html sysadmin [ ~ ]$
- Terraformの最新バージョンを自動で判定して取得します。実行ファイルは
~/bin/
に格納しています。
LATEST_URL=$(curl -sL https://releases.hashicorp.com/terraform/index.json | jq -r '.versions[].builds[].url' | grep -E 'terraform_[0-9]\.[0-9]{1,2}\.[0-9]{1,2}_linux.*amd64' | sort -V | tail -n 1) echo ${LATEST_URL} curl -O ${LATEST_URL} ls ~/terraform_*_linux_amd64.zip unzip ~/terraform_*_linux_amd64.zip mkdir ~/bin mv ~/terraform ~/bin/
sysadmin [ ~ ]$ echo ${PATH} ~/.local/bin:~/bin:~/.dotnet/tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/istio-latest/bin:/usr/local/linkerd/bin:/usr/lib/golang/bin:/opt/mssql-tools18/bin:~/bundle/bin:~/bundle/gems/bin sysadmin [ ~ ]$ sysadmin [ ~ ]$ which terraform /home/sysadmin/bin/terraform sysadmin [ ~ ]$ sysadmin [ ~ ]$ terraform version Terraform v1.3.2 on linux_amd64 Your version of Terraform is out of date! The latest version is 1.5.2. You can update by downloading from https://www.terraform.io/downloads.html sysadmin [ ~ ]$
- 新しくShellを開き直して最新のTerraformの実行ファイルが優先されるかを確認します。
exit
terraform version
認証設定
- Terraform向けのService Principalを作成していきます。Service Principal名を変数に格納します。
SP_NAME='sp_terraform'
- Subscriptionの情報が必要になるので予め変数に格納しておきます。
SUBSCRIPTION=/subscriptions/`az account show | jq -r .id` echo ${SUBSCRIPTION}
- 証明書用のパスワードを変数に格納します。
パスワードの複雑性に指定がある場合は適宜修正してください。後の手順でヒアドキュメントを用いてファイルに保存しているので、Shellによって変数展開される$$
や~
の扱いには注意してください。
CERT_PASSWORD=`openssl rand -base64 18` echo ${CERT_PASSWORD}
- Terraform用の証明書を事前作成した上で、Service Principalを作成しています。証明書の有効期間は
openssl
コマンドの-days
オプションで90日としています。
mkdir ~/credentials cd ~/credentials pwd openssl req -subj '/CN=myclientcertificate/O=MyCompany, Inc./ST=CA/C=US' -new -newkey rsa:4096 -sha256 -days 90 -nodes -x509 -keyout ./client.key -out ./client.crt openssl pkcs12 -export -password pass:${CERT_PASSWORD} -out ./client.pfx -inkey ./client.key -in ./client.crt az ad sp create-for-rbac --name ${SP_NAME} --role Contributor --scopes ${SUBSCRIPTION} --cert '@./client.crt'
Terraformのサンプル
動作確認用にResource Groupを作成するTerraformのサンプルを実行します。
事前準備
- Terraformのサンプル ファイルを格納するディレクトリを作成して移動します。
mkdir ~/Sample cd ~/Sample pwd
変数の設定
- TerraformからAzureへ接続する際の認証情報を格納する変数を定義します。
cat > ./variables.tf << EOF variable "subscription_id" { description = "Subscription ID" type = string sensitive = true } variable "tenant_id" { description = "Tenant ID" type = string sensitive = true } variable "client_id" { description = "Client ID" type = string sensitive = true } variable "client_certificate_password" { description = "Client Certificate Password" type = string sensitive = true } EOF
cat ./variables.tf
- 認証情報を格納します。機密情報を扱うファイルとなるため取り扱いに注意してください。
cat > ./secret.tfvars << EOF subscription_id = "`az account show | jq -r .id`" tenant_id = "`az account show --subscription 'Pay-As-You-Go' | jq -r .tenantId`" client_id = "`az ad sp list --display-name ${SP_NAME} | jq -r .[].appId`" client_certificate_password = "${CERT_PASSWORD}" EOF
cat ./secret.tfvars
メインの設定
- Resource Groupを作成するためのサンプルです。
cat > ./main.tf << EOF terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>3.44.1" } } } data "local_file" "client_certificate" { filename = pathexpand("~/credentials/client.pfx") } provider "azurerm" { features {} client_id = var.client_id client_certificate_path = data.local_file.client_certificate.filename client_certificate_password = var.client_certificate_password tenant_id = var.tenant_id subscription_id = var.subscription_id } resource "azurerm_resource_group" "rg-sample" { name = "rg-sample" location = "japaneast" } output "OUTPUT_TEST" { description = "Test Message" value = "Hello, World!" } EOF
cat ./main.tf
Terraformの実行コマンド
- 現在の作業ディレクトリでTerraform環境の初期化処理を行います。
terraform init
- 生成される設定情報を事前に確認します。TerraformからAzureへ接続する際の認証情報が含まれている変数定義ファイルを読み込んでいます。
terraform plan -var-file="./secret.tfvars"
- 実際に実行します。変数定義ファイルの指定を忘れないようにしてください。
terraform apply -var-file="./secret.tfvars"
- 検証作業が終わったら不要なリソースを削除します。検証時にShellを閉じているケースを考慮して、ディレクトリ移動を事前に行うようにしています。変数定義ファイルの指定を忘れないようにしてください。
cd ~/Sample terraform destroy -var-file="./secret.tfvars"
後片付け: Service Principalの設定削除
検証作業を終えてTerraformからAzureへのデプロイ作業も不要になったら、不正アクセスの要因にならないようにService Principalの設定を削除しておきます。
az ad sp create-for-rbac
コマンドを用いてService Principalを作成した際に、Enterprise ApplicationとApp Registrationの設定が作成されているので、2つ分の設定の削除が必要になります。
CLIからの作業だけだと、Enterprise ApplicationとApp Registrationの2つの設定個所を意識しにくいので、Web UIからの作業手順も用意しました。
CLIの手順
- Service Principal名を変数に指定します。
SP_NAME='sp_terraform'
- Enterprise Applicationの設定を削除します。事前と事後で設定が存在しているかの確認をしています。
az ad sp list --display-name ${SP_NAME} az ad sp delete --id `az ad sp list --display-name ${SP_NAME} | jq -r .[].id` az ad sp list --display-name ${SP_NAME}
- App Registrationの設定を削除します。事前と事後で設定が存在しているかの確認をしています。
az ad app list --display-name ${SP_NAME} az ad app delete --id `az ad app list --display-name ${SP_NAME} | jq -r .[].id` az ad app list --display-name ${SP_NAME}
Web UIの手順
Enterprise applicationsの設定の削除
Azure Active Directoryから
Enterprise applications
に移動します。Enterprise applications への移動 Application type == Enterprise Applications
の検索フィルタを削除して、sp_terraform
の設定を探して移動します。Enterprise applicationのTerraform用設定への移動 sp_terraform
のManage
セクションにあるProperties
を開いて、Delete
ボタンから削除します。Enterprise ApplicationのTerraform用設定の削除
App Registrationの設定の削除
Azure Active Directoryから
App Registrations
に移動します。App Registrations への移動 All applications
のタブに切り替えた後にsp_terraform
の設定を探して移動します。App RegistrationのTerraform用設定への移動 Overview
からDelete
ボタンから削除します。App RegistrationのTerraform用設定の削除