こんにちは、上野です。
今回はGoogle Cloud関連の内容です。みなさまGoogle CloudのリソースをTerraformなどのIaCでデプロイする場合、どのように実行されていますか?
AWSがメイン処理+Google Cloud(BigQueryなど一部)という構成を取ることがあり、AWS側でデプロイ管理もしようとすることも我々の現場では多いです。 Google CloudのリソースをAWSからデプロイする場合、Google Cloud側にサービスアカウント+キーを作成してそれを使用することもあるかと思います。 ただ、この場合永続的なキー情報になるため、この漏えいが心配になります。
Workload Identity 連携を使用すると、永続的なキーを使用せずAWSからアクセスできるとのことなので、今回はそれを試してみます。次のような構成イメージです。
AWS 側のIAM Roleを使用して、Google Cloud側のサービスアカウントにID連携を行います。永続的なキーを使用しないのが嬉しいポイントですね。
やってみる
今回はAWS環境のCloud9(EC2)からTerraformを実行し、Google Cloud上にCloud Storageバケットを作成するサンプルを実行してみます。
こちらの手順に従って実施していきます。わかりやすさ重視で、Console(GUI)中心でやっていきます。
今回は組織に属さないプロジェクト単体の環境で試しています。
前準備
API有効ページからIAM, Resource Manager, Service Account Credentials, and Security Token Service (STS) API を有効にします。
GCP側で使用する、サービスアカウントを作成しておきます。今回はGCSバケットの作成を試すため、Storage Adminの権限を付与して作成しておきます。
AWS側の設定(Cloud9+IAM Role)は、後ほどTerraform実行時の説明に記載します。
Workload Identity設定
新しいワークロード プロバイダとプール ページから、Identity poolの作成と設定をしていきます。
任意のPool IDを設定します。
Provider name、Provider ID、接続するAWS Accout IDを入力します。
provider attributesは今回はデフォルトのまま設定しておきます。
作成したWorkload Identity プールに、アクセス許可を追加していきます。
前準備で作成したバケット作成が可能なサービスアカウントを設定します。 Select members のところは、今回はプール内のすべての IDがアクセスできるように設定しておきます。
認証情報ファイル(json)が取得できるので、ダウンロードしておきます。
認証情報ファイルの内容は以下のとおりで、特にキー情報が含まれていません。
{ "type": "external_account", "audience": "//iam.googleapis.com/projects/[ProjectNumber]/locations/global/workloadIdentityPools/fromaws/providers/awstogcp", "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request", "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/createbucket@[ProjectID].iam.gserviceaccount.com:generateAccessToken", "token_url": "https://sts.googleapis.com/v1/token", "credential_source": { "environment_id": "aws1", "region_url": "http://169.254.169.254/latest/meta-data/placement/availability-zone", "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials", "regional_cred_verification_url": "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15" } }
AWS環境からデプロイ
AWSアカウント上のCloud9から、Google Cloudへデプロイしてみます。
Cloud9にはIAMロールを付与し、cloud9のtemporary credentialは無効にしておきます。
Cloud9に付与するロールはポリシー無し(権限無し)で問題ありませんでした。(NullRoleと命名)
どうやら認証の仕組みとしてIAMロール名を使用しているようで、temporary credentialではロール名が正しく取得できずエラーとなりました。よってAWS側の権限は不要でも、IAMロールを付与する必要があるようです。
次のようなGCSバケットを作成するだけのTerraformコード(gcs.tf)を用意します。
※プロジェクトIDとバケット名は適宜置き換えてください
provider "google" { project = "[プロジェクトID]" } resource "google_storage_bucket" "test" { name = "test-bucket-fu3ak1-20210628" location = "ASIA" }
先ほどGCP側でダウンロードした認証情報ファイル「clientLibraryConfig-awstogcp.json」も、Cloud9上にアップロードしておきます。 次のようなファイル構成にしました。(認証情報ファイルはtfファイルとは別の場所でも大丈夫です)
これで準備完了なのでapplyしていきます。
Google Cloudの認証情報ファイルを環境変数GOOGLE_APPLICATION_CREDENTIALS
に設定します。
TerraformのGoogle Cloud認証方法は、公式ドキュメントにも記載があります。
export GOOGLE_APPLICATION_CREDENTIALS=~/environment/terraform-gcs/clientLibraryConfig-awstogcp.json
あとはtfファイルがあるterraform-gcsフォルダに移動して、terraform apply
を実行するだけです。
次のようにapplyが成功します。
$ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # google_storage_bucket.test will be created + resource "google_storage_bucket" "test" { + bucket_policy_only = (known after apply) + force_destroy = false + id = (known after apply) + location = "ASIA" + name = "test-bucket-fu3ak1-20210628" + project = (known after apply) + self_link = (known after apply) + storage_class = "STANDARD" + uniform_bucket_level_access = (known after apply) + url = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes google_storage_bucket.test: Creating... google_storage_bucket.test: Creation complete after 2s [id=test-bucket-fu3ak1-20210628] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Google Cloud側にも作成できていることが確認できます。
参考までに、他のAWSアカウントからterraform applyを実行すると次のエラーとなります。
許可されたAWSアカウントのみデプロイできることがわかります。
{"error":"unauthorized_client","error_description":"Specified aws account id xxxxxxxxxxxx not found in the configured identity providers."}
検証は以上です。
まとめ
Google Cloudでサービスアカウントキーを発行せずに、外部からTerraformでリソースの作成ができました。 今回は検証用途で特にロール名による制限はしませんでしたが、設定次第では特定のロールにアクセスも限定できそうなので、 本番運用時は検討してみたいと思います。
同じ検討をされている方、参考になれば幸いです!