LoginSignup
29
18

More than 3 years have passed since last update.

Terraformでクレデンシャルを読み込む方法あれこれ

Last updated at Posted at 2020-04-13

これはなんですか

  • 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ドキュメントに書かれている例です。実際のクレデンシャルではありません)

provider1.tf
provider "aws" {
  region     = "ap-northeast-1"
  access_key = "AKIAIOSFODNN7EXAMPLE"
  secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}

変数を使う

アクセスキーをハードコードするのはクレデンシャル漏洩のリスクが高すぎるので、変数を利用して実行時に直接する方法もあります。

provider2.tf
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.tfvarsterraform.tfvars.json*.auto.tfvars*.auto.tfvars.json が自動的に読み込まれます。provider2.tf ファイル向けに terraform.tfvars を設定すると、次のようになります。

terraform.tfvars
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

Gitリポジトリでファイルを管理する際も、このように .tfvars にクレデンシャルを埋め込んで .gitignore で管理対象から除外することで、リモートリポジトリにクレデンシャルが載ることを防げます。

.gitignore
# terraform.tfvars を除外する
terraform.tfvars

環境変数を使う

以下の環境変数にクレデンシャルが設定されている場合、Terraformはそれを利用してIAMの認証を行います。

provider3.tf
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 で除外しないと、リモートリポジトリ上にクレデンシャルが公開されてしまいます。

.envrc
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="ap-northeast-1"

この場合は次のように .gitignore を設定しましょう。

.gitignore
.envrc

より良い方法は、AWS CLIで名前付きプロファイルを設定し、.envrc では AWS_PROFILE を指定するという方法です。これであれば最悪 .envrc を除外し忘れてもクレデンシャルの漏えいにはなりません。

.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は次のようになります。

.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のデフォルトとは異なるクレデンシャル情報が読み込めます。

provider4.tf
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に設定するのが良さそう。
    • 気が向いたら追記する(そもそも未確認......)
29
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
18