🔑

Terraformでマルチクラウド環境の認証情報をひとつにまとめる

2024/03/17に公開

概要

  • AWS + GCP の両方のリソースを作成する Terraform テンプレートを実行する際、「AWS Secrets Manager に GCP の認証情報を保存しておく」ことで、Terraform の実行に必要な認証情報を AWS の認証情報に一本化できます。
  • 同様に、「GCP の Secret Manager に AWS の認証情報を保存しておく」ことで、Terraform の実行に必要な認証情報を GCP の認証情報に一本化することができます。
  • Terraform をローカル環境で実行する運用の場合や、オンプレミス環境の CI/CD 環境から実行する場合などに認証情報を一本化できるので便利です。
  • 一般的には「terraform provider のパラメーターに他のリソースの属性を指定できる」という話なので、AWS + GCP の連携に限らず、 databricks provider の認証情報を AWS Secrets Manager に保存しておく、docker provider 利用時に aws_ecr_authorization_token で取得した認証情報を使用して ECR リポジトリにプッシュする、みたいなこともできます。

背景

  • ひとつのプロジェクトで AWS と GCP の両方を扱うことになる場合はしばしばあります。
  • Terraformで構成管理をしようとすると、AWS のためと GCP のためとそれぞれの認証情報が必要になります。
  • AWS、GCP ともに、 AWS Secrets ManagerSecret Manager (GCP) という、アプリケーション用にパスワード類を保存しておくサービスがあるので、これをうまく使ってどっちかに認証情報をまとめられないかなあ…という話。

複数の認証情報が必要で面倒くさいの図

AWS Secrets Manager に GCP の認証情報を保存しておく

AWS Secrets Manager に、Google のサービスアカウントの認証キーを保存しておきます。
Terraform 実行時には AWS の認証情報だけを指定し、Terraform 自身で AWS Secrets Manager から Google の認証情報を実行して GCP にアクセスさせます。

実行時にはAWSの認証情報だけで済ませるの図

https://github.com/ikedam/zenn_snippets/blob/multicloud_terraform_aws/

provider "aws" {
}

# AWS Secrets ManagerからGCPの認証情報(サービスアカウントのJSONキー)を取得する。
data "aws_secretsmanager_secret_version" "gcp_key" {
  secret_id = "terraform-gcp-key"
}

provider "google" {
  # AWS Secrets Managerから取得した認証情報で認証する。
  credentials = data.aws_secretsmanager_secret_version.gcp_key.secret_string
}

GCP の Secret Manager に AWS の認証情報を保存しておく

GCP の Secret Manager に、AWS の IAM ユーザーのアクセスキーIDとシークレットアクセスキーを保存しておきます。
Terraform 実行時には GCP の認証情報だけを指定し、Terraform 自身で Secret Manager から AWS の認証情報を実行して AWS にアクセスさせます。

実行時にはGCPの認証情報だけで済ませるの図

https://github.com/ikedam/zenn_snippets/blob/multicloud_terraform_gcp/

provider "google" {
}

# GCPのSecret ManagerからAWSの認証情報を取得する。
# ここでは アクセスキーID:シークレットアクセスキー のフォーマットで入れている。
data "google_secret_manager_secret_version" "aws_key" {
  secret = "terraform-aws-key"
}

provider "aws" {
  # GCPのSecret Managerから取得した認証情報でアクセスする。
  access_key = split(":", data.google_secret_manager_secret_version.aws_key.secret_data)[0]
  secret_key = split(":", data.google_secret_manager_secret_version.aws_key.secret_data)[1]
}

注意事項など

Terraformから取得した認証情報はデータソースの属性として state ファイル (terraform.tfstate) に保存されます:

  • AWS Secret Manager に Google のサービスアカウントの認証情報を保存したケース

    {
        ...
        {
          "mode": "data",
          "type": "aws_secretsmanager_secret_version",
          "name": "gcp_key",
          "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
          "instances": [
            {
              "schema_version": 0,
              "attributes": {
                "arn": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:terraform-gcp-key-xxxxxx",
                "created_date": "2024-03-16T12:43:54Z",
                "id": "terraform-gcp-key|AWSCURRENT",
                "secret_binary": "",
                "secret_id": "terraform-gcp-key",
                "secret_string": "{ここにサービスアカウントの認証キーのJSONががっつりはいる}\n",
                "version_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
                "version_stage": "AWSCURRENT",
                "version_stages": [
                  "AWSCURRENT"
                ]
              },
              "sensitive_attributes": []
            }
          ]
        },
        ...
    }
    
  • GCP の Secret Manager に AWS の IAM ユーザーの認証情報を保存したケース

    {
        ...
        {
          "mode": "data",
          "type": "google_secret_manager_secret_version",
          "name": "aws_key",
          "provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
          "instances": [
            {
              "schema_version": 0,
              "attributes": {
                "create_time": "2024-03-16T12:25:20.883484Z",
                "destroy_time": null,
                "enabled": true,
                "id": "projects/xxxxxxxxxxxx/secrets/terraform-aws-key/versions/1",
                "name": "projects/xxxxxxxxxxxx/secrets/terraform-aws-key/versions/1",
                "project": "xxxxxxxx",
                "secret": "terraform-aws-key",
                "secret_data": "アクセスキーID:シークレットアクセスキー",
                "version": "1"
              },
              "sensitive_attributes": []
            }
          ]
        }
        ...
    }
    

このため state ファイルは S3 や GCS などリモートに保存するようにして、適切な権限のあるユーザーだけがアクセスできるようにしてください。

Discussion