1. はじめに
AWSとGCP、マルチクラウド間の接続に悩まされたことはありませんか?
もしこのような業務要件を聞かれたときに、最初はAWS側のIAM Userでアクセスキーを発行して、それをGCP側に渡して、GCP側がこのアクセスキーのを使ってAWSのサービスを接続するということを思い浮かびませんか?
もちろんこのやり方ではできるですが、アクセスキーの漏洩リスクがあり、それでセキュリティの低下や、運用上の煩雑に繋がりそうなので、極力アクセスキーを発行しないかわりに、ロールを使うことはクラウドのベストプラクティスになります。
そこで、なんとGCPとAWS間は非常によいお友達であることを発見し、AWSのIAMロールでGCPとキーなし認証できます!
2. 早速ネタバレ
AWS側IAMのウェブアイデンティティで、GCP側のサービスアカウントを指定することできます。それで、GCP→AWSでは、AWSのIAM Roleを使って、STSでGCPへ接続することができます。
3. 構成図
では早速下記の構成図のように、GCP→AWS間で、IAM Role経由でSTS接続を行います!
- IAM側にIAM Roleを発行作成し、GCP側のService Accountと連携します。
- GCP側のService Accountを、Compute Engineと連携します。
- Compute Engineから、AWS Cliコマンドを使って、AWS側のS3を作成します。
4.GCP側構築
上記構成図を元に構築していきます。
-
Compute Engine作成後に、下記のミドルウェア等をCompute Engine内にインストールしておきます。
$ sudo yum install -y python3-pip
$ sudo yum install unzip -y
$ curl -L -o gcp-to-aws.zip https://github.com/cevoaustralia/gcp-sa-to-aws-iam-role/archive/master.zip
$ unzip gcp-to-aws.zip
$ cd gcp-sa-to-aws-iam-role-master/gcp
$ sudo pip3 install -r requirements.txt
上記インストール完了後に、aws --version
コマンドを叩いて、AWS Cliがインストールされたことを確認します。
[xxxxxxxx@instance-1 gcp]$ aws --version
aws-cli/1.24.10 Python/3.6.8 Linux/3.10.0-1160.71.1.el7.x86_64 botocore/1.26.10
上記確認できていればOK。
5. Service Account画面に戻り、上記の作成したService Accountの一意のID
をメモっておきます。
5.AWS側構築
-
IAM
の作成画面に遷移し、ウェブアイデンティティ
を選択の上、アイデンティティプロパイダー
にGoogle
を選択します。Audience
に上記手順のService Accountの一意のID
を入力します。
6.GCP上のCompute Engineでの操作
1.ディレクトリ~gcp-sa-to-aws-iam-role-master/gcp
に遷移していることを確認します。
[xxxxxxxxx@instance-1 gcp]$ pwd
/home/xxxxxxxxxx/gcp-sa-to-aws-iam-role-master/gcp
もしほかのディレクトリ配下にいれば、gcp-sa-to-aws-iam-role-master/gcp
に遷移してください。
2.ll
コマンドを叩いて、get_aws_creds.py
ファイルが存在していることを確認します。
[xxxxxxxxx@instance-1 gcp]$ ll
total 8
-rwxr-xr-x. 1 xxxxxxx xxxxxxx 1400 Mar 30 2021 get_aws_creds.py
-rw-rw-r--. 1 xxxxxxx xxxxxxx 22 Mar 30 2021 requirements.txt
こちらのget_aws_creds.py
ファイル中身を見てみると、AWS側のSTSトークンを取得してきて、それを最終的に~/.aws/credentials
に格納しにいきます。AWS Cliは~/.aws/credentials
に認証情報を取得してアクセスする動作になります。
[xxxxxxxx@instance-1 gcp]$ cat get_aws_creds.py
#!/usr/bin/env python3
#
# This code must run on a VM instance with a service account associated with it.
# The service account must be granted the 'Service Account Token Creator' IAM Role
import os
import sys
from os import path
import requests
import boto3
role = sys.argv[1]
# Set up the URL to request
SERVICE_ACCOUNT = os.getenv("SERVICE_ACCOUNT", "default")
BASE_URL = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/'
AUDIENCE = 'potato'
FORMAT = 'full'
METADATA_HEADERS = { 'Metadata-Flavor': 'Google' }
# Construct a URL with the audience and format
url = BASE_URL + SERVICE_ACCOUNT + "/identity?audience=" + AUDIENCE + "&format=" + FORMAT
# Get the service token
r = requests.get(url, headers=METADATA_HEADERS)
token = r.text
# Turn the token into AWS credentials
sts = boto3.client('sts')
res = sts.assume_role_with_web_identity(
RoleArn=role,
WebIdentityToken=token,
RoleSessionName='example')
creds = res['Credentials']
key = str(creds['AccessKeyId'])
secret = str(creds['SecretAccessKey'])
token = str(creds['SessionToken'])
output = "[default]\naws_access_key_id=%s\naws_secret_access_key=%s\naws_session_token=%s\n" % (key, secret, token)
try:
os.mkdir(path.join(os.getenv('HOME'), '.aws'))
except:
pass
with open(path.join(os.getenv('HOME'), '.aws', 'credentials'), 'w') as fp:
print(output, file=fp)
出典:https://github.com/cevoaustralia/gcp-sa-to-aws-iam-role
※最初は自分でスクリプトを書こうと思ったら、すでにGithub上で私が書いたスクリプトより良さそうなものがあったので、それで今回そちらを使うことになりました。
なお、当スクリプトは一点不足しており、AWSリージョン情報を定義しておらず、興味のある方は~/.aws/config
にリージョンを定義してください。
3.pythonシェルを実行
下記のように実行します。上記手順内でメモっていたARN
を後ろに代入してください。
[xxxxxxxxx@instance-1 gcp]$ ./get_aws_creds.py arn:aws:iam::xxxxxxxxxxxx:role/aws-allow-gcp-access
上記実行後、aws sts get-caller-identity
コマンドを叩くと、Assumeロールベース認証が確認できています。
[xxxxxxxxxx@instance-1 gcp]$ aws sts get-caller-identity
{
"UserId": "xxxxxxxxxxxxxx:example",
"Account": "xxxxxxxxxx",
"Arn": "arn:aws:sts::xxxxxxxxxx:assumed-role/aws-allow-gcp-access/example"
}
さらに、~/.aws/credentials
認証情報をみると、STSトークンが発行されていることを確認できます。
[xxxxxxxxxxx@instance-1 gcp]$ cat ~/.aws/credentials
[default]
aws_access_key_id=ASIAXXXXXXXXXX6LNI6UI
aws_secret_access_key=nVW2D1J11+XXXXXXXXXXXXxeDIfSk2LTUgvbJ8U
aws_session_token=FwoGZXIvYXdzEA8aDCE1V5NUr2Ee6xDvJiLQAVeNoH8gU2vUxmRL7UNM8xvYvYsfuCg5bPgYQal1E/AM/7wNr9rzrzqV2j7lJ5BVY4mhqn0IuZ5jg5+ST208xyzHc/GK2yo+ZiismMYalF47tfCfERgC/7kh61+u0LaEhohfSLciwF0R59VZHZiQyy00saNPY9zQa8JLjdg4shpxL+xSY12dysEmXDJMKMAZYcIMLvZIf0pJ5JoKPnvc6BPgNU+nTB6MLHOU+g+a3A8f2TxmLP7CP4R4KiWoyWFJc7I0wSLNKiQrOKwogr+xikgol4eOmAYyWK6QH+VxXXXXXXXXXXXXXXXXXXXx4x6cLuOecFFBgnEY1e2H0Jqq5uWaJjjoKuwH8VRhIaw5yuAqnra+2flOwwMYwyugHc1w9ama+qJgP97EJC2MwmgK5I=
STSトークンであるため、下記のコマンドをもう一回叩くと、STSトークンが新しく発行されることを確認できますよ〜
[xxxxxxxxx@instance-1 gcp]$ ./get_aws_creds.py arn:aws:iam::xxxxxxxxxxxx:role/aws-allow-gcp-access
[xxxxxxxxx@instance-1 gcp]$ cat ~/.aws/credentials
[default]
aws_access_key_id=ASIAXXXXXXXXXXXXUTGNA
aws_secret_access_key=iOPfLGkRQrzFM4BXXXXXXXXXXXXxO2piRHHwpCwUX
aws_session_token=FwoGZXIvYXdzEA8aDP4YPD/LaisLZnoufiLQARoaMPZx7u4I46VtKIW0zk67iVteo61FAmSwMhSR53wtuMB3wNwev6PL4sz7bpMotuXv0ZlLx49OSX5TV3xApcIr+JbJim8KyA7sM+zx16lehlTi1bBlTIFYnYh46a4PqcOyCBBtYD/qNRoydTJOR/cHBb5Lv3pGbu6TUNVJoqEdtRx/ERVtcddLS3O6F3ejiVmRt3QNreog2hJSDOZTdmJq53kO5IbxjW8gH2aNsK/JxNbsXD/yregYnspCTNHi7EyBHkpOLiFPWEMW9ib1SIEo+I+OmAYyWAfKVxXXXXXXXXXXXXXXXXXXXx4rYGYshuellrsC4puSmw3VFonPc06E3Oz0VvtaB+Bnk9rejj7cFmt6dRyXXd6sLbW485EPzGHrTibHUek9+6mjAFYk=
7. S3を作成してみます
AWSのIAM RoleにS3FullAccessの権限を付与したため、S3を作成することができると予想されます。
[xxxxxxxxx@instance-1 gcp]$ aws s3 mb s3://sdfhskgshkdfhkw48XXXX
make_bucket: sdfhskgshkdfhkw48XXXX
[xxxxxxxxx@instance-1 gcp]$ aws s3 ls
2022-08-22 13:45:56 sdfhskgshkdfhkw48XXXX
上記のように、S3が作られたことを確認できました。
8. STSトークンのセッション時間について
デフォルトは一時間になっていますが、AWS側のIAMロールのところで、セッション時間を最大12時間まで指定することができます。
9. AWSとGCP間の通信
もしAWSとGCP間のパブリック通信を懸念している方がいたら、GCPとAWS間に専用線とかのルーティングを設定して、AWSのSTS用VPC Endpointsにルーティングできれば良いです。
10. 参考資料
1.キーなしの API 認証 - サービス アカウント キーを必要としない Workload Identity 連携によるクラウド セキュリティの向上
2.AWS IAM Role を GCP から STS 認証で利用する設定例
3.GCP Service Account を AWS から STS 認証で利用する設定例
4.gcp-sa-to-aws-iam-role