Kubernetes クラスターで実行されるアプリのシークレットの保護
このチュートリアルでは、 外部シークレット・オペレーター ・オープン・ソース・ツールを使用して IBM Cloud Kubernetes Service クラスターを実行するアプリケーションのシークレットを管理するために IBM Cloud® Secrets Manager を使用する方法を学習します。
あるいは、 Kubernetes Service CLI プラグインを使用して、TLS シークレットと非 TLS シークレットを管理することもできます。 この方法について詳しくは、 Kubernetes Ingress のセットアップ を参照してください。
あなたは組織の開発者であり、あなたのチームは Kubernetes Service を使用して、 IBM Cloud 上にコンテナ化されたアプリケーションとサービスを展開しています。 現在のフローでは、 Kubernetes Secrets を使用して、クラスタで実行されるアプリやサービスで使用されるパスワードやAPIキーなどの機密データを保存しています。 アプリケーションのシークレットの制御を強化するには、外部のシークレット管理サービスにクラスターのシークレットを保管する機能を使用できます。このサービスでは、保存されたシークレットの暗号化、シークレットのアクティビティーのモニタリングが可能で、さらにシークレットの管理も簡単になります。
Secrets Manager を使用すると、 Kubernetes クラスターで実行されるアプリケーションによって使用されるシークレットを集中させて保護できます。 デプロイ時にシークレットを投入するのではなく、実行時に Secrets Manager からシークレットを安全にリトリーブするようにアプリケーションを構成できます。 シークレットを置き換える時間がある場合は、Secrets Manager から可能です。 例えば、以下のシナリオがあるとします。
- デベロッパーとして、Secrets Manager を使用して、Kubernetes クラスターにデプロイしたいアプリケーションのシークレットを保管します。
- Secrets Manager がシークレットの ID を提供します。 このIDをアプリの
ExternalSecrets
構成ファイルに記述して、その構成をクラスターに適用します。 - 外部シークレットコントローラーは、Kubernetes APIを使用して定義した構成ファイル内の
ExternalSecrets
オブジェクトをフェッチします。 - アプリケーションの実行時に、コントローラーはSecrets Managerから秘密データを取得し、
ExternalSecrets
オブジェクトをクラスターのKubernetes秘密に変換します。
このシナリオは、Kubernetes クラスターで実行されるワークロードのコンプライアンスの準備に影響を及ぼす可能性のある、サード・パーティー・ツールを特徴としています。 コミュニティやサードパーティのツールを追加する場合は、アプリのコンプライアンスを維持する責任があることを念頭に置き、問題が発生した場合は適切なプロバイダーと協力してトラブルシューティングを行う必要があります。 詳細については、IBM Cloud Kubernetes Service 使用の際の責任を参照してください。
開始前に
開始する前に、アカウント資格情報を作成し、リソースをプロビジョニングできるように、必ず管理者プラットフォーム・アクセス権限 を使用するようにしてください。 以下の前提条件も必要です。
-
jq
は、JSONデータのスライスとフィルタリングに役立ちます。 このチュートリアルにあるjq
を使用して、保管された環境変数を取得・使用します。
環境を設定する
Secrets Manager および Kubernetes Service を操作するには、IBM Cloud アカウントにクラスターと Secrets Manager インスタンスを作成する必要があります。 また、両方のサービスに対して操作を実行できるように許可を構成する必要もあります。
このステップでは、サービス ID と IBM Cloud API キーを作成して、アクセス環境をセットアップします。 これらのリソースが不要になった場合は、チュートリアルの終了時に簡単に削除できます。 あるいは、 信頼されたプロファイル を使用して、外部シークレット・オペレーターを許可することもできます。
サービス ID および API キーの作成
開始するには、Secrets Manager および Kubernetes Service に対して操作を実行するために必要なアカウント資格情報を作成します。
-
IBM Cloud CLI を使用して、コマンド・ラインから IBM Cloud にログインします。
ibmcloud login
ログインに失敗した場合は、
ibmcloud login --sso
コマンドを実行して再試行してください。 フェデレーテッドIDを使用してログインする場合は、--sso
パラメーターが必要です。 このオプションを使用する場合、CLI 出力にリストされているリンクに移動して、ワンタイム・パスコードを生成します。 -
サービス ID を作成し、環境変数として設定します。
export SERVICE_ID=`ibmcloud iam service-id-create kubernetes-secrets-tutorial --description "A service ID for testing ESO integration" --output json | jq -r ".id"`; echo $SERVICE_ID
-
サービス ID 許可を割り当てて、Secrets Manager からシークレットを読み取ります。
ibmcloud iam service-policy-create $SERVICE_ID --roles "SecretsReader" --service-name secrets-manager
SecretsReader サービス・アクセスを割り当てると、Secrets Manager からシークレットを読み取り、Kubernetes クラスターに取り込むための正しいレベルのアクセス権限が外部シークレット・コントローラーに付与されます。
-
サービス ID 用に IBM Cloud API キーを作成します。
export IBM_CLOUD_API_KEY=`ibmcloud iam service-api-key-create kubernetes-secrets-tutorial $SERVICE_ID --description "An API key for testing ESO integration." --output json | jq -r ".apikey"`
この API キーは、後でクラスター・デプロイメント用に Secrets Manager を構成する際に使用します。
Kubernetes クラスターと Secrets Manager インスタンスを作成します。
Kubernetes クラスタと Secrets Manager のインスタンスを IBM Cloud アカウント内に作成します。
IBM Cloud アカウントあたり、1 つの空き Kubernetes クラスターと Secrets Manager サービス・インスタンスを作成できます。 両方のリソースがご使用のアカウントに既にある場合は、既存の空きクラスターおよび Secrets Manager インスタンスを使用してチュートリアルを完了できます。
-
コマンド・ラインから、Secrets Manager サービス・インスタンスを作成するアカウント、リージョン、リソース・グループを選択します。
このチュートリアルでは、ダラス地域と対話します。 別の地域にログインしている場合は、次のコマンドを実行して、ダラスをターゲット地域に設定してください。
ibmcloud target -r us-south -g default
-
Kubernetes クラスターを作成します。
ibmcloud ks cluster create classic --zone dal10 --flavor free --name my-test-cluster
-
Secrets Manager インスタンスを作成します。
ibmcloud resource service-instance-create my-secrets-manager secrets-manager trial us-south
Secrets Manager とご使用の Kubernetes クラスターの両方のプロビジョニング完了には 5 分から 15 分かかります。
-
次のステップに進む前に、クラスタと Secrets Manager インスタンスが正しくプロビジョニングされたことを確認してください。
-
ワーカー・ノードのデプロイメントが完了していることを確認します。
ibmcloud ks worker ls --cluster my-test-cluster
ワーカー・ノードがプロビジョニングを終了すると、ステータスは 「レディー」 に変わります。
ID Public IP Private IP Flavor State Status Zone Version kube-c39pf4ld0m87o3fv1utg-mytestclust-default-000000dd 169.xx.xx.xxx 10.xxx.xx.xxx free normal Ready mex01 1.20.7_1543
-
次に、Secrets Manager インスタンスが正常にプロビジョニングされたことを確認します。
ibmcloud resource service-instance my-secrets-manager
インスタンスがプロビジョニングを終了すると、ステータスは 「アクティブ」 に変わります。
Name: my-secrets-manager ID: crn:v1:bluemix:public:secrets-manager:us-south:a/f047b55a3362ac06afad8a3f2f5586ea:fe06948b-0c6b-4183-8d4b-e6c1d38ff65f:: GUID: fe06948b-0c6b-4183-8d4b-e6c1d38ff65f Location: us-south Service Name: secrets-manager Service Plan Name: trial Resource Group Name: default State: active Type: service_instance Sub Type: Created at: 2021-01-06T17:11:32Z Created by: zara@example.com Updated at: 2021-03-31T02:33:26Z
-
-
CLI で、Kubernetes クラスターのコンテキストを設定します。
ibmcloud ks cluster config --cluster my-test-cluster
-
kubectl
コマンドが正しく実行され、Kubernetesコンテキストがクラスターに設定されていることを確認します。kubectl config current-context
出力例:
my-test-cluster/<your_cluster_ID>
トラステッド・プロファイルの作成
信頼できるプロファイルにより、外部シークレット・オペレーターは、サービス ID を作成したり API キーを管理したりすることなく、 Secrets Managerから読み取ることができます。
-
Secrets Manager インスタンスおよび Kubernetes クラスターの CRN を取得します。
CLUSTER_CRN=$(ibmcloud ks cluster get --cluster my-test-cluster --output json | jq -r '.crn') SECRETS_MANAGER_CRN=$(ibmcloud resource service-instance my-secrets-manager --output JSON | jq -r '.[0].crn')
-
プロファイルを作成します。
ibmcloud iam trusted-profile-create 'External Secrets'
-
信頼できるプロファイルを使用する権限を Kubernetes クラスターに付与します。
Kubernetes
ibmcloud iam trusted-profile-rule-create 'External Secrets' --name kubernetes --type Profile-CR --conditions claim:namespace,operator:EQUALS,value:external-secrets --conditions claim:name,operator:EQUALS,value:external-secrets --conditions claim:crn,operator:EQUALS,value:$CLUSTER_CRN --cr-type IKS_SA
OpenShift
ibmcloud iam trusted-profile-rule-create 'External Secrets' --name kubernetes --type Profile-CR --conditions claim:namespace,operator:EQUALS,value:external-secrets-operator --conditions claim:name,operator:EQUALS,value:cluster-external-secrets --conditions claim:crn,operator:EQUALS,value:$CLUSTER_CRN --cr-type IKS_SA
-
トラステッド・プロファイルが Secrets Manager インスタンスからシークレットを読み取ることを許可するアクセス・ポリシーを作成します。
ibmcloud iam trusted-profile-policy-create 'External Secrets' --roles SecretsReader --service-instance $SECRETS_MANAGER_CRN --service-name secrets-manager
Secrets Manager インスタンスの準備
最後に、シークレットの処理を開始できるように、Secrets Manager インスタンスを構成します。
-
コマンドラインから、Secrets Manager CLI プラグインにアクセスできることを確認します。
ibmcloud secrets-manager --help
まだプラグインをお持ちでないですか? Secrets ManagerCLIプラグインをインストールするには、
ibmcloud plugin install secrets-manager
を実行します。 -
固有の Secrets Manager API エンドポイント URLを使用して、環境変数をエクスポートします。
export SECRETS_MANAGER_URL=`ibmcloud resource service-instance my-secrets-manager --output json | jq -r '.[].dashboard_url | .[0:-3]'`; echo $SECRETS_MANAGER_URL
-
インスタンスのシークレット・グループを作成します。
シークレット・グループ は、インスタンス内の特定の機密情報にアクセスできるチーム内のユーザーを編成、制御するための方法です。 IBM Cloud CLI からシークレット・グループを作成するには、
ibmcloud secrets-manager secret-group-create
コマンドを使用します。 以下のコマンドを実行して、シークレット・グループを作成し、その ID を環境変数として保管します。export SECRET_GROUP_ID=`ibmcloud secrets-manager secret-group-create --name my-test-secret-group --description "Read and write to my test app" --output json --service-url $SECRETS_MANAGER_URL | jq -r '.id'`; echo $SECRET_GROUP_ID
Windows™コマンド・プロンプト(
cmd.exe
)またはPowerShellを使用していますか? コマンド・ラインで JSON コンテンツを渡す際にエラーが発生する場合、ご使用のオペレーティング・システムに固有の引用符のエスケープ要件に応じて、ストリングを調整する必要がある場合があります。 詳細については、IBM Cloud CLI の文字列の引用符の使用を参照してください。成功! これで、Kubernetes クラスターにデータを取り込むためのシークレットを Secrets Manager に保管できるようになりました。 次のステップに進んでください。
Secrets Manager にシークレットを作成する
シークレットはアプリケーション固有であり、シークレットを必要とする個別のアプリまたはサービスによって異なります。 シークレットは、ユーザー名、パスワード、API キー、またはその他のタイプの資格情報で構成される場合があります。
Secrets Manager は、サービスで作成および管理できるさまざまなシークレットのタイプをサポートしています。 例えば、IBM Cloud IAM 認証で保護されているアプリ用の API キーを管理する必要がある場合は、IAM 資格情報を作成できます。 または、不特定型の構造化データまたは非構造化データを保持できるシークレットを管理する必要がある場合は、任意シークレットを作成できます。
このチュートリアルでは、例として、ユーザー名およびパスワードを作成します。 IBM Cloud CLI からシークレットを作成するには、ibmcloud secrets-manager secret-create
コマンドを使用します。 以下のコマンドを実行して、シークレットを作成し、その ID を環境変数として保管します。
export SECRET_ID=`ibmcloud secrets-manager secret-create --secret-type=username_password --secret-name example_username_password --username-password-username user123 --username-password-password cloudy-rainy-coffee-book --secret-labels "my-test-cluster, tutorial" --secret-group-id $SECRET_GROUP_ID --output json $SECRETS_MANAGER_URL | jq -r '.id'`; echo $SECRET_ID
必ず、 instance_id
および region
をご使用のものに更新してください。
出力には、新しく作成されたシークレットの ID が表示されます。 以下に例を示します。
e0246cea-d668-aba7-eef2-58ca11ad3707
外部シークレット・オペレーターのセットアップ
アプリケーションの秘密が分かったので、クラスタに External Secrets Operatorツールを設定することができます。 このパッケージは、アプリケーションのKubernetesシークレットに変換されるExternalSecrets
オブジェクトを作成することで、Secrets
Managerとクラスターの間の接続を構成します。
外部シークレット・オペレーターは、IBM によって保守されないオープン・ソース・ツールです。 このツールの詳細や問題のトラブルシューティングについては、 プロジェクトのドキュメントを参照してください。
クラスターの外部シークレット・オペレーターの構成
Kubernetes
まず、公式のHelmチャートをインストールして、external-secrets
リソースをクラスターに追加します。 インストール・オプションについて詳しくは、 入門ガイドを参照してください。
-
外部 Secrets Operator Helm リポジトリーをインストールするには、以下のコマンドを実行します。
helm repo add external-secrets https://charts.external-secrets.io
-
外部 Secrets Operator と Secrets Managerの間の認証を構成します。
認証にサービス ID を使用している場合は、以下のようにします。
kubectl -n default create secret generic secret-api-key --from-literal=apikey=$IBM_CLOUD_API_KEY helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace --set installCRDs=true
信頼できるプロファイルを使用して認証を行っている場合は、以下のようにします。
echo ' installCRDs: true extraVolumes: - name: sa-token projected: defaultMode: 420 sources: - serviceAccountToken: path: sa-token expirationSeconds: 3600 audience: iam extraVolumeMounts: - mountPath: /var/run/secrets/tokens name: sa-token webhook: extraVolumes: - name: sa-token projected: defaultMode: 420 sources: - serviceAccountToken: path: sa-token expirationSeconds: 3600 audience: iam extraVolumeMounts: - mountPath: /var/run/secrets/tokens name: sa-token' >values.yml helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace -f values.yml
OpenShift
-
External Secrets Operator をインストールするには、以下のリソースを作成します。
echo ' apiVersion: v1 kind: Namespace metadata: name: external-secrets-operator --- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: external-secrets-operator namespace: external-secrets-operator spec: targetNamespaces: - external-secrets-operator --- apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: external-secrets-operator namespace: external-secrets-operator spec: channel: stable installPlanApproval: Automatic name: external-secrets-operator source: community-operators sourceNamespace: openshift-marketplace ' | oc create -f-
-
外部 Secrets Operator と Secrets Managerの間の認証を構成します。
認証にサービス ID を使用している場合は、以下のようにします。
echo " apiVersion: operator.external-secrets.io/v1alpha1 kind: OperatorConfig metadata: name: cluster namespace: external-secrets-operator spec: {} --- apiVersion: v1 kind: Secret metadata: name: secret-api-key namespace: default type: Opaque stringData: apikey: $IBM_CLOUD_API_KEY " | oc create -f-
信頼できるプロファイルを使用して認証を行っている場合は、以下のようにします。
echo ' apiVersion: operator.external-secrets.io/v1alpha1 kind: OperatorConfig metadata: name: cluster namespace: external-secrets-operator spec: extraVolumeMounts: - mountPath: /var/run/secrets/tokens name: sa-token extraVolumes: - name: sa-token projected: defaultMode: 420 sources: - serviceAccountToken: audience: iam expirationSeconds: 3600 path: sa-token webhook: extraVolumeMounts: - mountPath: /var/run/secrets/tokens name: sa-token extraVolumes: - name: sa-token projected: defaultMode: 420 sources: - serviceAccountToken: audience: iam expirationSeconds: 3600 path: sa-token ' | oc create -f-
アプリ構成の更新
外部シークレット・オペレーターをクラスターにインストールした後、アプリケーションのシークレット・バックエンドとして Secrets Manager を定義できます。 開始するには、Secrets Manager で使用したいシークレットをターゲットとする構成ファイルを作成します。
-
アプリケーションのルート・ディレクトリーに、
external-secrets-example.yml
ファイルを作成します。touch external-secrets-example.yml
-
ファイルを修正して、Secrets Manager インスタンスから取り出すシークレットに関する情報を含めます。
apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: ibmcloud-secrets-manager-example spec: provider: ibm: serviceUrl: <endpoint_url> auth: secretRef: secretApiKeySecretRef: name: secret-api-key key: apikey --- apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: ibmcloud-secrets-manager-example spec: secretStoreRef: name: ibmcloud-secrets-manager-example kind: SecretStore target: name: ibmcloud-secrets-manager-example data: - secretKey: username remoteRef: property: username key: username_password/<SECRET_ID> - secretKey: password remoteRef: property: password key: username_password/<SECRET_ID>
シークレット ID またはシークレット名の 2 つのモードで作業することを選択できます。 シークレット名を選択すると、形式が
secret_type/secret_id
からsecret_group/secret_type/secret_name
に変わります。<endpoint_url>
を、Secrets Manager 取得したエンドポイント URL 以前に置き換えます。<SECRET_ID>
を、前のステップで作成したシークレットの固有 ID に置き換えます。トラステッド・プロファイルを使用して認証を行っている場合は、
auth
ブロックを以下のスニペットに置き換えます。auth: containerAuth: profile: "External Secrets" iamEndpoint: https://iam.cloud.ibm.com tokenLocation: /var/run/secrets/tokens/sa-token
-
クラスターに構成を適用します。
kubectl apply -f external-secrets-example.yml
-
外部シークレット・オペレーターが、Secrets Manager インスタンスに保管されているシークレットをフェッチできることを確認します。
kubectl get secret ibmcloud-secrets-manager-example -o json | jq '.data | map_values(@base64d)'
出力例:
{ "password": "cloudy-rainy-coffee-book", "username": "user123" }
成功! これで、Secrets Manager インスタンスに保管されているシークレット・データをフェッチできるようになりました。 次のステップに進んでください。
クラスターへのアプリのデプロイ
最後に、external-secret-example.yml
ファイルで定義した Secrets Managerシークレットを使用するアプリケーションをクラスターにデプロイできます。 アプリケーション実行時に、Secrets Manager からフェッチされたシークレット・データは、クラスターで使用できる Kubernetes シークレットに変換されます。
アプリのデプロイ方法の例をお探しですか? アプリの単一インスタンスのデプロイについて詳しくは、 クラスターでの Kubernetesネイティブ・アプリのデプロイ を参照してください。
(オプション) リソースのクリーンアップ
本チュートリアルで作成したリソースが今後不要な場合は、以下の手順を実行して、アカウントからリソースを削除できます。
-
テスト Kubernetes クラスターを削除します。
ibmcloud ks cluster rm --cluster my-test-cluster
-
テスト Secrets Manager インスタンスを削除します。
ibmcloud resource service-instance-delete my-secrets-manager
-
許可を削除します。
サービス ID を使用している場合。
ibmcloud iam service-id-delete $SERVICE_ID
信頼できるプロファイルで作業している場合。
ibmcloud iam trusted-profile-delete 'External Secrets'
特記事項
YAML文書 を構築する際には、データセクションの各キーは、 Secrets Manager インスタンスからRESTを使用して定期的にポーリングされることを念頭に置いてください。 以下の点にご注意ください。
- デフォルトでは、ポーリング間隔は1時間に設定されており、この値を設定するのが望ましい。 この値は、External Secretsテンプレートで
spec.refreshInterval
を使用することで変更できます。 間隔は、s
、m
、またはh
の単位で表すことができます。 - Secrets Manager シークレットを ID (
keyByName: true
) ではなく名前でフェッチするように YAML を設定した場合、関連するシークレット ID をフェッチするために ESO によって追加の呼び出しが行われます。 詳しくは、外部シークレット資料をご覧ください。
次のステップ
お疲れさまでした。 このチュートリアルでは、Secrets Manager をセットアップして、アプリケーションのシークレットをクラスターに安全に取り込む方法を学習しました。 Secrets Manager の開始に役立つリソースをさらにチェックしてください。
- 外部シークレット・オペレーターによってサポートされている Secrets Manager内のシークレット・タイプ を確認します。
- Secrets Manager API の詳細をご覧ください。