このチュートリアルでは、Google Kubernetes Engine(GKE)クラスタで使用されるセンシティブ データを Secret Manager に保存し、GKE 用 Workload Identity 連携と Google Cloud クライアント ライブラリを使用して Pod のデータに安全にアクセスする方法について説明します。このチュートリアルは、クラスタ内のストレージからセンシティブ データを移動するセキュリティ管理者を対象としています。
クラスタ ストレージの外部にセンシティブ データを保存すると、攻撃が発生した場合に不正アクセスされるリスクが軽減されます。GKE 用 Workload Identity 連携を使用してデータにアクセスすると、有効期間の長いサービス アカウント キーの管理に伴うリスクを回避し、クラスタ内の RBAC ルールではなく、Identity and Access Management(IAM)を使用して Secret へのアクセスを制御できます。Secret Manager や HashiCorp Vault などの外部 Secret ストア プロバイダを使用できます。
このチュートリアルでは、GKE Autopilot クラスタを使用します。この操作を GKE Standard で行う場合は、GKE 用 Workload Identity 連携を手動で有効にする必要があります。
GKE 用 Workload Identity 連携を使用すると、静的なサービス アカウント キー ファイルのような安全性の低い手段を使用することなく、GKE ワークロードから Google Cloud APIs にアクセスできます。このチュートリアルでは Secret Manager を例として使用しますが、同じ手順で他の Google Cloud APIs にアクセスすることもできます。詳細については、GKE 用 Workload Identity 連携をご覧ください。
目標
- Google Cloud Secret Manager で Secret を作成します。
- GKE Autopilot クラスタ、Kubernetes Namespace、Kubernetes サービス アカウントを作成します。
- IAM 許可ポリシーを作成して、Secret の Kubernetes サービス アカウントへのアクセスを許可します。
- テスト アプリケーションを使用してサービス アカウントへのアクセスを確認します。
- Secret Manager API を使用して Secret にアクセスするサンプルアプリを実行します。
費用
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
始める前に
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Kubernetes Engine and Secret Manager APIs:
gcloud services enable container.googleapis.com
secretmanager.googleapis.com - Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Kubernetes Engine and Secret Manager APIs:
gcloud services enable container.googleapis.com
secretmanager.googleapis.com -
Grant roles to your user account. Run the following command once for each of the following IAM roles:
roles/secretmanager.admin, roles/container.clusterAdmin
gcloud projects add-iam-policy-binding PROJECT_ID --member="USER_IDENTIFIER" --role=ROLE
- Replace
PROJECT_ID
with your project ID. -
Replace
USER_IDENTIFIER
with the identifier for your user account. For example,user:myemail@example.com
. - Replace
ROLE
with each individual role.
- Replace
環境を準備する
このチュートリアルのサンプル ファイルを含む GitHub リポジトリのクローンを作成します。
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd ~/kubernetes-engine-samples/security/wi-secrets
Secret Manager で Secret を作成する
次の例は、Secret の作成に使用するデータを示しています。
サンプルデータを格納する Secret を作成します。
gcloud secrets create bq-readonly-key \ --data-file=manifests/bq-readonly-key \ --ttl=3600s
このコマンドは次の処理を行います。
us-central1
Google Cloud リージョンでサンプルキーを使用して新しい Secret Manager Secret を作成します。- コマンドを実行してから 1 時間後に Secret を期限切れに設定します。
クラスタと Kubernetes リソースを作成する
GKE クラスタ、Kubernetes Namespace、Kubernetes サービス アカウントを作成します。2 つの Namespace を作成します(1 つは読み取り専用アクセス用、もう 1 つは Secret への読み取り / 書き込みアクセス用)。また、GKE 用 Workload Identity 連携で使用する Kubernetes サービス アカウントを各 Namespace に作成します。
GKE Autopilot クラスタを作成します。
gcloud container clusters create-auto secret-cluster \ --region=us-central1
クラスタのデプロイには 5 分ほどかかります。Autopilot クラスタでは常に GKE 用 Workload Identity 連携が有効になっています。GKE Standard クラスタを使用する場合は、続行する前に GKE 用 Workload Identity 連携を手動で有効にする必要があります。
readonly-ns
Namespace とadmin-ns
Namespace を作成します。kubectl create namespace readonly-ns kubectl create namespace admin-ns
readonly-sa
Kubernetes サービス アカウントとadmin-sa
Kubernetes サービス アカウントを作成します。kubectl create serviceaccount readonly-sa --namespace=readonly-ns kubectl create serviceaccount admin-sa --namespace=admin-ns
IAM 許可ポリシーを作成する
readonly-sa
サービス アカウントに、シークレットへの読み取り専用アクセス権を付与します。gcloud secrets add-iam-policy-binding bq-readonly-key \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/readonly-ns/sa/readonly-sa \ --role='roles/secretmanager.secretAccessor' \ --condition=None
次のように置き換えます。
PROJECT_NUMBER
: 数値による Google Cloud プロジェクト番号。PROJECT_ID
: Google Cloud プロジェクト ID。
admin-sa
サービス アカウントに、Secret への読み取り / 書き込みアクセス権を付与します。gcloud secrets add-iam-policy-binding bq-readonly-key \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \ --role='roles/secretmanager.secretAccessor' \ --condition=None gcloud secrets add-iam-policy-binding bq-readonly-key \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \ --role='roles/secretmanager.secretVersionAdder' \ --condition=None
Secret へのアクセスを確認する
各 Namespace にテスト Pod をデプロイして、読み取り専用アクセスと読み取り / 書き込みアクセスを確認します。
読み取り専用 Pod マニフェストを確認します。
この Pod は、
readonly-ns
Namespace 内のreadonly-sa
サービス アカウントを使用します。読み取り / 書き込み Pod マニフェストを確認します。
この Pod は、
admin-ns
Namespace 内のadmin-sa
サービス アカウントを使用します。テスト Pod をデプロイします。
kubectl apply -f manifests/admin-pod.yaml kubectl apply -f manifests/readonly-pod.yaml
Pod の実行が開始されるまでに数分かかることがあります。進捗状況をモニタリングするには、次のコマンドを実行します。
watch kubectl get pods -n readonly-ns
Pod のステータスが
RUNNING
に変わったら、Ctrl+C
を押してコマンドラインに戻ります。
読み取り専用アクセスをテストする
readonly-test
Pod でシェルを開きます。kubectl exec -it readonly-test --namespace=readonly-ns -- /bin/bash
Secret を読み取ります。
gcloud secrets versions access 1 --secret=bq-readonly-key
出力は
key=my-api-key
です。新しいデータを Secret に書き込みます。
printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-
出力は次のようになります。
ERROR: (gcloud.secrets.versions.add) PERMISSION_DENIED: Permission 'secretmanager.versions.add' denied for resource 'projects/PROJECT_ID/secrets/bq-readonly-key' (or it may not exist).
読み取り専用サービス アカウントを使用する Pod は、Secret の読み取りのみ可能であり、新しいデータを書き込むことはできません。
Pod を終了します。
exit
読み取り / 書き込みアクセスをテストする
admin-test
Pod でシェルを開きます。kubectl exec -it admin-test --namespace=admin-ns -- /bin/bash
Secret を読み取ります。
gcloud secrets versions access 1 --secret=bq-readonly-key
出力は
key=my-api-key
です。新しいデータを Secret に書き込みます。
printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-
出力は次のようになります。
Created version [2] of the secret [bq-readonly-key].
新しい Secret バージョンを確認します。
gcloud secrets versions access 2 --secret=bq-readonly-key
出力は
my-second-api-key
です。Pod を終了します。
exit
Pod には、Pod マニフェストで使用される Kubernetes サービス アカウントに付与されるアクセスレベルのみを取得します。admin-ns
Namespace の admin-sa
Kubernetes アカウントを使用する Pod は Secret の新しいバージョンを書き込むことができますが、readonly-sa
Kubernetes サービス アカウントを使用する readonly-ns
Namespace の Pod は Secret を読み取ることのみができます。
コードから Secret にアクセスする
このセクションでは、次の操作を行います。
クライアント ライブラリを使用して、Secret Manager で Secret を読み取るサンプル アプリケーションをデプロイします。
アプリケーションが Secret にアクセスできることを確認します。
可能な限り、Secret Manager API を使用して、アプリケーション コードから Secret Manager の Secret にアクセスする必要があります。
サンプル アプリケーションのソースコードを確認します。
このアプリケーションは、Secret Manager API を呼び出して Secret を取得します。
サンプル アプリケーションの Pod マニフェストを確認します。
このマニフェストの内容は次のとおりです。
readonly-sa
サービス アカウントを使用するreadonly-ns
Namespace に Pod を作成します。- Google イメージ レジストリからサンプル アプリケーションを pull します。このアプリケーションは、Google Cloud クライアント ライブラリを使用して Secret Manager API を呼び出します。アプリケーション コードは、リポジトリ内の
/main.go
で確認できます。 - 使用するサンプル アプリケーションの環境変数を設定します。
サンプル アプリケーションの環境変数を置き換えます。
sed -i "s/YOUR_PROJECT_ID/PROJECT_ID/g" "manifests/secret-app.yaml"
サンプルアプリをデプロイします。
kubectl apply -f manifests/secret-app.yaml
Pod が機能し始めるまでに数分かかることがあります。Pod がクラスタに新しいノードを必要とする場合、GKE がノードのプロビジョニングしている間に
CrashLoopBackOff
タイプのイベントが発生することがあります。ノードが正常にプロビジョニングされると、クラッシュは停止します。Secret へのアクセスを確認します。
kubectl logs readonly-secret-test -n readonly-ns
出力は
my-second-api-key
です。出力が空白の場合、Pod がまだ実行されていない可能性があります。数分待ってから、もう一度お試しください。
その他の方法
機密データを Pod にマウントする必要がある場合は、GKE 用の Secret Manager アドオン(プレビュー)を使用します。このアドオンは、GKE クラスタで Kubernetes Secret Store CSI ドライバの Google Cloud Secret Manager プロバイダをデプロイして管理します。手順については、GKE で Secret Manager アドオンを使用するをご覧ください。
マウントされたボリュームとして Secret を提供すると、次のようなリスクがあります。
- マウントされたボリュームは、ディレクトリ トラバーサル攻撃を受けやすくなります。
- デバッグ エンドポイントを開くなどの構成ミスによって、環境変数が不正使用される可能性があります。
可能な限り、Secret Manager API を使用してプログラムで Secret にアクセスすることをおすすめします。手順については、このチュートリアルのサンプル アプリケーションを使用するか、Secret Manager クライアント ライブラリをご覧ください。
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
リソースを個別に削除する
クラスタを削除します。
gcloud container clusters delete secret-cluster \ --region=us-central1
Secret Manager で Secret を削除します。
gcloud secrets delete bq-readonly-key
この手順を行わないと、作成時に
--ttl
フラグを設定したため、Secret は自動的に期限切れになります。
プロジェクトを削除する
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
次のステップ
- GKE 用 Workload Identity 連携の仕組みについて学習する。
- Google Cloud に関するリファレンス アーキテクチャ、図、ベスト プラクティスを確認する。Cloud アーキテクチャ センターをご覧ください。