Cloud Functions(Google Cloud)でAWS SDKを実行する
はじめに
先日、Cloud Functionsを使ったツールを作成する機会があり、その際に得られた知見をまとめてみました。(Google Cloud初心者向けの内容です。)
はじめに、それぞれのサービスやツールを簡単に説明します。
Cloud Functionsとは
- イベント駆動なサーバレスプラットフォームです。
- Function as a Service(FaaS)として、Google Cloudの中ではポピュラーなサービスです。
- AWSで言うところのLambdaに相当します。
- 本記事内にあるようにデプロイさえできれば、あとはエンドポイントを指定して実行できます。
Secret Managerとは
- 安全に機密情報を管理することができる、Google Cloudの1サービスです。
- Cloud IAMによって明示的にアクセスを管理することができます。
- AWSにもAWS Secrets Managerと言うサービスが有り、類似した機能が提供されています。
AWS SDK for Python (Boto3)とは
- Python向けのAWS SDKです。
- AWSリソースを手軽に操作することができます。
- Boto3の入門には以下の記事もおすすめです。
やりたいこと
本記事ではCloud Functionsのサンプルとして、ハイブリッドクラウドなユースケースを考えます。
具体的には、Cloud FunctionsからSecret Manager経由でAWSの認証情報を取得して、Boto3により最終的になんらかのAWSサービスに関連した処理を実行します。
事前準備
gcloudコマンドのインストール
あらかじめCloud SDK(gcloudコマンド)を用意しておきます。
以下のページの手順に従って下さい。
念のため正常にインストールされたかを確認しておきます。
$ gcloud version | head -n 1
Google Cloud SDK 354.0.0
APIの有効化
また、Google Cloudを各サービスを利用するにはコンソール画面から各サービスのAPIを有効化しておく必要があります。
もしそのプロジェクトで初めてGoogle Cloudのサービス使うのであれば、本記事で使用する以下の2つのAPIを有効化して下さい。それぞれコンソール画面から該当のサービスを開いてワンクリックで済みます。
- Cloud Functions API
- Secret Manager API
さらに、Cloud Functionsは暗黙的にCloud StorageとCloud Buildを利用しているようなので、その2つも有効化を求められる場合があります。ご注意下さい。
- Cloud Storage API
- Cloud Build API
やってみた in Python
サンプルコード
from google.cloud import secretmanager
import boto3
import os
def main(request):
aws_access_key_id = get_secret('sec_aws_access_key_id')
aws_secret_access_key = get_secret('sec_aws_secret_access_key')
request_json = request.get_json()
target_environment = request_json['environment']
return(aws_action(
aws_access_key_id,
aws_secret_access_key,
target_environment,
))
def get_secret(secret_name):
'''
Secret Managerから最新の情報を取得する
'''
client = secretmanager.SecretManagerServiceClient()
gcp_project_id = os.environ.get('GCP_PROJECT', 'GCP Project ID')
name = f"projects/{gcp_project_id}/secrets/{secret_name}/versions/{'latest'}"
response = client.access_secret_version(request={"name": name})
return(response.payload.data.decode('UTF-8'))
def aws_action(access_key_id, secret_access_key, env):
'''
認証情報を使用してAWSのfoo-barサービスを使った何らかの処理を実行する
'''
client = boto3.client('foo-bar',
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
region_name='ap-northeast-1')
# ... snip ...
# ここにBoto3で実行したい処理を記述します。
# ... snip ...
return
if __name__ == '__main__':
main()
google-cloud-secret-manager
boto3
解説
main関数
- 予めコンソール等で
sec_aws_access_key_id
、sec_aws_secret_access_key
の2つをSecretに登録しておく必要があります。 - リクエストのボディからJSON形式で情報を取り出し、
environment
パラメータを利用しています。この記事の本筋ではありませんが、便利なハックなので紹介の意味で書きました。(動作テストを行う目的であれば不要です。)
get_secret関数
- 上記のようにすると
gcp_project_id
は、環境変数から読み取ることも可能です。取得可能な予約済みの環境変数についてはこちらのリストが参考になります。 - Secretのバージョンは基本的には最新のみを取得したいため、明示的に最新バージョンのエイリアス
latest
を指定しています。
Cloud Functionsデプロイ
gcloud
コマンドを利用して、ローカル環境から以下のようにデプロイできます。
関数名はdeploy
サブコマンドの後に続けて指定します。(ここではCloudFunctions-To-AWS
)
#!/bin/bash
SERVICE_ACCOUNT="foo@bar.gserviceaccount.com"
gcloud functions deploy CloudFunctions-To-AWS \
--region=asia-northeast1 \
--source=./cloud-functions \
--service-account=${SERVICE_ACCOUNT} \
--entry-point=main \
--runtime=python37 \
--security-level=secure-always \
--trigger-http
解説
- サービスアカウントは予め用意したものを設定する必要があります(後述)
-
--source
にはpythonコードのディレクトリを指定します。 -
--entry-point
はkickするPythonコードの関数名です。 -
--security-level
にはsecure-always
を指定しており、HTTPSを必須としています。 - デプロイに際してのデバッグでは
--verbosity=debug
を追加する方法が便利です。
補足
Cloud Functionsをデプロイする際、初回のデプロイでは以下のメッセージが表示されます。
Allow unauthenticated invocations of new function [CloudFunctions-To-AWS]?
(y/N)?
多くの場合では認証を求める設定としたいと思いますので、その場合には必ずN
を選択します。
おわりに
最後まで読んでいただき、ありがとうございます。
実際に上記のサンプルを動かすにはサービスアカウントの適切な設定が必要となりますが、それについてはやや煩雑なため、別途記事を書きました。
SecretManagerにアクセスできるサービスアカウントを設定する - Zenn
しかし、サービスアカウントの設定を除いた本記事の内容だけであれば「思ったよりもシンプルに実装できそう」と感じて頂けたのでは無いでしょうか。
どなたかに届けば幸いです。
参考文献
Discussion