1. 概要
この Codelab では、Python での Secret Manager の使用に焦点を当てます。
Secret Manager を使用すると、シークレットをバイナリ blob またはテキスト文字列として保存、管理し、シークレットにアクセスできます。適切な権限があれば、シークレットの内容を表示できます。
Secret Manager は、実行時にアプリケーションが必要とするデータベース パスワード、API キー、TLS 証明書などの構成情報を保存するのに適しています。
学習内容
- Cloud Shell の使い方
- Python 用 Secret Manager クライアント ライブラリをインストールする方法
- Python クライアント ライブラリを使用してシークレットを作成し、アクセスする方法
- Python クライアント ライブラリを使用して Cloud Functions のシークレットにアクセスする方法
必要なもの
アンケート
このチュートリアルをどのように使用されますか?
Python のご利用経験はどの程度ありますか?
Google Cloud サービスの使用経験はどの程度ありますか?
<ph type="x-smartling-placeholder">2. 設定と要件
セルフペース型の環境設定
- Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Gmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。
- プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列です。この値はいつでも更新できます。
- プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud コンソールでは一意の文字列が自動生成されます。通常、それが何であるかは関係ありません。ほとんどの Codelab では、プロジェクト ID を参照する必要があります(通常は
PROJECT_ID
として識別されます)。生成された ID が気に入らない場合は、別のランダムな ID を生成できます。または、ご自身でお試しになることもできます。このステップを終えた後は変更できず、プロジェクト期間中は維持されます。 - なお、3 つ目の値は、一部の API で使用される [プロジェクト番号] です。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
- 次に、Cloud のリソースや API を使用するために、Cloud コンソールで課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルの終了後に課金が発生しないようにリソースをシャットダウンするには、作成したリソースを削除するか、プロジェクト全体を削除します。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。
Cloud Shell の起動
Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では、Google Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。
Cloud Shell をアクティブにする
- Cloud Console で、[Cloud Shell をアクティブにする] をクリックします。
Cloud Shell を初めて起動する場合は、その内容を説明する中間画面(スクロールしなければ見えない範囲)が表示されます。その場合は、[続行] をクリックします(今後表示されなくなります)。この中間画面は次のようになります。
Cloud Shell のプロビジョニングと接続に少し時間がかかる程度です。
この仮想マシンには、必要な開発ツールがすべて含まれています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。このコードラボでの作業のほとんどは、ブラウザまたは Chromebook から実行できます。
Cloud Shell に接続すると、すでに認証は完了しており、プロジェクトに各自のプロジェクト ID が設定されていることがわかります。
- Cloud Shell で次のコマンドを実行して、認証されたことを確認します。
gcloud auth list
コマンド出力
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project
コマンド出力
[core] project = <PROJECT_ID>
上記のようになっていない場合は、次のコマンドで設定できます。
gcloud config set project <PROJECT_ID>
コマンド出力
Updated property [core/project].
3. Secret Manager API を有効にする
Secret Manager API を使用するには、この API を有効にする必要があります。Cloud Shell を使用し、次のコマンドで API を有効にできます。
gcloud services enable secretmanager.googleapis.com
次のような出力が表示されます。
Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.
4. Python 用 Secret Manager クライアント ライブラリのインストール
Secret Manager クライアント ライブラリをインストールします。
pip3 install --user google-cloud-secret-manager==2.10.0
5. インタラクティブな Python を開始する
このチュートリアルでは、IPython というインタラクティブな Python インタープリタを使用します。このインタープリタは Cloud Shell にプリインストールされています。Cloud Shell で ipython
を実行してセッションを開始します。
ipython
次のように表示されます。
Python 3.9.2 (default, Feb 28 2021, 17:03:44) Type 'copyright', 'credits' or 'license' for more information IPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help. In [1]:
6. Secret の作成
1 つのシークレットには 1 つ以上のシークレット バージョンが含まれています。gcloud
コマンドラインを使用して作成できますが、Python を使用して作成することもできます。
シークレットを使用するには、まずシークレットの名前でシークレットを作成し、次にシークレットの値となるシークレットのバージョンを追加する必要があります。
IPython 内でプロジェクト ID を設定します。
PROJECT_ID = "<PROJECT_ID>"
シークレットを作成する
次のコードを IPython セッションにコピーします。
from google.cloud import secretmanager
def create_secret(secret_id):
# Create the Secret Manager client.
client = secretmanager.SecretManagerServiceClient()
# Build the resource name of the parent project.
parent = f"projects/{PROJECT_ID}"
# Build a dict of settings for the secret
secret = {'replication': {'automatic': {}}}
# Create the secret
response = client.create_secret(secret_id=secret_id, parent=parent, secret=secret)
# Print the new secret name.
print(f'Created secret: {response.name}')
関数を呼び出して、my_secret_value
という新しいシークレットを作成します。
create_secret("my_secret_value")
次の出力が表示されます。
Created secret: projects/<PROJECT_NUM>/secrets/my_secret_value
シークレット バージョンを追加する
シークレットが作成されたので、バージョンを作成して値を割り当てることができます。
次のコードを IPython セッションにコピーします。
def add_secret_version(secret_id, payload):
# Create the Secret Manager client.
client = secretmanager.SecretManagerServiceClient()
# Build the resource name of the parent secret.
parent = f"projects/{PROJECT_ID}/secrets/{secret_id}"
# Convert the string payload into a bytes. This step can be omitted if you
# pass in bytes instead of a str for the payload argument.
payload = payload.encode('UTF-8')
# Add the secret version.
response = client.add_secret_version(parent=parent, payload={'data': payload})
# Print the new secret version name.
print(f'Added secret version: {response.name}')
関数を呼び出して、新しいシークレット バージョンを追加します。
add_secret_version("my_secret_value", "Hello Secret Manager")
次の出力が表示されます。
Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/1
シークレットには複数のバージョンを含めることができます。別の値で関数を再度呼び出します。
add_secret_version("my_secret_value", "Hello Again, Secret Manager")
次の出力が表示されます。
Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/2
新しいバージョンのシークレットが元のシークレットよりも大幅に長いことに注目してください。この属性は後で参照します。
7. シークレットへのアクセス
シークレット バージョンにアクセスすると、シークレットの内容と、シークレット バージョンに関する追加のメタデータが返されます。シークレット バージョンにアクセスするときは、特定のバージョンを指定するか、「latest」を指定して最新バージョンを要求できます。
Secret は非公開にする必要があります。データベースの認証情報をシークレットとして保存し、それを使用して認証するか、証明書を保存して使用する。ただし、機密事項を直接出力しないでください。秘密を守るという目的が果たされません。
これから Secret を操作し、Secret を直接出力せずにその値を評価します。代わりに、シークレットの値のハッシュを出力します。
次のコードを IPython セッションにコピーします。
def access_secret_version(secret_id, version_id="latest"):
# Create the Secret Manager client.
client = secretmanager.SecretManagerServiceClient()
# Build the resource name of the secret version.
name = f"projects/{PROJECT_ID}/secrets/{secret_id}/versions/{version_id}"
# Access the secret version.
response = client.access_secret_version(name=name)
# Return the decoded payload.
return response.payload.data.decode('UTF-8')
import hashlib
def secret_hash(secret_value):
# return the sha224 hash of the secret value
return hashlib.sha224(bytes(secret_value, "utf-8")).hexdigest()
関数を呼び出して、シークレットを値のハッシュとして取得します。
secret_hash(access_secret_version("my_secret_value"))
ハッシュに似た出力が表示されます(正確な値がこの出力と一致しない場合があります)。
83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11
バージョンを指定していないため、最新の値が取得されました。
想定されるバージョン番号を追加して関数を呼び出し、確認します。
secret_hash(access_secret_version("my_secret_value", version_id=2))
最後のコマンドと同じ出力が表示されます。
83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11
関数を再度呼び出します。ただし、今回は最初のバージョンを指定します。
secret_hash(access_secret_version("my_secret_value", version_id=1))
今回は異なるハッシュが表示されるはずです。これは、出力が異なることを示しています。
9a3fc8b809ddc611c82aee950c636c7557e220893560ec2c1eeeb177
8. Cloud Functions での Secret Manager の使用
Google Cloud のさまざまな部分でシークレットを利用できます。このセクションでは、Google のイベント ドリブン サーバーレス コンピューティング サービスである Cloud Functions を中心に説明します。
Cloud Functions で Python を使用することに関心がある場合は、Python の Codelab における HTTP Google Cloud Functions のコースを進めることができます。
exit
関数を呼び出して IPython を閉じます。
exit
Cloud Shell に戻ります。
yourname@cloudshell:~ (<PROJECT_ID>)$
Cloud Functions API を使用する前に、この API を有効にする必要があります。Cloud Shell を使用し、次のコマンドで API を有効にできます。
gcloud services enable cloudfunctions.googleapis.com cloudbuild.googleapis.com
関数をビルドするための新しいフォルダを作成し、書き込み先となる空のファイルを作成します。
mkdir secret-manager-api-demo cd secret-manager-api-demo touch main.py touch requirements.txt
Cloud Shell の右上からコードエディタを開きます。
secret-manager-api-demo
フォルダ内の main.py
ファイルに移動します。ここにすべてのコードを配置します
9. シークレットにアクセスする Cloud Functions の関数を作成する
コマンドラインまたは IPython ターミナルからシークレットの値の保存や取得を行うのは便利ですが、関数内でこれらのシークレットにアクセスできるほうがはるかに便利です。
先ほど作成した access_secret_version
関数を使用して、Cloud Functions の関数のベースとして使用できます。
次のコードを main.py
ファイルにコピーします。
main.py
import os
from google.cloud import secretmanager
project_id = os.environ["PROJECT_ID"]
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/my_secret_value/versions/latest"
response = client.access_secret_version(name=name)
my_secret_value = response.payload.data.decode("UTF-8")
def secret_hello(request):
if "Again" in my_secret_value:
return "We meet again!\n"
return "Hello there.\n"
関数をデプロイする前に、環境の設定を完了する必要があります。そのためには、関数の依存関係を設定する必要があります。
requirements.txt
という新しいファイルを作成し、google-cloud-secret-manager
パッケージを追加します。
requirements.txt
google-cloud-secret-manager==2.10.0
これで、main.py
と requirements.txt
だけを含むフォルダが作成されました。
シークレットへのアクセスを許可する
関数をデプロイする前に、Cloud Functions にシークレットへのアクセスを許可する必要があります。
ターミナルに戻ります。
シークレットにアクセスするためのアクセス権を Cloud Functions サービス アカウントに付与します。
export PROJECT_ID=$(gcloud config get-value core/project) gcloud secrets add-iam-policy-binding my_secret_value \ --role roles/secretmanager.secretAccessor \ --member serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com
次の出力が表示されます。
Updated IAM policy for secret [my_secret_value]. bindings: - members: - serviceAccount:<PROJECT_ID>@appspot.gserviceaccount.com role: roles/secretmanager.secretAccessor etag: BwWiRUt2oB4= version: 1
10. Cloud Functions の関数をデプロイする
前のセクションのセットアップが完了したら、Cloud Functions の関数をデプロイしてテストできます。
作成した 2 つのファイルのみを含むフォルダ内で、関数をデプロイします。
gcloud functions deploy secret_hello \ --runtime python39 \ --set-env-vars PROJECT_ID=${PROJECT_ID} \ --trigger-http \ --allow-unauthenticated
次の出力が表示されます(一部が切り捨てられています)。
Deploying function (may take a while - up to 2 minutes)...done. ... entryPoint: secret_hello httpsTrigger: url: https://<REGION>-<PROJECT_ID>.cloudfunctions.net/secret_hello ... status: ACTIVE ...
次のコマンドを使用して、関数の URL(httpsTrigger.url
メタデータ)を取得します。
FUNCTION_URL=$(gcloud functions describe secret_hello --format 'value(httpsTrigger.url)')
次に、関数を呼び出して、期待される戻り値で関数にアクセスできるかどうかをテストします。
curl $FUNCTION_URL
次の出力が表示されます。
We meet again!
この関数は、文字列「Again」を含むように設定されている最新バージョンのシークレットを参照するため、この関数は想定どおりに動作します。
11. 完了
Python を使用して Secret Manager API を使用する方法を学びました。
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにする手順は次のとおりです。
- Cloud コンソールで、[リソースの管理] ページに移動します。
- プロジェクト リストで、プロジェクトを選択し、[削除] をクリックします。
- ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。
詳細
- Secret Manager: https://cloud.google.com/secret-manager/
- Google Cloud 上の Python: https://cloud.google.com/python/
- Python 用 Cloud クライアント ライブラリ: https://googlecloudplatform.github.io/google-cloud-python/
ライセンス
この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。