4C — 外側の層は内側の層を救ってくれない
一言でいうと
Cloud → Cluster → Container → Code。この4つの層は、外側が内側を包みますが、内側の代わりにはなりません。 クラウドのファイアウォールが完璧でも、コードに認可チェックがなければ、正規のユーザーが他人のデータを見てしまいます。
なぜ必要なのか
「セキュリティを強化しよう」という言葉は、どの方向も指していません。ファイアウォールをさらに絞るのか、RBACを見直すのか、 イメージをスキャンするのか、コードレビューを増やすのか。すべてセキュリティですが、防げる脅威はまったく違います。
4Cモデルはこの混乱を整理します。各層が何を防げるのか、そして何は原理的に防げないのかを はっきりさせてくれるからです。
どう動くのか
4つの層とそれぞれの守備範囲
| 層 | 統制手段 | ここで防げるもの | ここでは防げないもの |
|---|---|---|---|
| Cloud/インフラ | ネットワーク境界、IAM、ノードOS、物理セキュリティ | インターネットからapiserverやetcdへ直接接続されること | 正当な認証情報を持つ内部関係者 |
| Cluster | 認証/認可(RBAC)、アドミッション、ネットワークポリシー、監査ログ | 権限のないAPI呼び出し、危険なPodスペック | 権限の範囲内で起きる誤用・悪用 |
| Container | イメージの出所・スキャン、最小権限での実行、読み取り専用ルート | 脆弱なベースイメージ、root実行 | アプリケーションロジックの欠陥 |
| Code | 認可チェック、入力検証、Secretの扱い、依存関係管理 | IDOR、インジェクション、ハードコードされたキー | 上の層の設定ミス |
なぜ外側は内側を救えないのか
理由は3つあります。
1つ目は、外側の層はリクエストの意味を知らないことです。クラウドのファイアウォールが見るのは、
「誰がどこへTCPを開いたか」までです。正規にログインしたユーザーがGET /v1/orders/10422を呼んだとき、それが自分の注文なのか
他人の注文なのかを、ファイアウォールは判断する根拠を持ちません。その判断に必要な情報はデータベースにあるからです。
2つ目は、内側の層の欠陥は、外側の層からは正常なトラフィックに見えることです。IDOR攻撃のリクエストは認証も 通過し、レスポンスコードも200です。失敗したリクエストが1つもないので、アラートも鳴りません。
3つ目は、層が互いの前提に依存していることです。コンテナをどれだけ最小権限で動かしても、ノードが 乗っ取られればそのノード上のすべてのコンテナが一緒に奪われます。逆にノードが堅牢でも、コードが認証情報を ログにダンプすれば、その値はログのインデックスへ流れていきます。
では、どう使うのか
4Cは「全部やろう」ではなく、「この脅威はどの層で防ぐのが最も安く確実か」を問うための道具です。
- インターネットからetcdの2379ポートが開いている → Cloud層の問題です。ファイアウォールで閉じるのが正解で、 etcdの認証を強化するのは次善策です。
- 開発者が本番のSecretを読める → Cluster層(RBAC)の問題です。コードでは防げません。
- Podがrootで動いている → Container層の問題です。PSAやアドミッションで防ぎます。
- 他人の注文書が見える → Code層の問題です。どんなインフラ統制でも防げません。
現場での姿
著者のホームラボで、4Cの層の依存関係がそのまま表に出た出来事がありました。
DHCPの更新でコントロールプレーンノードのIPが.111から.120に変わると、クラスター全体が止まりました。
IPアドレスの割り当てというCloud/インフラ層の出来事1つが、Cluster層を丸ごと無力化したのです。
もっと正確にいえば、問題は証明書でした。apiserver.crtのSubject Alternative Nameに.111だけが
あり、.120がありませんでした。TLSの信頼がIPに結び付いていたため、インフラ層でアドレスが1つ
変わっただけで、クラスター層の身元の仕組みが壊れたのです。
同じクラスターを7ノードに増やしたあとにも、似た教訓が得られました。etcdメンバー3つでクォーラムを確保していましたが、
controlPlaneEndpointがcp-1の物理IPに固定されていたため、cp-1が落ちるとデータは安全なのに
誰も接続できなくなりました。「データの可用性とアクセスの可用性は別物」という、これも層が互いを
代わりに守れないという同じ話です。
続けて読むこと
続く読み物では、各層の攻撃対象領域を具体的なエントリーポイントの一覧として広げていきます。 次のモジュールからはCluster層に下りて、apiserver・etcd・kubeletを1つずつ分解していきます。