AWS
PR

EKS で aws-auth から system:masters を消しても管理者権限が残る理由

saratogax
記事内に商品プロモーションを含む場合があります

EKS で aws-auth ConfigMap から system:masters のエントリを削除したのに、まだ管理者としてクラスタに入れてしまう。

あるいは逆に、aws-auth を見ても管理者が見つからないのに、誰かが管理者権限で操作できている。

こうした食い違いに出会ったら、EKS には aws-auth に一切現れない管理者が存在することを思い出してください。

クラスタを作成した IAM プリンシパルです。

この主体には system:masters が自動付与されており、しかも aws-auth では管理されていません。

そのため aws-auth をどう編集しても、その権限は消えません。

本記事では、この仕様の詳細と、kubectl auth whoami による判定手順、そして認証モードによって剥奪できるかどうかが変わる点を解説します。

クラスタ作成者には管理者権限が自動付与される

AWS のドキュメントには、はっきりこう書かれています。

クラスタを作成した IAM エンティティ(ユーザーまたはロール。フェデレーションユーザーを含む)には、クラスタの RBAC 設定において system:masters 権限が自動的に付与される。

そして重要なのが、次の一文です。

「このアクセスは削除できず、aws-auth ConfigMap を通じて管理されない」(This access cannot be removed and is not managed through the aws-auth ConfigMap.)

つまり、棚卸しの対象として aws-auth を見ても、この主体は原理的に出てきません。

別のドキュメントでは「このプリンシパルはいかなる可視の設定にも現れないため、どのプリンシパルが元々クラスタを作成したかを把握しておくこと」とも注意されています。

なお system:masters グループは、デフォルトで cluster-admin ClusterRole にバインドされています。

実質的にクラスタの全権限です。

なぜ ConfigMap に載せない設計なのか

一見すると不透明な仕様ですが、理由があります。

aws-auth を編集ミスした場合、すべての IAM ユーザー・ロールがクラスタから恒久的にロックアウトされる危険があります。

作成者の権限を ConfigMap の外に置いておけば、最後の生命線として機能します。

実際 AWS は「クラスタ作成者を ConfigMap に追加しないこと」をベストプラクティスとしています

ドキュメントの表現では、この権限は「ブレークグラス(緊急時の最終手段)」として確保しておくべきものと位置づけられています。

権限を剥奪する場面で何が困るか

私がこの仕様に向き合ったのは、「Kubernetes API の権限と到達経路を棚卸しし、不要な強権限を剥奪する」という調査でした。

そこで問題になったのが、剥奪してよいかどうかの判断です。

具体的には、CI 用のロールが aws-auth 上で system:masters を持っており、これを剥奪したいという状況でした。

ここで怖いのが「剥奪した結果、誰もクラスタに入れなくなる」という事故です。

aws-auth だけを見ていると、管理者エントリが他に無いように見えるケースがあります。

その状態で剥奪すれば、管理者アクセスがゼロになるように見えてしまいます。

しかし実際には、運用担当者は暗黙の admin 経路で入れていました。

この経路は aws-auth に依存しないため、ConfigMap をどう変更しても影響を受けません

逆のパターンも起こりえます。

「棚卸しが終わった、管理者は N 人だ」と報告した後で、実は台帳に載っていない全権限の主体がいた、という漏れです。

どちらの向きでも、aws-auth だけを根拠にすると判断を誤ります。

判定手順 1:kubectl auth whoami で確かめる

では、ある IAM ロールが暗黙の admin かどうかをどう判定するか。

最も直接的なのは、そのロールを assume したセッションで kubectl auth whoami を実行することです。

kubectl auth whoami

実際の出力例です(値は一部ダミーに置き換えています)。

Username   kubernetes-admin
Groups     [system:masters system:authenticated]
Extra: canonicalArn   arn:aws:iam::111122223333:role/example-operator-role
Extra: sessionName    example_user
UID        aws-iam-authenticator:111122223333:AROAEXAMPLEID

ここから 3 つのことが読み取れます。

  • Username が kubernetes-adminaws-auth 経由ではありません。ConfigMap でマッピングされた主体なら、そこで定義した username(例: ci-runner)やノードの system:node:... が出ます
  • Groups に system:masters → クラスタ管理者として通っています
  • Extra: canonicalArn → 実際に assume している IAM ロールの ARN。どの主体としてクラスタに入っているかが特定できます

この 3 点が揃えば、aws-auth を経由せず system:masters を持っていると確定できます。

つまり暗黙の cluster creator admin です。

この判定は剥奪作業の前後で実行すると、さらに効果的です。

私は aws-auth から CI 用ロールを削除した前後で kubectl auth whoami の出力が変わらないことを確認し、管理者アクセスが維持されていることをライブで実証しました。

kubectl auth whoami は SelfSubjectReview API を使います。この API は Kubernetes 1.26 でアルファ、1.27 でベータ、1.28 で GA になりました。1.28 以降のクラスタなら追加設定なしで動きます。kubectl auth whoami | Kubernetes

判定手順 2:CloudTrail で作成者を特定する

kubectl auth whoami は「今入れている自分」を確認する手段です。

一方、棚卸しでは「そもそも誰がこのクラスタを作ったのか」を知りたい場面があります。

可視の設定に現れないので、CloudTrail の CreateCluster イベントを探すことになります。

userIdentity セクションを見れば、作成した IAM プリンシパルが分かります。

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateCluster \
  --query 'Events[].{Time:EventTime,User:Username}' \
  --output table

ただし注意点があります。

CloudTrail のイベント履歴は 90 日しか保持されません。

数年前に作られたクラスタでは、この方法では追えないことになります。

長期保管用の Trail を S3 に出していれば、そちらを Athena で検索する手が残ります。

そうした備えが無い場合は、kubectl auth whoami で「現に入れる主体」を確認していく実測アプローチのほうが現実的です。

私のケースでは、対象クラスタの中には aws-authcreationTimestamp が 6 年以上前のものもあり、CloudTrail では到底追えませんでした。

認証モードによって「剥奪できるか」が変わる

ここが実務上もっとも重要な分岐点です。

EKS の認証モード(authenticationMode)には 3 種類あり、暗黙 admin の扱いが変わります。

認証モード権限管理の方法作成者の admin 権限
CONFIG_MAPaws-auth ConfigMap のみ剥奪できない
API_AND_CONFIG_MAPAccess Entries + ConfigMap剥奪・辞退が可能
APIAccess Entries のみ剥奪・辞退が可能
※表は横スクロールできます

古いクラスタは CONFIG_MAP のままのことが多く、この場合暗黙 admin は剥奪できません

ドキュメントにも「CONFIG_MAP 認証方式に依存している場合、このアクセスは剥奪できない」と明記されています。

棚卸しの報告書では、ここを「対応不可の残存リスク」として正直に書くしかありません。

Access Entries なら剥奪できる

API または API_AND_CONFIG_MAP モードであれば、作成者の cluster-admin 権限を剥奪できます。

付与されているポリシーの関連付けを外す形です。

aws eks list-associated-access-policies \
  --cluster-name <CLUSTER_NAME> \
  --principal-arn <IAM_PRINCIPAL_ARN>

aws eks disassociate-access-policy \
  --cluster-name <CLUSTER_NAME> \
  --principal-arn <IAM_PRINCIPAL_ARN> \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy

新規クラスタであれば、作成時点で暗黙 admin を辞退するという選択もできます。

aws eks create-cluster \
  --name <CLUSTER_NAME> \
  --access-config authenticationMode=API_AND_CONFIG_MAP,bootstrapClusterCreatorAdminPermissions=false

bootstrapClusterCreatorAdminPermissions=false が、その辞退のフラグです。

モード変更は一方通行

既存クラスタのモードは update-cluster-config で変更できますが、この操作は元に戻せません。

CONFIG_MAP から API にしたい場合は、まず API_AND_CONFIG_MAP を経由する必要があります。

そして APIAPI_AND_CONFIG_MAPAPI_AND_CONFIG_MAPCONFIG_MAP という逆方向はできません。

棚卸しの流れで軽々に踏むべき操作ではないので、別タスクとして計画したほうが安全です。

なお CONFIG_MAP モードのクラスタで Access Entries を確認しようとすると、次のように弾かれます。

aws eks list-access-entries --cluster-name <CLUSTER_NAME>
# → InvalidRequestException

これはエラーではなく「Access Entries を使っていない」ことの確認結果です。

逆に API 系モードのクラスタでは、aws-auth と Access Entries の両方を棚卸ししないと網羅できません。

棚卸しのチェックリスト

ここまでを踏まえた、実務用の手順です。

  1. 認証モードを確認するaws eks describe-clusteraccessConfig.authenticationMode。これで以降の調査範囲と、剥奪可否が決まります
  2. aws-auth を棚卸しするmapRoles / mapUsers の明示エントリ
  3. Access Entries を棚卸しするAPI 系モードの場合のみ。aws eks list-access-entries
  4. 暗黙 admin を洗い出す。運用担当者が assume するロールで kubectl auth whoami。Username が kubernetes-admin なら該当
  5. 剥奪の前後で kubectl auth whoami を実行する。管理者アクセスが維持されることをライブで確認

4 番が本記事の要点です。

そして環境が複数ある場合は、環境ごとに実測してください

私が調べた環境では、暗黙 admin となっているロールがクラスタごとに異なっていました。

作成した時期も担当者も違えば、当然そうなります。

さらに、あるクラスタでは運用ロールが aws-auth に明示登録されていました

つまり「暗黙 admin を持たないロールを、明示的に管理者として登録した」正当なエントリです。

これを「不要な強権限」と誤認して剥奪すると、そのクラスタだけ管理者を失う事故になります。

同じ組織のクラスタでも構成は揃っていない、という前提で臨むのが安全です。

設計時の推奨事項

これから EKS クラスタを作る立場であれば、AWS の推奨に沿っておくと後の棚卸しが楽になります。

  • 専用の IAM ロールでクラスタを作成する。個人のユーザーやフェデレーションユーザーで作ると、その人が暗黙 admin として残り続けます
  • そのロールを日常運用に使わない。ブレークグラス専用として封印し、誰が assume できるかを定期的に監査します
  • 作成は自動化パイプラインに紐づける。他の主体が assume できない専用ロールをパイプラインに持たせる形が推奨されています
  • API 系モードを選び、必要なら作成時に辞退するbootstrapClusterCreatorAdminPermissions=false で最初から作らない選択もできます

ちなみに aws-auth ConfigMap 自体、AWS のドキュメント上で非推奨(deprecated)と明記されるようになりました。

今後は Access Entries が正道になります。

移行する際は、aws-auth のエントリが自動移行されない点に注意してください。

Access Entries を有効化したとき自動作成されるのは元のクラスタ作成者の分だけで、ConfigMap に足した他のロールは手動で作り直す必要があります。

まとめ

  • EKS のクラスタ作成者には system:masters が自動付与され、aws-auth には一切現れない
  • 判定は kubectl auth whoamiUsername が kubernetes-admin かつ Groups に system:masters なら暗黙 admin
  • 作成者の特定は CloudTrail の CreateCluster だが、履歴は 90 日なので古いクラスタでは追えない
  • CONFIG_MAP モードではこの権限を剥奪できないAPI 系モードなら Access Entries で剥奪・辞退が可能
  • モード変更は一方通行。棚卸しの流れで軽々に踏まない
  • クラスタごとに構成は違う。環境ごとに実測する

「棚卸しした」と言うためには、可視の設定に載っていないものまで数える必要がありました。

強権限の剥奪という緊張する作業でも、kubectl auth whoami という 1 コマンドで前後を比較できると、判断にかなりの自信が持てます。

あわせて読みたい(EKS 運用)

ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました