Workload Identity でAWS EC2からGCPのリソースへアクセスする 


## これは何?
AWS → Google Cloud へのリソースにアクセスするため、以下のリンクの通りに環境を構築し、EC2(AWS) → Cloud Storage(GCP)へアクセスできるかを検証してみました。

https://blog.g-gen.co.jp/entry/using-workload-identity-federation-with-aws

検証してみた結果、以下のように認証エラーとなりました。

```bash
$ gcloud storage ls
ERROR: (gcloud.storage.ls) There was a problem refreshing your current auth tokens: ('Unable to retrieve AWS region', '<?xml version="1.0" encoding="iso-8859-1"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\n\t"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n <head>\n  <title>401 - Unauthorized</title>\n </head>\n <body>\n  <h1>401 - Unauthorized</h1>\n </body>\n</html>\n')
```

```bash
$ gcloud storage ls
ERROR: (gcloud.storage.ls) There was a problem refreshing your current auth tokens: ('Error code invalid_grant: Received invalid AWS response of type SignatureDoesNotMatch with error message: Credential should be scoped to a valid region. ', '{"error":"invalid_grant","error_description":"Received invalid AWS response of type SignatureDoesNotMatch with error message: Credential should be scoped to a valid region. "}')
Please run:
```

原因としてはGoogle Cloud のサービスアカウントを借用するための認証用トークンの生成をインスタンスメタデータから生成するのですが、EC2のメタデータが[IMDSv2](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)であったため、Workload Identity のAWSプロバイダーでIMDSv2を有効にする必要があります。(IMDSv1に一時的に戻したら成功)

今回は、IMDSv2を有効化した状態で、GoogleCloudのリソースにアクセスする方法を解説します。

## 対処方法
Workload Identity のAWSプロバイダーでIMDSv2用の認証情報の構成ファイルを作成するひつようがあります。

https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds?hl=ja

`gcloud iam workload-identity-pools create-cred-config`コマンドで、作成済みのAWSプロバイダーに対してIMDSv2用の構成ファイルを作成することができます。

```bash
gcloud iam workload-identity-pools create-cred-config \
    projects/「プロジェクトナンバー」/locations/global/workloadIdentityPools/「Workload Identity IDプール」/providers/「Workload Identity プロバイダー」 \
    --service-account=「サービスアカウントEメールアドレス」 \
    --aws \
    --enable-imdsv2 \
    --output-file=output.json
    
```

また、Terraform で実施するには、local-execで`gcloud iam workload-identity-pools create-cred-config ..`コマンドを実行するようにします。

```hcl:workload_identity.tf
// サービスアカウント
resource "google_service_account" "service_account" {
  account_id   = var.gcp_account_id
  display_name = var.desplay_name
  description  = var.description
}

// サービスアカウント ロール
resource "google_project_iam_member" "role" {
  for_each = toset(var.sa_roles)

  role    = each.value # "roles/storage.admin" etc ..
  project = var.gcp_pj_id
  member  = "serviceAccount:${google_service_account.service_account.email}"
}


// Workload Identity ユーザープール
resource "google_iam_workload_identity_pool" "aws" {
  project                   = var.gcp_pj_id
  workload_identity_pool_id = "aws-id-pool"
  display_name              = "aws-id-pool"
  description               = "ID Pool for AWS"
}

// Workload Identity ユーザープール プロバイダー
resource "google_iam_workload_identity_pool_provider" "aws" {
  workload_identity_pool_id          = google_iam_workload_identity_pool.aws.workload_identity_pool_id
  workload_identity_pool_provider_id = "aws-provider"
  display_name                       = "aws-provider"
  description                        = "Provider for AWS"
  aws {
    account_id = var.aws_account_id
  }
}
// 認証情報ファイル生成 (INDSv2)
resource "null_resource" "imdsv2" {
  provisioner "local-exec" {
    command = "gcloud iam workload-identity-pools create-cred-config ${google_iam_workload_identity_pool_provider.aws.id} --service-account=${google_service_account.service_account.email} --aws --enable-imdsv2 --output-file=output_credential.json"
  }
  depends_on = [google_iam_workload_identity_pool_provider.aws]
}

# サービスアカウント 借用
resource "google_service_account_iam_binding" "aws_sa_role_binging" {
  service_account_id = var.service_account_name
  role               = "roles/iam.workloadIdentityUser"

  members = [
    "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.aws.id}/*"
  ]
}
```

上記のように実施することで、作成済みのAWSプロバイダーに対してIMDSv2用の構成ファイルを作成することができました。