Kubernetes API Server:匿名クライアント認証の設計と実装

Kubernetes API サーバーは、認証されていない要求(匿名要求)の取り扱いを制御するための柔軟なメカニズムを備えています。この仕組みは、ヘルスチェックやオープンな権限設定を行う場合に有用ですが、不適切に設定するとセキュリティリスクを引き起こす可能性があります。

1. 匿名要求の仕組み

クライアントが証明書、Bearer Token、Basic 認証などの認証情報を含まずに API サーバーにアクセスした場合、その要求は 匿名要求 として処理されます。

バージョン 1.6 以降では、デフォルトで匿名要求が許可されています(--anonymous-auth=true)。このとき、API サーバーは以下の属性で擬似的なユーザーを生成します:

  • ユーザー名: system:anonymous
  • 所属グループ: system:unauthenticated

2. 認証処理の流れ

要求が届いた際、API サーバーは以下の手順で匿名要求を扱います:

  1. 標準の認証チェーン(クライアント証明書、Token、Peer RP など)を適用
  2. いずれの方法でも認証できない場合、要求を匿名ユーザーとして扱う

図示すると、以下のようになります:

クライアント → (認証情報なし)
      ↓
API サーバー → 認証チェイン試行 → 全て失敗
      ↓
system:anonymous としてマッピング
      ↓
 RBAC による権限評価
      ↓
 200 OK / 403 Forbidden / 401 Unauthorized

3. 動作確認編

3.1 匿名要求を有効化した場合

以下のコマンドで API エンドポイントを匿名で呼び出すと、認証は成功しますが、デフォルトでは何も権限がないためアクセス拒否されます:

curl -k https://<apiserver-ip>:6443/api/v1/namespaces/default/pods

レスポンス例:

{
  "kind": "Status",
  "apiVersion": "v1",
  "status": "Failure",
  "message": "pods is forbidden: User \"system:anonymous\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "code": 403
}

実際に読み取り許可を与えるには、以下のように ClusterRoleBinding を作成します:

kubectl create clusterrolebinding allow-anon-list-pods \
  --clusterrole=view \
  --user=system:anonymous

この設定後にもう一度同じ cURL コマンドを実行すると、Pod リストが返却されます(該当名前空間に Pod が存在すること前提)。

3.2 匿名要求を無効化する場合

Kubernetes の管理用マニフェストを編集して、API サーバー起動時のオプションを変更します:

# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    - --anonymous-auth=false

変更後、kubeadm または kubelet が自動的に API サーバーを再起動します。再度匿名でアクセスすると、以下のように 401 Unauthorized が返されます:

{ "kind": "Status", "apiVersion": "v1", "status": "Failure", "message": "Unauthorized", "code": 401 }

4. 安全設定実践

4.1 匿名ユーザーへの明示的拒否

すべての匿名要求を防ぎたい場合は、RBAC を使用して明示的に拒绝することが推奨されます:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: deny-system-anonymous
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: denial-role
subjects:
- kind: User
  name: system:anonymous
  apiGroup: rbac.authorization.k8s.io

ただし、denial-role という名前の ClusterRole が事前に存在しない場合は、以下のように作成します:

kubectl create clusterrole denial-role --resource=* --verb=* --dry-run=client -o yaml | kubectl apply -f -

4.2 監査ログのカスタマイズ

匿名要求を監査ログに記録するには、監査ポリシーを次のように定義します:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  users: ["system:anonymous"]

このポリシーは要求・レスポンスボディを含めたログを生成します。./etc/kubernetes/audit-policy.yaml に配置し、API サーバー起動引数に --audit-policy-file=/etc/kubernetes/audit-policy.yaml を追加してください。

5. デバッグと検証コマンド集

  • API サーバー起動引数を確認:
ps aux | grep kube-apiserver | grep -E 'anonymous-auth'
  • system:anonymous が実際に持っている権限を評価する:
kubectl auth can-i create pods --as=system:anonymous
# 結果例: no

kubectl auth can-i list pods --as=system:anonymous
# 結果例: no(権限設定次第で yes になる場合あり)
  • 匿名要求のログを Direct検知:
kubectl logs -n kube-system kube-apiserver-$(hostname) | grep 'system:anonymous'

タグ: Kubernetes API-Server Anonymous-Authentication rbac Audit-Policy

9月15日 10:04 投稿