本文へスキップ

CKAD 概念ノート: ServiceAccount、アクセス制御、SecurityContext

  • kubernetes
  • ckad
  • rbac
  • serviceaccount
  • securitycontext
  • security

基準: Kubernetes v1.35 (kind kindest/node:v1.35.8 でコマンド・YAML を確認)

目次

リクエストの流れ

kubectl / Pod
   │  (client certificate, bearer token ...)
   ▼
[1] Authentication   失敗 → 401 Unauthorized
   ▼
[2] Authorization    失敗 → 403 Forbidden
   ▼
[3] Admission        mutating → validating、一つでも拒否するとリクエスト全体を拒否
   ▼
etcd に保存

Authentication: 誰なのか

  • ユーザーの種類は二つ
    • normal user: Kubernetes の外で管理。API で User オブジェクトは作れない
    • ServiceAccount: Kubernetes API が管理し、namespace に属する
  • 方式: client certificate、bearer token、authenticating proxy などの authentication plugin
  • 結果としてリクエストに付く属性: username、UID、groups、extra
  • ServiceAccount の username: system:serviceaccount:<namespace>:<name>
    • groups: system:serviceaccounts、system:serviceaccounts:<namespace>
  • どの方式でも拒否されなかったリクエストは (anonymous を許可していれば) system:anonymous / system:unauthenticated として扱う
  • 不正な bearer token → 401 Unauthorized

Authorization: してもよいか

  • 確認する属性: user、group、verb、resource、subresource、namespace、API group など
  • HTTP method → verb の対応
HTTPverb
POSTcreate
GET、HEADget (単一)、list (コレクション)、watch
PUTupdate
PATCHpatch
DELETEdelete (単一)、deletecollection (コレクション)
  • mode: Node、RBAC、ABAC、Webhook、AlwaysAllow、AlwaysDeny
  • 複数の authorizer があれば順番に問い合わせ、最初に allow/deny を出したものが決める。すべて「意見なし」なら拒否
  • デフォルトは deny。RBAC には許可のルールしかなく、拒否のルールはない
  • 拒否 → 403 Forbidden

Admission: 受け入れてよいか

  • authentication・authorization を通過した後、保存の直前にリクエストを横取りする kube-apiserver 組み込みのコード
  • 二段階: mutating (オブジェクトを変更できる) → validating (検査だけ)
  • 読み取りのリクエスト (get、list、watch) は admission を通らない
  • 有効・無効の切り替え: kube-apiserver --enable-admission-plugins=... / --disable-admission-plugins=...
  • v1.35 のデフォルト有効リストのうち CKAD に関わるもの
plugin役割
NamespaceLifecycle削除中、または存在しない namespace へのオブジェクト作成を防ぐ
LimitRangerLimitRange を適用 (デフォルトの requests/limits を注入、範囲を検査)
ResourceQuotanamespace 単位の総量制限
ServiceAccountPod に ServiceAccount・token を自動設定
PodSecurityPod Security Standards を適用
  • 「作成はできたのに Pod が立ち上がらない」ではなく「作成そのものが拒否される」なら、admission の段階で止められた可能性が高い

RBAC

API group rbac.authorization.k8s.io/v1、オブジェクトは 4 種類。

オブジェクト範囲内容
Rolenamespace一つの namespace の中の権限ルール
ClusterRoleクラスタクラスタ範囲のリソースの権限、または複数の namespace で使い回すルール
RoleBindingnamespaceRole か ClusterRole を subject に結び付ける。効果はその namespace の中に限定
ClusterRoleBindingクラスタClusterRole をクラスタ全体に結び付ける
  • subject の種類: User、Group、ServiceAccount
  • binding を作った後は roleRef を変更できない。変えるなら削除して作り直す
  • 組み込みのユーザー向け ClusterRole: cluster-admin、admin、edit、view
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
  - apiGroups: [""] # "" = core API group
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
  - kind: ServiceAccount
    name: my-sa
    namespace: default
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ServiceAccount

  • 人ではないアカウント。Pod の中のプロセスが API server にアクセスするときの身元
  • namespace ごとに default ServiceAccount が自動で作られる。消しても control plane が作り直す
  • default ServiceAccount には、RBAC 上 API discovery 以外の権限がない
  • Pod への指定: spec.serviceAccountName
    • 既存の Pod の serviceAccountName は変更できない。Deployment などは template を変えて新しい Pod に入れ替える
    • spec.serviceAccount は deprecated な alias
  • token
    • v1.22 から、TokenRequest API で取得した短命・自動更新の token を projected volume としてマウント
    • パス: /var/run/secrets/kubernetes.io/serviceaccount/ (token、ca.crt、namespace)
    • 手動発行: kubectl create token <sa> (--duration で有効期間を要求)
  • 自動マウントをオフにする: automountServiceAccountToken: false
    • ServiceAccount と Pod の両方に書けて、両方にあれば Pod 側が優先
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-sa
  namespace: default
automountServiceAccountToken: false
---
apiVersion: v1
kind: Pod
metadata:
  name: api-client
  namespace: default
spec:
  serviceAccountName: my-sa
  automountServiceAccountToken: true # Pod の設定が優先
  containers:
    - name: app
      image: busybox:1.28
      command: ["sh", "-c", "sleep 1h"]

SecurityContext

Pod・container がノード上でどのユーザー・権限で実行されるかを決める設定。RBAC と違って API の権限とは関係ない。

  • 場所
    • Pod レベル: spec.securityContext、すべての container に適用
    • container レベル: spec.containers[].securityContext
    • 両方あれば container レベルが上書き
フィールドPodcontainer意味
runAsUser / runAsGroupOOプロセスの UID / 基本 GID
runAsNonRootOOtrue なら UID 0 で実行しようとすると kubelet が起動を拒否
seccompProfileOORuntimeDefault、Localhost、Unconfined
fsGroupOXvolume の所有グループ
supplementalGroupsOX追加のグループ
sysctlsOXPod の sysctl
capabilitiesXOLinux capability の add/drop
readOnlyRootFilesystemXOroot filesystem を読み取り専用に
allowPrivilegeEscalationXOsetuid などによる権限昇格を許すか (no_new_privs)
privilegedXOprivileged モード
  • allowPrivilegeEscalation: container が privileged か CAP_SYS_ADMIN を持っていれば常に true
  • capability 名は CAP_ 接頭辞なしで: CAP_SYS_TIME → SYS_TIME
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  volumes:
    - name: tmp
      emptyDir: {}
  containers:
    - name: app
      image: busybox:1.28
      command: ["sh", "-c", "sleep 1h"]
      volumeMounts:
        - name: tmp
          mountPath: /tmp # readOnlyRootFilesystem のときの書き込み先
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
          add: ["NET_BIND_SERVICE"]

Pod Security Standards

Pod のセキュリティレベルを三段階のポリシーとして定義したもの。強制は PodSecurity admission controller (Pod Security Admission) が担当する。

レベル内容
Privileged制限なし。既知の権限昇格も許可
Baseline既知の権限昇格をブロック。デフォルト (最小限の指定) の Pod 設定は許可
Restricted現在の Pod hardening の best practice に沿った強い制限

Restricted が要求する container の設定 (抜粋):

  • allowPrivilegeEscalation: false
  • runAsNonRoot: true、runAsUser は 0 禁止
  • capabilities.drop に ALL、add は NET_BIND_SERVICE のみ
  • seccompProfile.type: RuntimeDefault か Localhost (未指定・Unconfined は不可)
  • volume の種類の制限: configMap、csi、downwardAPI、emptyDir、ephemeral、persistentVolumeClaim、projected、secret

namespace のラベルで適用:

apiVersion: v1
kind: Namespace
metadata:
  name: secure-ns
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted
mode違反したとき
enforcePod を拒否
auditaudit log に annotation を追加、許可
warnユーザーに警告、許可

紛らわしいものの比較

項目AB
401 vs 403401: authentication の失敗 (誰なのかわからない)403: authorization の拒否 (誰かはわかるが権限がない)
authorization vs admissionリクエストの属性 (user、verb、resource) だけを見て判断オブジェクトの中身 (フィールドの値) まで見て変更・拒否。読み取りのリクエストは対象外
Role vs ClusterRolenamespace の範囲クラスタの範囲。RoleBinding で一つの namespace にだけ付けることもできる
RoleBinding + ClusterRole効果は RoleBinding の namespace の中に限定ClusterRoleBinding なら全 namespace
RBAC vs SecurityContextAPI server に対する権限ノード上でプロセスが持つ権限
runAsNonRoot vs runAsUser条件の検査 (root なら実行を拒否)実際の UID を指定
privileged vs capabilities事実上ホストレベルの権限すべて必要な capability だけを選んで add/drop
Pod vs container の securityContext共通のデフォルト、fsGroup など Pod 専用のフィールド上書き、capabilities など container 専用のフィールド

試験のポイント

imperative なコマンド

# ServiceAccount
kubectl create serviceaccount my-sa -n dev
kubectl set serviceaccount deployment/web my-sa -n dev
kubectl create token my-sa -n dev

# RBAC
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n dev
kubectl create rolebinding pod-reader-binding --role=pod-reader \
  --serviceaccount=dev:my-sa -n dev
kubectl create clusterrole secret-reader --verb=get,list,watch --resource=secrets
kubectl create rolebinding view-binding --clusterrole=view \
  --serviceaccount=dev:my-sa -n dev

# 権限の確認
kubectl auth can-i list pods -n dev --as=system:serviceaccount:dev:my-sa
kubectl auth can-i --list -n dev --as=system:serviceaccount:dev:my-sa

# Pod Security Admission
kubectl label namespace secure-ns pod-security.kubernetes.io/enforce=restricted
  • SecurityContext には imperative なフラグがない。kubectl run ... --dry-run=client -o yaml で骨組みを作ってから YAML に追加

kubectl explain

kubectl explain pod.spec.securityContext                          # Pod レベル: runAsUser、fsGroup など
kubectl explain pod.spec.containers.securityContext               # container レベル: capabilities、readOnlyRootFilesystem など
kubectl explain pod.spec.containers.securityContext.capabilities  # add、drop
kubectl explain pod.spec.automountServiceAccountToken
kubectl explain role.rules                                        # apiGroups、resources、verbs
kubectl explain rolebinding.subjects                              # kind、name、namespace

参考ドキュメント