Terraform CloudからAWSリソースの操作をOIDC認証(Dynamic Provider Credentials)で
こんにちは!営業製作所でプロダクトエンジニアをやっている西村( @nishim )です。
弊社ではTerraformを使い、主にAWSリソースを管理しています。また、エンジニアが増えてきたタイミングでTerraform Cloudを導入しstate管理や実行環境の一元化をしました。
Terraform Cloud導入時にアクセスキー・シークレットでの認証ではなくOIDC(Dynamic Provider Credentials)での認証を行うようにする&OIDCに必要なリソースもTerraformで作れるようにしたので、ここではどうやったのかについて書いていきます。
そもそも何でアクセスキー・シークレットでの認証ではなくOIDCでの認証にするのか?
アクセスキーやシークレットは固定の文字列なので、定期的にローテーションを行うとしても常に漏洩・不正利用の可能性があります。ローテーションも運用コストが発生したり、そもそもその作業がミスの可能性を孕んでいます。
一方でOIDCでの認証後に得られるトークンは短命(デフォルト60分)であり、継続的に不正使用することが難しくなっています。また、一度設定してしまえばその後はキーローテーションも不要です。
比較するとOIDC認証の方が安全なためセキュリティインシデントの対応コストを下げられ、キーの管理やローテーションも不要になるため運用コストも下げられます。
前提
Terraform Cloudの利用が前提になります。
実装したTerraformのコード
tfc-oidcモジュール
main.tf
このモジュールでは3つのAWSリソースを作成します。
- ホスト名が
app.terraform.io
なIDプロバイダ(aws_iam_openid_connect_provider) - OIDCでAWSから認証された後にassume roleされるIAMロール。ここでの主な引数は次の2つ
-
assume_role_policy
: どのような条件を満たせばこのロールを引き受けられるか -
managed_policy_arns
: IAMロールが持つ権限を指定するポリシーのARNのリスト
-
- IAMロールが持つ権限を定義するIAMポリシー
- 許可するアクションはモジュール呼び出し時にvariable
allow_aws_actions
で指定- なるべく権限を絞れるように
- 許可するアクションはモジュール呼び出し時にvariable
terraform {
required_version = "~> 1.7.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.34.0"
}
tls = {
source = "hashicorp/tls"
version = "~> 4.0.5"
}
}
}
data "tls_certificate" "tfc" {
url = "https://${var.tfc_hostname}"
}
resource "aws_iam_openid_connect_provider" "tfc" {
url = data.tls_certificate.tfc.url
client_id_list = ["aws.workload.identity"]
thumbprint_list = [data.tls_certificate.tfc.certificates[0].sha1_fingerprint]
}
resource "aws_iam_role" "tfc_role" {
name = "tfc_role"
description = "IAM Role for Terraform Cloud"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = aws_iam_openid_connect_provider.tfc.arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"${var.tfc_hostname}:aud" : one(aws_iam_openid_connect_provider.tfc.client_id_list)
}
StringLike = {
"${var.tfc_hostname}:sub" = "organization:${var.tfc_organization}:project:${var.tfc_project}:workspace:${var.tfc_workspace}:run_phase:*"
}
}
}
]
})
managed_policy_arns = [
aws_iam_policy.tfc_policy.arn,
]
}
resource "aws_iam_policy" "tfc_policy" {
name = "tfc_policy"
description = "IAM Policy for Terraform Cloud"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = var.allow_aws_actions
Resource : "*"
}
]
})
}
variables.tf
variable "tfc_hostname" {
description = "Terraform Cloudのホスト名"
type = string
}
variable "tfc_organization" {
description = "Terraform Cloudの組織名"
type = string
}
variable "tfc_project" {
description = "Terraform Cloudのプロジェクト名"
type = string
}
variable "tfc_workspace" {
description = "Terraform Cloudのワークスペース名"
type = string
}
variable "allow_aws_actions" {
description = "許可するアクション"
type = list(string)
default = []
}
outputs.tf
呼び出し元で、IAMロールのARNが確認・利用できるようにoutput
を定義します。
output "iam_role_for_terraform_cloud" {
value = {
name = aws_iam_role.tfc_role.name
arn = aws_iam_role.tfc_role.arn
}
}
モジュール利用箇所
Terraform Cloudに関する引数と、Terraformで作成・管理したいリソースに対する許可アクションを指定してモジュールを利用します。
module "tfc_oidc" {
source = "../../modules/tfc-oidc"
tfc_hostname = "app.terraform.io" # TFC
tfc_organization = "hoge-corp" # 実態に合わせて変更
tfc_project = "hoge-product" # 実態に合わせて変更
tfc_workspace = "hoge-product-production" # 実態に合わせて変更
# 必要最低限にする
allow_aws_actions = [
"acm:*",
"cloudfront:*",
"ec2:*",
"ecr:*",
"ecs:*",
"elasticloadbalancing:*",
"iam:*",
"lambda:*",
"logs:*",
"rds:*",
"route53:*",
"s3:*",
"ssm:*"
]
}
使い方
事前準備
コードを書いただけの状態だとIDプロバイダやIAMロール、IAMポリシーが存在しないので、まだOIDC認証は行えません。
最初はAWSプロバイダーをアクセスキー、シークレットで利用できるようにした上でterraform plan
、terraform apply
を行いリソースを作ります。
applyが成功し3リソースが作成できたら、
- アクセスキーやシークレットは不要になるので、削除や失効処理を行います。
- AWSプロバイダーの設定からもアクセスキーやシークレットを利用する記述を削除します。
Terraform Cloudの設定
Terraform Cloudでは、最低2つの環境変数(Terraform variable
ではなくEnvironment variable
!)を設定する必要があります。
-
TFC_AWS_PROVIDER_AUTH
:true
固定 -
TFC_AWS_RUN_ROLE_ARN
: モジュールが作成したIAMロールのARN
その他のオプションについてはTerraform Cloudの公式ドキュメントが詳しいです。
Terraform Cloudでterraform plan / terraform apply
ここまでくるとTerraform Cloudでterraform plan
やterraform apply
がOIDC認証でできるようになっているはずです🎉
まとめ
OIDCでの認証に切り替えた結果、前述のこのメリットが得られている、または得られる予定です。
比較するとOIDC認証の方が安全なためセキュリティインシデントの対応コストを下げられ、キーの管理やローテーションも不要になるため運用コストも下げられます。
そんなに手間もかからずメリットを享受できるのでおすすめです!
それでは良いTerraform Lifeを🙌
Discussion