ServiceAccount トークンを Secret として自動的にマウントする方法には、オーディエンスバインディングのないトークン、権限が過剰なシステムコンポーネントのアカウント、有効期限のないトークン、そしてサービスアカウントごとに 1 つの Secret が作成されることによるクラスターのスケーラビリティの制限という 4 つのセキュリティリスクがあります。ServiceAccount トークンボリュームプロジェクションは、トークンを projected ボリュームとして直接マウントすることで、これら 4 つすべてのリスクを解消します。これにより、Secret を必要とせず、設定可能なオーディエンスバインディング、自動回転、および設定可能な有効期限を実現します。
トークンボリュームプロジェクションを使用する理由
従来の方法では、各 ServiceAccount を Secret に保存し、ファイルとして Pod にマウントします。これにより、以下の問題が発生します:
-
オーディエンスバインディングの欠如:JSON Web トークン (JWT) が
audienceID にバインドされていないため、サービスアカウントの所有者が他のユーザーになりすまし、なりすまし攻撃を仕掛ける可能性があります。 -
広範な攻撃対象領域:システムコンポーネントは、多くの場合、必要以上の権限を持っています。攻撃者がこれらのサービスアカウントを取得した場合、Kubernetes コントロールプレーンに対して権限昇格攻撃を仕掛ける可能性があります。
-
有効期限がない:JWT は、サービスアカウントが存在する限り有効です。侵害されたトークンを失効させるには署名キーをローテーションする必要がありますが、これは client-go では自動化されていない複雑な手動プロセスです。
-
Secret の増殖:サービスアカウントごとに 1 つの Secret が作成されるため、大規模なワークロードのデプロイメントにおいて弾力性と容量が低下します。
ServiceAccount トークンボリュームプロジェクションは、これら 4 つすべての問題に対処します。Pod はトークンを projected ボリュームとしてマウントするため、Secret への依存を回避し、オーディエンスバインディング、有効期限、自動回転をサポートします。
前提条件
開始する前に、以下を確認してください:
-
Kubernetes 1.20 以降が実行されている ACK マネージドクラスター、ACK 専用クラスター、または ACK Serverless クラスター。 ACK マネージドクラスターを作成する、ACK 専用クラスターを作成する (廃止済み)、およびACK Serverless クラスターを作成するを参照してください。
-
クラスターで ServiceAccount Token Volume Projection が有効になっている必要があります。 この機能は、Kubernetes 1.22 以降を実行しているクラスターではデフォルトで有効になっています。 クラスターをアップグレードするには、「ACK クラスターを手動でアップグレードする」をご参照ください。
この機能が有効になると、API サーバーと controller-manager は、必要なフィーチャーゲートを自動的に設定し、API サーバーに以下の起動パラメーターを追加します:
| パラメーター | 説明 | デフォルト値 | コンソールでの設定 |
|---|---|---|---|
service-account-issuer |
ServiceAccount トークンの発行者。トークンペイロードの iss フィールドに対応します。 |
https://kubernetes.default.svc |
サポート済み |
api-audiences |
API サーバーへのリクエストトークンを検証するために使用される識別子。複数のオーディエンスを設定する場合は、カンマ (,) で区切ります。 |
https://kubernetes.default.svc |
サポート済み |
service-account-signing-key-file |
トークンの署名に使用される秘密鍵のファイルパス。 | /etc/kubernetes/pki/sa.key |
サポートされていません。デフォルト値: /etc/kubernetes/pki/sa.key |
手順1:ServiceAccount の作成
各名前空間には、default ServiceAccount が含まれています。既存のサービスアカウントを表示するには、次のコマンドを実行します:
kubectl get serviceaccounts
Pod のプロセスに専用の ID を割り当てるには、新しい ServiceAccount を作成します:
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
ServiceAccount が作成されたことを確認します:
kubectl get serviceaccounts/build-robot -o yaml
手順2:ServiceAccount トークンボリュームプロジェクションを使用した Pod のデプロイ
コンテナがクラスターの API サーバーで認証できるように、ServiceAccount トークンをボリュームとして Pod にプロジェクションします。次の例では、audience が vault で、有効期限が 2 時間 (7200 秒) のトークンを設定します。
-
次の内容で
nginx.yamlという名前のファイルを作成します:apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 name: nginx volumeMounts: - mountPath: /var/run/secrets/tokens name: vault-token serviceAccountName: build-robot volumes: - name: vault-token projected: sources: - serviceAccountToken: path: vault-token expirationSeconds: 7200 audience: vault -
Pod をデプロイします:
kubectl apply -f nginx.yaml -
トークンが正しい有効期限でマウントされていることを確認します。
-
Pod が実行中であることを確認します:
kubectl get pod nginx期待される出力:
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 3m15s -
Pod からトークンをダウンロードします:
kubectl exec -t nginx -- cat /var/run/secrets/tokens/vault-token > vault-token -
トークンをデコードし、その有効期限を確認します:
cat vault-token |awk -F '.' '{print $2}' |base64 -d 2>/dev/null |jq '.exp' | xargs -I {} date -d @{}出力例:
Mon Aug 26 15:45:59 CST 2024
-
トークンのローテーションとファイルパーミッション
トークンのローテーション
Pod がローテーションされた最新のトークンをリアルタイムで取得できるように、ターゲットトークンを定期的に (推奨は 5 分ごと) 再読み込みしてください。公式の Kubernetes は、client-go バージョン 10.0.0 以降でトークンの自動取得をサポートしています。
ファイルパーミッション
トークンボリュームプロジェクションを使用すると、コンテナ内の ServiceAccount トークンのファイルパーミッションが次のように変更されます:
| 設定 | パーミッション |
|---|---|
| 従来の ServiceAccount トークン (Secret からマウント) | 644 |
| バインドされた ServiceAccount トークンボリュームプロジェクション | 600 |
fsGroup が有効なバインド済みトークン |
640 |
次のステップ
-
RRSA による Pod アクセス制御のための ServiceAccount RAM 権限の設定を行うことで、Pod レベルの API アクセスの隔離と、クラウドリソースへのきめ細かなアクセス制御を実現します。
-
ACK Pro マネージドクラスターで Kubernetes の Secret キーを暗号化するには、「Alibaba Cloud KMS を使用したディスク暗号化」をご参照ください。
-
Kubernetes ドキュメントの「Pod のサービスアカウントの設定」。