これはなんですか
- TerraformでAWSクレデンシャル情報を読み込む方法について、簡単にまとめます。
- ドキュメントを読めば全てわかる案件です。
前提
IAMユーザーのクレデンシャル
AWSではIAMユーザーの認証情報として、アクセスキーが使えます。プログラムからAWSのリソースを操作する場合、このアクセスキーを使ってIAMユーザーとしての認証を行います。アクセスキーはアクセスキーIDとシークレットアクセスキーの組です。アクセスキーは一般にクレデンシャルと呼ばれます。
IAMロール
AWSではIAMロールを使った認証も存在します。IAMロールは、IAMユーザーと同様にAWSリソースへのアクセス許可/拒否が設定できます。IAMユーザーと異なるのは、ロールをAWSのリソースにアタッチできる点です。IAMロールがアタッチされたリソースは、ロールの認証情報を利用して他のAWSリソースが操作できるようになります。
また、IAMロールは自らの権限をIAMユーザーに委譲できます。IAMユーザーは委譲された権限でAWSリソースを操作できます。
Terraformでクレデンシャルを設定する
クレデンシャルの設定方法をいくつか挙げます。ほとんどTerraformドキュメントの日本語訳です。
.tf で access_key
属性と secret_key
属性を設定する
直接値を入力する
一番シンプルな方法は、provider "aws" {}
に直接設定する方法です。次のように、 access_key
属性と secret_key
属性にそれぞれ、アクセスキーIDとシークレットアクセスキーを設定します。(この値はAWSドキュメントに書かれている例です。実際のクレデンシャルではありません)
provider "aws" {
region = "ap-northeast-1"
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
変数を使う
アクセスキーをハードコードするのはクレデンシャル漏洩のリスクが高すぎるので、変数を利用して実行時に直接する方法もあります。
variable "access_key" {}
variable "secret_key" {}
provider "aws" {
region = "ap-northeast-1"
access_key = var.access_key
secret_key = var.secret_key
}
上記の設定をした場合、terraform
コマンドの実行時に各変数の値を設定することになります。対話式のインターフェースで入力するか、-var
オプションでコマンド入力時に指定します。
.tfvars
に値を埋め込む
コマンド入力のたびにクレデンシャルを投入するのは面倒です。これを回避する方法として、.tfvars
ファイルを使う方法があります。.tfvars
ファイルはTerraformの変数を設定するためのファイルです。デフォルトでは、terraform.tfvars
、terraform.tfvars.json
、*.auto.tfvars
、*.auto.tfvars.json
が自動的に読み込まれます。provider2.tf ファイル向けに terraform.tfvars
を設定すると、次のようになります。
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
Gitリポジトリでファイルを管理する際も、このように .tfvars
にクレデンシャルを埋め込んで .gitignore
で管理対象から除外することで、リモートリポジトリにクレデンシャルが載ることを防げます。
# terraform.tfvars を除外する
terraform.tfvars
環境変数を使う
以下の環境変数にクレデンシャルが設定されている場合、Terraformはそれを利用してIAMの認証を行います。
provider "aws" { }
$ export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
$ export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
$ export AWS_DEFAULT_REGION="ap-northeast-1"
$ terraform plan
AWS CLI 用に名前付きプロファイルが設定済みの場合は AWS_PROFILE
も利用できます。
$ export AWS_PROFILE="your_project"
$ terraform plan
これら環境変数については、AWS CLIのドキュメントを確認してください。
名前付きプロファイルについては、以下ドキュメントを確認してください。
direnvでディレクトリ単位で環境変数を設定する
上記の方法でクレデンシャル を渡す場合、実行の都度環境変数を設定するのは面倒です。また、異なるAWSアカウントを操作するような状況では、設定間違いの危険もあります。それを解決するツールとして、direnv があります。ディレクトリ内に .envrc
というファイルを置いてdirenvを有効化することで、そのディレクトリ配下では .envrc
内で設定した環境変数が使えるようになります。設定方法についてはここでは省略します。
direnv環境下でGitリポジトリ管理をする場合は注意が必要です。 .envrc
にアクセスキーIDとシークレットアクセスキーを直接設定する場合、.envrc
を .gitignore
で除外しないと、リモートリポジトリ上にクレデンシャルが公開されてしまいます。
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="ap-northeast-1"
この場合は次のように .gitignore
を設定しましょう。
.envrc
より良い方法は、AWS CLIで名前付きプロファイルを設定し、.envrc
では AWS_PROFILE
を指定するという方法です。これであれば最悪 .envrc
を除外し忘れてもクレデンシャルの漏えいにはなりません。
export AWS_PROFILE="your_project"
export AWS_DEFAULT_REGION="ap-northeast-1"
名前付きプロファイルを使う時の注意
AWS CLI での IAM ロールの使用 に書かれているように、AWSではIAMロールのアクセス情報で名前付きプロファイルが設定できます。このプロファイルをTerraformで使う場合は AWS_SDK_LOAD_CONFIG
変数に真値を設定する必要があります。direnvと併用する場合、.envrcは次のようになります。
export AWS_PROFILE="your_project"
export AWS_DEFAULT_REGION="ap-northeast-1"
export AWS_SDK_LOAD_CONFIG=1
AWS_SDK_LOAD_CONFIG
に真を表す値として 1
を設定しました。特別な制限がなければ、direnvでクレデンシャルを設定する場合はこの書き方をすれば良いと思います。
クレデンシャルが書かれたファイルを指定する
AWS CLI では、デフォルトで $HOME/.aws/credentials
にクレデンシャル情報を配置します。Terraformもデフォルトでこのファイルを参照して名前付きプロファイルを認識します。provider "aws" {}
には shared_credentials_file
属性があり、これを使えばAWS CLIのデフォルトとは異なるクレデンシャル情報が読み込めます。
provider "aws" {
region = "ap-northeast-1"
shared_credentials_file = "/Users/tf_user/.aws/creds"
profile = "your_project"
}
ここまで説明した方法には優先順位が設定されています。複数の設定がある場合は次の順で認証が行われます。
-
provider "aws" {}
のaccess_key
属性とsecret_key
属性 - 環境変数
- アクセスキーを指定する方が名前付きプロファイル指定より優先される※要検証
-
provider "aws" {}
のshared_credentials_file
属性
ロールが設定されたEC2インスタンス上で実行する
TerraformをEC2インスタンス内で実行する場合は、インスタンスにアタッチされたIAMロールの認証情報が使われます。この場合、特にアクセスキーや名前付きプロファイルを指定する必要はありません。デプロイ用サーバ (Jenkinsなど?) を利用する場合が当てはまるかと思います。
ECS/CodeBuild で実行する
TBD
https://www.terraform.io/docs/providers/aws/index.html#ecs-and-codebuild-task-roles
AssumeRole する
IAMロールから委譲された権限を使ってTerraformを実行します。
TBD
https://www.terraform.io/docs/providers/aws/index.html#assume-role
https://dev.classmethod.jp/cloud/aws/iam-role-and-assumerole/
https://dev.classmethod.jp/etc/sugano-005-s3/
https://dev.classmethod.jp/cloud/aws/assume-role-deploy-iam-user-and-role/
所感
- ローカルで実行するなら環境変数を使うのが良い。
- CI/CD回すならCodeBuildに設定するのが良さそう。
- 気が向いたら追記する(そもそも未確認......)