はじめに
GCPを、AWSからセキュアに操作するWorkload Identityという機能について、以前に何度か記事にしました。
その際、
- 認証情報が記述された構成ファイルを保存して
- 環境変数
GOOGLE_APPLICATION_CREDENTIALS
にファイルパスを記載する
という方法で行っていました。
今回は、"ファイル保存&環境変数"という方法を使わず、コードの中で実現する方法になります。
概要
以下のページにサンプルがありました。
json_config_info = json.loads("<ファイルの中身の文字列>")
# jsonの認証設定を読み込む
credentials = aws.Credentials.from_info(json_config_info)
# スコープを設定
## スコープに設定する内容は以下より
## https://developers.google.com/identity/protocols/oauth2/scopes
scoped_credentials = credentials.with_scopes([''])
# プロジェクト、認証を指定してクライアント作成
client = <任意のGCPサービス>.Client(
project="<対象のGCPプロジェクトID>",
credentials=scoped_credentials
)
またこの方法は、EC2などに限定されます。メタデータURLが異なるためとのことですので、他の環境で実装する方はご注意ください。
参考
やったこと
AWSの準備
- Cloud9を使いました
- アカウントIDをGCP側で設定しますので、要メモ
GCPの準備
IAM Service Account Credentals APIを有効化しておきます。無効のままでも後で有効化するようURLに誘導されます。
以降はCloudShellからやっていきます。
各種変数定義
許可する権限は、最も強いroles/owner
にしています。適宜変更ください。
変数セット直後に、変数の中身をechoしています。
# 先のAWSアカウントIDをセット
AWS_ACCOUND_ID="123456789012" && echo $AWS_ACCOUND_ID
# 以下、適宜変更していく
POOL="hogehoge-pool" && echo $POOL
PROVIDER="hogehoge-aws-provider" && echo $PROVIDER
SERVICE_ACCOUNT="access-from-hogehoge-aws" && echo $SERVICE_ACCOUNT
DESCRIPTION="Access from hogehoge env on AWS with workload identity federation" && echo $DESCRIPTION
BIND_ROLE="roles/owner" && echo $BIND_ROLE
# 以下二つは`gcloud projects list`で確認する
PROJECT_NUMBER="123456789012" && echo $PROJECT_NUMBER
PROJECT_ID="hogehpge-pj" && echo $PROJECT_ID
サービスアカウントの作成
削除用のコマンドも併記しておきます。
gcloud iam service-accounts create $SERVICE_ACCOUNT --description="${DESCRIPTION}"
# 削除時は以下
# gcloud iam service-accounts delete "${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com"
Workload Identity Poolの作成
gcloud iam workload-identity-pools create $POOL --location="global"
# 削除時は以下
# gcloud iam workload-identity-pools delete $POOL --location="global"
Workload Identity Providerの作成
gcloud iam workload-identity-pools providers create-aws $PROVIDER \
--location="global" \
--workload-identity-pool=$POOL \
--account-id=$AWS_ACCOUND_ID
# 削除
# gcloud iam workload-identity-pools providers delete $PROVIDER \
# --location="global" \
# --workload-identity-pool=$POOL
サービスアカウントに権限付与
# 権限の付与
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role=$BIND_ROLE
# 確認
gcloud projects get-iam-policy $PROJECT_ID
# 権限の削除
# gcloud projects remove-iam-policy-binding $PROJECT_ID \
# --member="serviceAccount:${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
# --role=$BIND_ROLE
Workload Identity Poolとサービスアカウントの連携
AWS側に使用を許可する範囲を任意にしています。必要に応じて制限してください。
# 一旦全権限で付与してみる
gcloud iam service-accounts add-iam-policy-binding "${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL}/*"
# 確認
gcloud iam service-accounts get-iam-policy "${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com"
# 削除
# gcloud iam service-accounts remove-iam-policy-binding "${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
# --role="roles/iam.workloadIdentityUser" \
# --member="principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL}/*"
認証構成ファイルの取得
gcloud iam workload-identity-pools create-cred-config \
"projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL}/providers/${PROVIDER}" \
--service-account="${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--aws \
--output-file="config-aws-provider.json"
Pythonで操作(cloud9から)
環境は依然と同様に、virtualenv
で仮想化環境で行いました。
mkdir aws-to-gcp
cd aws-to-gcp
# virtualenv上で環境構築
virtualenv a2genv
source a2genv/bin/activate
(a2genv) $ pip install google-cloud-storage
以前はCloud9のtemporary credentialを無効にして、IAMロールをアタッチしていましたが、今回やったときは特に必要なく実行できました。
このあたりのところは以前の状態もハッキリしないので、試す際はご留意ください。
Pythonスクリプトは以下です。今回はGCSのバケット一覧を取ってくる例です。
from google.cloud import storage
import json
from google.auth import aws
json_config_info = json.loads("""
< 先ほどGCPで作成したファイルの中身をここにコピペ >
""")
credentials = aws.Credentials.from_info(json_config_info)
scoped_credentials = credentials.with_scopes(
['https://www.googleapis.com/auth/devstorage.full_control'])
storage_client = storage.Client(project="<対象のGCPプロジェクトID>",credentials=scoped_credentials)
print(list(storage_client.list_buckets()))
おわりに
今回はWorkload Identity連携の、別方法を記事にしました。
認証情報をコードに直に書いていますが、実際に使う場合はParameter Storeで保存してそこから取得する、という方法がセキュアかと思います。
どなたかのお役に立てれば幸いです。