re:Invent 2023: AWSによるAmazon EKSのKubernetesワークロードセキュリティ強化
はじめに
海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!
📖 AWS re:Invent 2023 - Securing Kubernetes workloads in Amazon EKS (CON335)
この動画では、Amazon EKSにおけるKubernetesワークロードのセキュリティ確保について詳しく解説します。クラスターへのアクセス保護、クラスター内外のアクセス制御、そしてNetwork Policiesの実装など、最新の機能を紹介します。特に注目すべきは、近日リリース予定のCluster Access ManagementとEKS Pod Identityです。これらの機能により、IAM権限の管理やクラスターアクセスの設定が大幅に簡素化されます。セキュリティと使いやすさを両立させたEKSの進化を、具体的なデモを交えて学べる内容です。
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。本編
Amazon EKSにおけるKubernetesワークロードのセキュリティ確保:セッション概要
皆さん、おはようございます。ラスベガスへようこそ。私はAmazon EKSチームのPrincipal Software EngineerのMicah Hauslerです。私はGeorge John、Amazon EKSチームのSenior Product Managerです。本日はご参加いただき、ありがとうございます。
これはCON335、Amazon EKSにおけるKubernetesワークロードのセキュリティ確保についてのセッションです。今日は、セキュリティについてお話しします。セキュリティの最も古い形態といえば、おそらく出入り口やドアを思い浮かべるでしょう。時には物事を外に置いておきたいこともあれば、中に閉じ込めておきたいこともあります。今日の話では、この入口管理というテーマを通して、セキュリティについての議論を展開していきます。
それでは、アジェンダを見ていきましょう。大きく3つのパートに分かれています。Kubernetesクラスターへのアクセスの保護、クラスターからのアクセスの保護、そしてクラスター内でのアクセスの保護について話し合います。これらが今日の議論の主なポイントとなります。
Kubernetesと Amazon EKSの基本概念
ちょっと手を挙げていただけますか。KubernetesやEKSを使っている方、または使ったことがある方はどのくらいいらっしゃいますか? ほとんどの方ですね。素晴らしい。Kubernetesに馴染みがない方のために、簡単に説明しますと、Kubernetesはコンテナオーケストレーターです。つまり、コンピュート上でコンテナを制御してスケジューリングします。EKSの場合、それはEC2インスタンスやAWS Fargateになります。これらを使って、自社開発のアプリケーションやベンダーのアプリケーションなど、さまざまなアプリケーションを実行できます。これらは多くの場合、Amazon S3やAmazon RDS、Amazon Bedrockなど、他のAWSサービスと連携します。これがKubernetesの概要と、その仕組みの大まかな説明です。
Amazon EKSのCluster Access Management:新機能の紹介
さて、紀元前1250年頃の古代ギリシャにいると想像してみてください。あなたは都市の最も重要な部分であるアクロポリスの防衛を任されました。どうしますか?おそらく、このようなものを建設するでしょう。これは、ミケーネのギリシャにあるライオンゲートの写真です。見てみると、巨大な石で強化された大きな壁と、閉じることができる門があります。当時としては、かなり最先端のものでした。実際、約1000年後にギリシャ人がこれを見たとき、巨人によって建てられたと考えたほどです。
時を3,300年進めて西暦2018年、Amazon EKSがローンチされました。ご想像の通り、EKSクラスターのフロントゲートを守ることは同様に重要でした。当時私たちが取った手法は、クラスターを保護するための非常にKubernetesネイティブでオープンソースな方法でした。これは、KubernetesのパーミッションとIAMを使用して、ConfigMapを通じてマッピングを定義し、誰が何にアクセスできるかを決定できることを意味しました。
この手法にはトレードオフがありました。一方では、IAMを使用できるため、別のアイデンティティプロバイダーを作成する必要がありませんでした。IAMとKubernetes RBACを使ってアクセスを設定できるため、CloudTrailによる監査可能性や多要素認証など、IAMのすべての利点も得られました。しかし、この手法に関して、お客様から使い勝手の課題についてフィードバックをいただいていました。
お客様から聞いた一つの点は、クラスターにアクセス権を設定するために複数のAPIを使用しなければならないということです。まずEKS管理APIを使ってクラスターを作成し、準備が整うのを待ってから、Kubernetes APIを使ってConfigMapでIAMプリンシパルとKubernetesのパーミッションの間のマッピングを定義します。つまり、インフラストラクチャ・アズ・コードのようなツールを使って、必要なアクセス権を持つクラスターを一度に立ち上げる自動化が実質的にできないのです。
もう一つのフィードバックは、全体的な体験がややこしいということです。タイポがないように気をつけ、すべてのマッピングが想定通りであることを確認しなければなりません。もし間違えると、ロックアウトされる可能性があります。アクセスを回復する方法はありますが、理想的な体験とは言えません。最後に、クラスターを作成すると、作成したIAMプリンシパルに自動的にKubernetesパーミッションのスーパーユーザー権限が付与されます。何らかの理由でそのIAMプリンシパルを削除すると、ロックアウトされる可能性があります。
信じられないかもしれませんが、EKSにはGitHubで公開されているロードマップがあります。多くのお客様から、この体験が理想的ではないというフィードバックをいただいています。しかし、朗報があります。
Amazon EKSから、Cluster Access Managementという新機能が近々リリースされる予定です。これにより、ほとんど、もしくはすべての問題が解決されるでしょう。ここでMicahに引き継いで、APIや構築方法、そして簡単なデモについて説明してもらいましょう。
Cluster Access ManagementのAPI機能と使用方法
ありがとうございます。私たちはこのCluster Access Management機能にとてもワクワクしています。近々リリースされる予定です。主な特徴としては、AWS APIを提供することです。 Georgeが説明したように、現在はKubernetes APIにこのconfig mapがあります。クラスターを作成する際、AWS EKS APIにアクセスし、AWS認証情報を使用してそれと通信する必要があります。その後、完全に異なるAPIに切り替えて、Kubernetes APIのファイルを編集する必要があります。この新機能では、AWS ネイティブAPIを使用するため、Infrastructure as Codeツールとの相性が抜群です。また、クラスターの作成時のアクセスも大幅に簡素化されます。クラスターの作成が完了する前でもエントリーを追加できるので、クラスターの作成を待ってからパーミッションのブートストラップを開始する必要がなくなります。
また、きめ細かな制御も可能です。クラスター作成者にパーミッションを与え、そのアイデンティティがクラスター内のパーミッションを編集することを期待する代わりに、これらはすべてEKS APIで保護されています。それらに関するパーミッションがあり、クラスターへのアクセスを編集できる人物に関するIAMポリシーをすべて設定できます。 こちらは、マネジメントコンソールでの表示の簡単なスクリーンショットです。クラスターを作成する際、クラスターアクセスを設定し、クラスター作成者に何らかのパーミッションを与えるかどうかを決定できます。Infrastructure as Codeによる自動化でクラスターへのアクセスが不要な場合もあるでしょう。
クラスター作成後、このマネジメントAPIに追加のエントリーを加えたい場合は、ここで追加できます。これは別の表示例です。 さらに、粗粒度のポリシーアクセスも提供する予定です。これについては後ほどデモでお見せします。基本的に、クラスターにアクセスできるこれらのアイデンティティに対して、ある程度のパーミッションをブートストラップできます。認証と認可の2つの部分があります。前半は認証部分で、誰がクラスターに対して認証できるかを決定します。後半は認可部分で、クラスター内でどのレベルのアクセス権を持つかを決定します。
このAPIがどのように見えるかというと、AWS CLIに慣れている方なら、クラスターを作成して認証モードを設定します。これは後ほどデモでお見せします。アクセスエントリーを作成し、それらをポリシーに関連付けることができます。作成後も、いつでも更新が可能です。 では、すぐにデモに移って、どのように見えるかをお見せしましょう。
Cluster Access Managementのデモンストレーション
ここに作成したクラスターがあります。このAPIがどのように見え、どのように機能するかを説明していきます。 まず、特定のconfig fileを使用するための設定をしています。クラスターの説明をします。クラスターを説明する際に最初に気づくのは、クラスターに関する多くの設定が表示されることです。おそらくendpointには馴染みがあると思いますが、authentication modeという新しいフィールドを追加しています。このクラスターにはすでにAPIとconfig mapが設定されています。
既存の方法をご存知の方は、クラスター内のconfig mapを見ると、定義されたroleがconfig map内に表示されることをご存知でしょう。この場合、managed node groupを使用しました。すでにそれを接続しており、EKS APIを使用すると、自動的にこのエントリーがAWS auth config mapに追加されます。つまり、基本的にはEKSが生成した空のconfig mapということになります。
先ほど示したように、クラスターのconfigを更新できます。3つの異なるmodeがあります。既存のクラスターを持っているか、新しいクラスターを作成する場合、デフォルトのmodeはconfig mapになります。つまり、見た目や感覚は同じです。クラスターへのアクセス権を持つ人に対する制御や、クラスターへのアクセスを管理している場合、それは変わりません。この新しい方法がありますが、デフォルトでは有効になっていません。有効にする必要があります。2つ目のmodeは、このAPIとconfig mapのmodeで、EKS APIのエントリーと、config mapの両方を参照します。これは一種の移行フェーズです。そして最後のmodeは、API onlyで、新しいEKS APIのみを使用してクラスターへのアクセスを設定します。
このクラスターはすでに更新済みなので、このcallは失敗しますが、APIとconfig mapがクラスターに送信されるのが分かります。
次に、access entriesをリストアップします。このクラスターには2つあります。 このクラスターを作成したとき、EKSは自動的にcluster creatorを追加し、ノードのnode roleをAPIに追加しました。これらのaccess entriesを詳しく見ることができます。 adminやcluster creator roleを見ると、principal identityとARNが表示されます。同様にnode roleも確認できます。ここでの重要な違いはtypeです。EC2 Linuxと表示されているのが分かります。 EKSでは異なるノードに異なる権限レベルがあるため、permissionsの追加設定管理を行っています。例えば、WindowsノードはEC2 Linuxノードとは少し異なる権限セットを持っています。そこで表示されているtypeがそれです。しかし、ほとんどの人間ユーザーや他のマシンユーザーの場合は、標準的なtypeになります。
ここで、クラスターをconfig mapのみにロールバックしようとすると、実際には失敗することを説明したいと思います。APIにそれらのエントリが必要なため、config mapへのロールバックはサポートしていません。このデモで使用しているAWS設定ファイルを簡単に紹介します。ここには、異なるロールがクラスターにアクセスし、異なる権限レベルを持つことを示すために、いくつかの異なるプロファイルがあります。クラスターを作成するために使用するベースロールがあります。現在、これはクラスター内の管理者です。また、cluster adminとcluster viewerと呼んでいる追加のロールもあります。
EKS Pod Identity:クラスター内からの外部リソースアクセスの新しい保護方法
新しいアクセスエントリを作成したい場合は、単にAPIを呼び出すだけです。この機能がリリースされたら、Infrastructure as Codeやその他の方法でこれを行うことができます。ここで、viewerのアクセスエントリを作成しました。現在、クラスター内に権限はありません。Kubernetesから組み込みのクラスターロールを説明したい場合、これらはKubernetesのRole-Based Access Control(RBAC)におけるクラスターレベルの権限です。サービスアカウントで使用されるすべてのシステムロールをフィルタリングします。実際には4つだけです:下位レベルの管理者であるadmin、完全なクラスター管理者、editorロール、そしてviewerロールです。
EKS APIで、これら4つのKubernetesロールにほぼ類似したアクセスポリシーを作成します。先ほど述べたように、これらは粗粒度のポリシーで、クラスターへの表示アクセス、編集アクセス、または管理者アクセスを誰かに与えるためのブートストラップ機能を提供します。RBACを使用したい場合は、これらを全く使用する必要はありませんし、RBACと併用することもできます。ここに、ローンチ時に提供予定のポリシーのリストがあります。これらはRBACポリシーに似ていますが、追加のものも見られます。例えば、nodesやEMRなどです。
この新しいAPIは、人間やクラスターにアクセスする必要がある他の自動化だけでなく、クラスターにアクセスする必要がある他のAWSサービスにも使用されます。したがって、クラスターへのアクセスを記述すると、例えばEKSでEMRを使用している場合、このロールとこのポリシーを使用していることがわかります。ここで、アクセスポリシーを関連付けることができます。先ほどのviewerロールをEKS viewポリシーに関連付けます。次に、AWS profileをviewerのIAMロールを使用するように切り替えます。get caller identityを実行して、自分が誰で、どのロールなのかを確認できます。今、実際にviewerロールになっており、クラスター作成者ではありません。これを使用して、すべての名前空間のすべてのポッドを取得しようとしてみましょう。素晴らしい、できました。クラスター管理者ではありませんが、今はクラスターにアクセスできます。
しかし、viewerロールポリシーに含まれていない変更を試みると、例えば、Kubernetesコマンドラインを使用してリテラルからconfig mapを作成しようとすると、つまりconfig mapにキーと値を設定しようとすると、実際には失敗します。このユーザーにはconfig mapを作成する権限がありません。クラスターを作成した管理者ロール(baseプロファイルと呼んでいます)に戻ると、クラスター設定をAPIに更新できます。これは進行中で、まだポッドを取得できます。以上がデモです。
では、これはどのように内部で動作するのでしょうか? EKSに詳しい方なら、AWS IAM authenticatorというオープンソースプロジェクトを使用していることをご存知かもしれません。これはGitHubにあり、私も貢献者の一人です。
AWSの他のスタッフも維持管理を手伝っています。仕組みとしては、KubernetesのクライアントであるあなたがKubernetesに呼び出しを行う際、bearer tokenを送信します。 そのトークンはKubernetesによって解釈され、「このトークンの扱い方は分からないが、EKSが管理するIAM authenticator認証webhookが有効になっていることは分かっている」と判断します。そして、このwebhookがそのトークンの処理方法を知っているのです。
ここでトークンと呼んでいるものは、実際には先ほどお見せしたget caller identity APIに対する事前署名されたSigV4リクエストです。クライアントとしてget call identityを呼び出すと、AWSから返ってくるレスポンスがあなたの身元となります。このURLを事前署名すると、Amazon S3の事前署名URLと同様に、他の人に自分の認証情報を渡すことなく、その署名が有効な期間中、特定のオブジェクトにアクセスできるようになります。同じ原理で、get call identityのURLを事前署名して他の人に渡せば、その人はそのコールだけを実行して、あなたの身元を確認できるのです。
AWS IAM authenticatorはこのリクエストを実行し、 Secure Token Service(STS)に対して送信して、クライアントが誰であるかを確認するレスポンスを受け取り、それをKubernetes APIに返して「これがユーザーの身元です」と伝えます。config mapモードでは、これまでの仕組みでは、IAM authenticatorプロセスがauth config mapを参照して、「STSからこのようなレスポンスを受け取ったが、このクラスター内でどのような権限があるか」を確認し、そしてKubernetesにこのユーザーの身元を伝えます。
ここで重要な違いは、APIとAPI config mapモードを導入するにあたり、Amazon EKS APIもこの真実のソースになるということです。そして、私たちが管理するKubernetesコントロールプレーンに、あなたが送信したそれらのレコードをディスク上のファイルにプッシュダウンします。 これにより、authenticatorはそのコンテキストをマージでき、APIとconfig mapモードの場合、EKS APIがconfig mapの内容よりも優先されるようになります。そして、クライアントの身元をAPIサーバーに送り返します。APIモードのみの場合は、当然ながらconfig mapを無視し、APIを通じてディスクに同期されたファイルからのみ読み取ります。
EKS Pod IdentityのIAMロールとポリシー設定
さて、これまでクラスターへのアクセス、つまりクラスターの正面玄関をどのように保護するかを見てきました。次のセクションでは、クラスター内部から外部のリソースへのアクセスをどのように保護するかを見ていきます。これはフロリダ州キーウェストの海岸から68マイル離れたフォートジェファーソンの写真です。ここで少し歴史をご紹介しましょう。出口を確保したり、人々が施設から出られないようにしたりする施設を建設する任務を与えられたら、水に囲まれた島がいい場所だと分かるでしょう。この施設には、リンカーン大統領の暗殺者を助けたサミュエル・マッド博士が、19世紀半ばにこの施設が連邦刑務所だった時期に、しばらくの間収監されていました。
Amazon EKSに話を戻しましょう。クラスター内部からアプリケーションが外部のリソースにアクセスする際、そのアクセスをどのように保護・制御するのでしょうか?この目的のために、IAM roles for service account(IRSA)という機能があります。この機能は数年前から提供されています。IRSAが登場する以前は、EC2ワーカーノード上で実行されているポッドにIAM権限を与えて他のAWSリソースにアクセスさせる方法は、EC2インスタンス自体にアタッチされたIAMロールを利用することでした。これは、同じEC2インスタンス上で実行されているすべてのポッドが、そのIAMロールが持つすべての権限を取得することを意味し、過剰な権限付与となり、最小権限の原則に違反する可能性がありました。
2019年にIRSAをリリースし、ポッドに細かなIAM権限を付与できるようになりました。これにより、同じEC2インスタンス上で実行される複数のアプリケーションに属する複数のポッドが、それぞれ異なる権限セットを持つことが可能になりました。IRSAは素晴らしい機能で、多くのお客様にご利用いただいています。ここで強調したいのは、IRSAを構築した際、EKS on AWSだけでなく、AWS上のKubernetesのために構築したということです。これがどういう意味か説明しましょう。現在、AWS上でKubernetesを実行する方法は複数あります。マネージドサービスであるEKSがあります。EKS Anywhereを使えば、オンプレミスでEKSを実行できます。また、EC2インスタンス上で独自のKubernetesクラスターを実行する、つまり自己管理型Kubernetesクラスターを運用することもできます。この場合、コントロールプレーンとデータプレーンの両方の責任を負うことになります。多くのお客様がこれを利用しています。私たちはIRSAがこれらすべての環境で動作することを望んでいたので...
IAM roles for service accounts(IRSA)を設計する際、意図的にEKS APIへの依存を避けました。代わりに、IAMのような基本的なAWSサービスを活用して構築しました。IRSAに詳しい方はご存知かと思いますが、OIDCプロバイダーなどのIAMの基本的な構成要素を使用しています。IAMでOIDCプロバイダーを作成し、作成したOIDCプロバイダーを信頼するようにロール信頼ポリシーを使用します。EKS APIとやり取りしないということは、EKS、自己管理クラスター、その他の環境でIRSAを使用できることを意味します。
しかし、お客様からユーザーエクスペリエンスに関する課題についてフィードバックをいただきました。規制産業のお客様からは、クラスター管理者が必ずしもIAMを管理する権限を持っているわけではないと指摘されました。これらのお客様にとって、IRSAのIAMロールを設定するには、IAM管理チームに連絡を取る必要があり、多くのやり取りが発生します。これにより、プロセス全体が手動で長くなり、自動化にも適していません。
IAMロールのスコーピングは2つ目の課題です。現在IRSAで使用されるロールは、クラスター自体で実行されているOIDCプロバイダーを指すトラストポリシーを持っています。新しいクラスターでロールを使用したい場合、例えばブルー/グリーンデプロイメントの一部として、新しいクラスターを指すようにロールのトラストポリシーを更新する必要があります。ロールが別のチームによって管理されている場合、これは再び理想的とは言えない経験につながります。
3つ目の課題はスケーリングです。アカウント内のクラスター数を増やすと、アカウントで作成できるOIDCプロバイダーの数やトラストポリシーのサイズなどの制限に直面する可能性があります。制限を増やしたりロールを複製したりする回避策はありますが、これらは優れたソリューションとは言えません。最後に、動的な環境を持つお客様から、すべてのアドオンと権限を1つのステップでクラスターにブートストラップしたいという声を聞いています。現在のIRSAは使用前にクラスターが準備完了状態である必要があり、これらのシナリオには理想的ではありません。
re:Inventの発表をフォローしている方々に素晴らしいニュースがあります。EKS Pod Identityと呼ばれる機能を発表しました。Micahにステージを譲る前に、IRSAを成功裏に使用している多くのお客様がいること、そして私たちはIRSAへの投資とサポートを継続することを強調させてください。AWSでは、お客様のフィードバックを真剣に受け止めており、異なるソリューションを求めるお客様のセグメントからの声を聞いています。私たちは選択肢を提供したいと考えています:IRSAは引き続き存在し、EKS Pod Identityは別のオプションとなります。ユースケースと要件に基づいて、どちらがより適しているかを決定できます。
EKS Pod Identityの実装とデモンストレーション
ありがとう、George。このローンチについて本当にワクワクしています。EKS Pod Identityの重要なポイントは、信頼関係を本当に簡素化することです。Georgeが言及したように、ロールのトラストポリシーの更新には広範な権限が必要です。Pod Identityでは、EKSを信頼してロールを正しく配布するだけで済みます。また、IAM roles for service accountsと並行して動作する後方互換性もあります。IRSAを使用している場合、Pod Identityをオンにすることができ、これはIRSAよりも優先されます。その後、必要に応じてIRSAをオフにすることができます。
私のお気に入りの機能の1つは、スケーラブルな Attribute Based Access Control(ABAC)です。IAM ロールセッションタグのサポートを追加しました。これについてはデモでご紹介します。非常に強力なセキュリティ機能です。さらに、すべてが監査可能です。この機能をサポートする新しい EKS API や、ポッドが使用する AWS API はすべて AWS CloudTrail と統合されています。
これが AWS コンソールでどのように表示されるかを簡単にスクリーンショットでお見せします。クラスターレベルに移動して、ポッドアイデンティティ設定を作成します。これにより、IAM ロールを Kubernetes の namespace とサービスアカウントに関連付けることができ、ポッドの権限管理を効率化できます。
この設定は基本的に、IAM ロールと Kubernetes の namespace、そしてその namespace 内のサービスアカウントとのマッピングです。つまり、マッピングはクラスター、ロール、namespace、サービスアカウントで構成されます。AWS コンソールでこれらの関連付けのリストも確認できます。
この仕組みの概要をお話しします。例えば、IAM 管理者がロールを作成するとします。このロールを「secret reader」と呼ぶことにしましょう。管理者はこのロールの信頼ポリシーを設定し、effect を allow にし、principal 側で pods.eks.amazonaws.com を設定します。アクションは assume role と tag session です。AWS で何らかのアイデンティティを使用したことがある方なら、EC2 や ECS、Lambda、CodeBuild などで同様の設定をしたことがあるでしょう。基本的にはこのようにサービスを信頼します。これがこの機能の重要なポイントの1つです。つまり、アイデンティティを提供したい他の AWS サービスとほぼ同じように見え、感じるということです。
このシークレットリーダーロールを使用するためには、クラスター管理者がいて、その管理者にpod identity associationを作成する権限を与える必要があるかもしれません。しかし、そのためには、クラスター管理者にpod identity associationの作成権限を与えるだけでは不十分で、IAM pass roleの権限も与える必要があります。 Pass roleは、IAMに組み込まれた重要な防御メカニズムで、権限の昇格を防ぎます。シークレットリーダーロールがEKSを信頼しているからといって、クラスター管理者がそのロールを使用できるわけではありません。そのロールに対するpass role権限も必要です。これが、この新しいAPIの主要な保護機能の一つであり、このチェックを強制し、セッションタギングがどのように機能するかを示しています。
その使用方法を、不完全な例ですが、簡単に説明します。 例えば、AWS resourceがSecrets Managerのシークレットだとします。これらのSecrets Managerのシークレットにはタグがあり、例えばタグがEKS-cluster-nameで、値がクラスターの名前だとします。K8s-namespaceやK8s-service-accountについても同様です。IAMロールセッションタグがここで活躍します。IAMポリシーでセッションタグを参照できるのです。この例のポリシーでは、条件で、リソースタグに対する文字列が、そのセッションの同じセッションタグの値と一致しなければならないと指定しています。
つまり、クラスターで使用したいIAMロールがある場合、リソース上のそれらのタグはすべてセッションタグと一致する必要があります。これの素晴らしい点は、このIAMポリシーや、さらにはIAMロールを複数のクラスターで再利用でき、クラスターごとに個別のポリシーや、ポリシー内にクラスター名をハードコードした個別のロールを作成する必要がないことです。セッションタグとリソースタグの一致に頼るだけで済みます。
結果として、コンテナがあり、例えば黄色のクラスターがあって、同じIAMロール(シークレットリーダーロール)を引き受けるとします。 EKSがポッド内のコンテナに認証情報を与える際に設定するロールセッションタグは、EKSクラスター名イエローになります。そして、シークレットのリソースタグ、つまりポッドに与える権限(シークレットの作成やシークレット値へのアクセスなど)は、セッションタグのタグと一致する必要があります。青いクラスターの場合も同じですが、同じIAMロールと同じIAMポリシーを再利用できます。これは、ロールの再利用を可能にしたい場合に非常に強力です。数十のクラスターがあり、ハードコードされたクラスター名以外は本質的に同じ多くの異なるロールを管理している場合、これを廃止して1つにまとめることができます。
これらのAPIがどのように見えるかを簡単に概説します。AWS CLIを通じて、 pod identity associationを作成できます。ここでも、クラスターレベルで指定します。クラスター名、namespace、service account、role ARNを指定し、後で別のロールに更新することもできます。別のロールに更新する場合は、ポッドを再起動する必要があります。なぜなら、ポッドは以前のセッションからの以前の認証情報で実行し続けるからです。そして、1か所ですべてのpod identity associationをリストアップし、さらに削除することもできます。
EKS Pod Identityの内部動作メカニズム
それでは、簡単なデモに移りましょう。ここに2つのクラスターがあります。kubectlを使用して、私が持っているコンテキストを確認しています。実際には、blue fishと red fishクラスターだけを使用します。
まず最初に、ロールの設定方法をお見せします。これから説明していきますが、クラスターに付与したいロールがあります。ポリシードキュメントを見てみましょう。既に見たように、pods.eks.amazonaws.comが信頼されており、EKSがセッションにタグを付けてロールを引き受けることを許可しています。ここに追加の条件を設けました。このロールを任意のクラスターで使用できないようにし、これら2つのクラスターでのみ使用可能にしたいのです。他にもたくさんのクラスターがあることはお分かりでしょう。特定のクラスターに対してのみ許可するように条件キーを追加できます。つまり、アカウント内の任意のクラスターではなく、特定のクラスターに限定できるのです。
このロールのポリシーを見てみましょう。S3ポリシーとSecrets Managerポリシーの2つがあります。S3ポリシーを見ると、最初のスタンザには3つのアクション(delete、put、get objects)がありますが、それぞれ異なるリソースに対して実行できます。S3バケットがあり、バケット名は少し長いですが、最初の行にconfigプレフィックスがあるのがわかります。その後、テンプレート変数としてセッションタグを入れています。つまり、config/クラスター名/名前空間名/サービスアカウント名という形式で、その下では何でもできるようになっています。2行目は単に/dataとし、その後にクラスター名、そして全てが続きます。これは、クラスター内の何かがそのプレフィックス内でオブジェクトをput、get、deleteできるという一般的なプールのようなものです。
最後に、logsプレフィックスがあり、Kubernetes pod UIDを入れています。これはUID4で、各ポッドで異なるものになります。なぜこれが必要なのでしょうか?例えば、CIシステムを実行する場合、サービスアカウント名やポッド名さえも使いたくないかもしれません。ポッド名は時間とともに重複する可能性がありますが、UIDは重複しません。各ポッドが異なるプレフィックスにアップロードできるようにしたいが、他のものを上書きできないようにしたい場合があるかもしれません。これはその一例です。そして最後に、このロールはバケット全体をリストでき、他のバケットもリストできます。
Secrets Managerポリシーを見てみると、これはS3のパスプレフィックスというよりも、よりタグベースになっています。Secrets Manager starを許可します。つまり、リソースタグのEKS cluster nameが、そのリソースのタグのクラスター名キーであり、そのタグの値がセッションタグ値のEKS cluster nameと一致する限り、任意のSecrets Managerコールを許可します。ここではクラスターレベルのタグを使用し、全てのリソースに対して何でもできるようにしています。ランダムパスワードの取得もできます。つまり、ランダムパスワードの生成が可能です。全てのシークレットをリストできますが、必ずしもアクセスできるわけではありません。そして、タグ解除に関するいくつかの他の権限があります。タグ解除は拒否します。他の人のリソースのタグを解除して、自分のものとしてタグ付けし、所有権を主張することはできないようにしています。また、Secrets ManagerのポリシーAPIの管理も許可していません。
それでは、クラスターのリストを表示してみましょう。blue-fishとred-fishがあります。そして、新しいアドオンを作成します。この新機能の一部として、ポッドの認証情報交換を行うアドオンがあります。これについては後ほど詳しく説明しますが、ポッドが起動すると、このエージェントに認証情報を要求します。エージェントはEKSに対して認証情報の交換を行います。ここでpod identity agentをインストールしています。少々お待ちください。そして、red-fishクラスターのpod identity associationをリストアップします。まだありませんね、よし。
では、新しく作成しましょう。IAMロールがあり、ポリシーも確認しましたので、作成を進めます。はい、作成されました。red-fishクラスター上に、そしてそのポッドロールがポッドロールです。これでクラスターにロールが関連付けられました。次に、Kubernetesポッドをインストールします。kubectl get podsを実行すると、ポッドはまだありません。ここにデプロイメントがあります。このデプロイメントで2つのことを行います。まず、pod identity associationで参照したサービスアカウントがあります。そして、非常にシンプルなコンテナを実行しています。Amazon Linux 2023を使用し、いくつかの環境変数を注入しました。config mapを通じてバケット名をマッピングし、ポッドにメタデータのヒントを与えています。セッションロールの認証情報にセッションタグがあっても、必ずしもそれを知ることはできません。そこで、クラスター名、ポッドの名前空間、サービスアカウント名、ポッド名などの情報をポッドに提供しています。
これらは環境変数として注入され、この場合ポッド名はホスト名になっています。また、後ほど見ていただきますが、いくつかのconfig mapをポッド内のパスとしてマウントしています。
クラスター内のアクセス保護:Network Policiesの導入
デモのセットアップを実行しましょう。セットアップスクリプトを含むconfig mapを作成し、Kubernetesデプロイメントファイルをクラスターに適用しています。kubectl get podsを使用すると、デプロイメントであるポッドが実行されているのが確認できます。kubectl execを使ってそのポッドに入ります。これでポッド内のシェルに入りました。red fishクラスターのデフォルト名前空間にあるポッドの中にいます。ポッドのホスト名がそこに表示されています。
いくつかのことを示すスクリプトを実行してみましょう。ポッド内で、caller identityを取得します。ポッドはどのアイデンティティを持っているでしょうか?はい、ポッドロールを持っていますね、素晴らしい。次に、設定した環境変数と他のいくつかの変数を見てみましょう。ポッド名、サービスアカウント、ポッドUIDを設定しましたが、AWSが自動的にポッドに注入するものもいくつかあります。container authorization token fileとcredential full URIです。これらはSDKへのヒントで、「認証情報の取得方法はこうだよ。このURLのエージェントと通信して、capacity agentから読み取るべきトークンはこれだよ」と伝えています。
まず、S3のデモを行いましょう。先ほど、異なるプレフィックスを持つS3のポリシーを見ました。ランダムなデータを生成し、一時ファイルに書き込みます。そして、そのランダムデータを/dataの下のバケットにコピーします。データとクラスター名を使用する必要があります。つまり、data cluster nameとすると、クラスター名は私たちのpodの環境変数なので、そこにコピーすると、うまく動作します。
バケット全体をリストアップすると、中身を確認できます。アップロードしたランダムデータ、blue fishクラスターの下にある他のデータ、そして他のpodから実行されたログがあります。他のpodのbash履歴を自分たちの一時フォルダにコピーしようとすると、それは自分たちのpod UIDではないので失敗します。しかし、自分たちのbash履歴を、logsパスの下の自分たちのpod UIDプレフィックスにアップロードしようとすると、それは成功します。
次に、Secrets Managerのデモをさっと行いましょう。全てのシークレットをリストアップしようとすると、まだシークレットがありません。先ほど、ランダムなパスワードを作成できると言いましたね。誰でもそれができます。ここで、一つを環境変数として保存し、シークレットを作成します。ここで何が上手くいかないか分かりますか?タグがありません。タグなしで作成しようとしましたが、失敗します。このコールにタグを追加し、キーをEKS cluster name、値をクラスター名として指定すると、うまくいきます。
そのシークレットの値を取得したい場合、自分で作成したシークレットなので、それができます。タグを外そうとすると、明示的な拒否があるのでできません。シークレットの削除も同様で、所有者なので可能です。もう一度素早く実行したいと思います。シークレットを再作成して、他のクラスターから見せたいからです。あ、すでに削除がスケジュールされていますね。Secrets Managerでは、シークレットを削除する必要があり、時には結果整合性があります。これはそのような場合の一つです。
はい、再作成しました。では、ここから抜けて、blueクラスターに戻りましょう。blue fishにいて、すでにpodを作成したので、その全てを再確認する必要はありません。podが実行中です。そのpodにexecすると、以前と同じものが見えます:pod end、同じroleがあり、環境変数があります。red fishの代わりにblue fishクラスターです。しかし、別のデモを実行したい場合、シークレットを作成してタグを設定することもできます。
これが青い魚のシークレット です。secretsをリストすると、今作成した青い魚と、以前からあった赤い魚のシークレットを含むすべてのシークレットが表示されます。そこにあるのがわかりますね。 青い魚クラスターのシークレット値を取得しようとすると、それは可能です。赤い魚クラスターの場合は失敗します。同様に、ログについても、 自分のpodのものでないログはコピーできません。
そして、サプライズがあります。それが何か見てみましょう。EKSの楽しいASCIIアートです。つまり、EKSは単に機能するということですね。素晴らしいことです。実際に起こっていることは、先ほど少し触れましたが、AWS CLIやすべてのAWS SDKが、ディスクからそのトークンを取得し、ローカルのメタデータサービス、つまりpodメタデータサービスを呼び出して認証情報を取得しているのです。ここに認証情報を示しましたが、それがどのように認証情報を取得しているかがわかります。
先ほど言及したように、ここで裏側で起こっていることは 、アプリケーションコンテナがディスクからサービスアカウントを読み取っているということです。AWS SDKでは、このローカルのpod identity agentを呼び出しています。これは私たちがインストールしたアドオンです。pod identity agentは、そのトークンでEKS APIを呼び出し、「このトークンの認証情報が必要です」と伝えます。すべての関連付けの詳細と、どのロールが必要かを把握しており、そのロールの認証情報を返します。
部分的に振り返ると、まず、今後リリースされるcluster access management機能を使ってクラスターへのアクセスをどのように保護できるかについて話しました。次に、クラスター内から外部へのアクセスをどのように保護できるかを見ました。IAM roles for service accounts (IRSA)やEKS pod identityなど、複数のオプションがあります。次に、クラスター内でのアクセスをどのように保護できるかを見ていきます。
VPC CNIでのNetwork Policiesネイティブサポート
壁、要塞、城というテーマを続けて、中世以前のイングランドに住んでいて、あなたが王だとイメージしてください。どのように自分を守りますか?王国の外からの敵と、内部からも身を守る必要があります。これはドーバー城の写真です。よく見ると、城を取り囲む複数の壁があることがわかります。つまり、一つの壁が破られても、王を守る別の壁があるのです。これは本当に多層防御の例です。
では、EKSで同様のことを実現するにはどうすればよいでしょうか? まず、Network Policiesについて簡単に説明させてください。Kubernetesには Network Policies という構成要素があります。デフォルトでは、クラスター内で実行されているポッド間にネットワーク分離はありません。しかし、マイクロサービスを使用したアプリケーションがあり、どのポッドがどのポッドと通信できるかについてポリシーを設定したい場合があります。
今年8月以前は、EKSクラスターでNetwork Policiesを有効にする方法は、サードパーティのプラグインをインストールすることでした。私たちが提供しているデフォルトのポッドネットワーキングプラグインであるVPC CNIには、そのサポートがありませんでした。これについて、お客様からフィードバックをいただきました。Network Policyを実現するために複数のプラグインを実行することで、ポッドのレイテンシーが増加するというものでした。また、複数のプラグインを管理、サポート、コスト管理するオーバーヘッドについても指摘がありました。最後の懸念点は、表面積を増やすことで新たな障害モードが導入されるということでした。
そこで、嬉しいお知らせがあります。今年8月に、VPC CNIでNetwork Policiesのネイティブサポートを開始しました。 Micahが、私たちが行ったことについて詳しく説明します。
ありがとうございます。はい、これは本当にエキサイティングです。単一のプラグインなので、Network Policyを実現するために複数のものをインストールする必要がなく、EKSに付属のVPC CNIを使用してNetwork Policyサポートを得ることができます。これは、EC2 security groups for podsのような、CNIの他の機能とも統合されています。つまり、Kubernetes Network Policyに加えて、オフボックスでセキュリティグループを適用することもできます。また、非常にパフォーマンスが高いです。IPテーブルベースの方法でネットワークアクセスをブロックするのではなく、eBPFを使用しています。
eBPFをご存じない方のために説明しますと、eBPFは拡張Berkeley Packet Filterの略です。これはLinuxカーネル内のエンジンで、ユーザースペースから呼び出されるシステムコールをインターセプトします。一般的に、トレーシング、セキュリティ、ロードバランシングなどに使用されます。今回のケースでは、セキュリティのために使用しています。これは呼び出しをインターセプトする方法です。
このインターセプションは、カーネルを実行したりコンパイルしたり、カスタムカーネルモジュールを実行したりすることなく行うことができます。 では、これはどのように機能するのでしょうか?EKSは、マネージドコントロールプレーン上でネットワークポリシーコントローラーを実行します。Kubernetesリソースであるネットワークポリシーを作成すると、このネットワークポリシーコントローラーがそれを認識し、次にネットワークポリシーエンドポイントCRDを作成します。 これはEKS固有のCRDで、このネットワークポリシーで適用されるルールを取り込み、各ノードのVPC CNIエージェントがこのネットワークポリシーエンドポイントから読み取って、何を適用すべきかを知ります。ここでの重要な2つのコンポーネントは、ネットワークポリシーコントローラーと、既にノード上に存在するエージェントです。
では、これの具体例はどのようなものでしょうか?このようなネットワークポリシーがあるかもしれません。これはKubernetesのネットワークポリシーです。名前はdemo-app-red-nsです。 specの最初の部分にはpod selectorがあります。これは、ラベルapp: demoを持つすべてのポッドに適用されます。これが適用されるポッドに対して、namespaceの名前がredであるnamespaceからのingressを許可します。つまり、これは基本的に、namespaceのredからのトラフィックのみを許可し、他の場所からは許可しないという非常にシンプルなセレクターです。
繰り返しになりますが、これは先ほど述べたEC2セキュリティグループと連携して機能します。例えば、VPC内にAmazon RDSやAmazon ElastiCacheがあり、ポッドを持つEKSノードグループがある場合、ネットワークポリシーとEKS CRDを使用して、VPCリソースやクラスターリソースへのポッドのアクセスを制限することができます。
最新のEKSセキュリティ関連機能の紹介
次に、最近のセキュリティ関連の発表をいくつか見てみましょう。これらについて多くの時間を割くつもりはありませんが、 これらの用語でGoogle検索すれば、適切な「What's New」の投稿、ブログ、またはドキュメントにたどり着けるでしょう。1つ目は、Network LoadBalancerのEC2セキュリティグループサポートです。EKSクラスターにプロビジョニングするNLBまたはNetwork LoadBalancerを、セキュリティグループルールで保護できるようになりました。NLBの背後で実行されているアプリケーションに、特定のエンドポイントIPアドレスからのみアクセスできるようにするルールを設定できます。
2つ目は、EKS管理APIのPrivateLinkサポートです。これにより、VPC内からEKS管理APIにアクセスするための安全でプライベートな方法が提供されます。インターネットや公共ネットワークを経由せずに、VPCから直接プライベートネットワークを通じてEKS管理APIにアクセスできます。3つ目は、Amazon Detectiveの機能強化です。EKSから収集するVPCフローログに対して、Amazon Detectiveがより多くの分析と可視化を提供するようになりました。
4つ目は、EKSのGuardDuty統合に対する改善です。以前は、GuardDutyを使用してAPIサーバーへのすべてのトラフィックを監視できましたが、今回はそれを拡張し、ワーカーノード上のクラスターでGuardDutyエージェントを実行して、ワーカーノードのOSレベルの問題を確認できるようになりました。GuardDutyがOSレベルの問題を検出できるようになったのです。最後に、EKSクラスターにデプロイされるコンテナイメージの署名と検証を行う機能をリリースしました。これはいくつかの異なるAWSサービスによって実現されています。
AWS Signerは、イメージを簡単に署名できるように改良されたマネージド署名サービスです。署名されたイメージをECRなどのコンテナレジストリに保存し、イメージがEKSクラスターにデプロイされるたびに、アドミッションコントローラー、Gatekeeper、またはKubernetesのコアコンポーネントを使用できます。独自のアドミッションコントローラーを作成することもできます。ブログ記事に例がありますが、クラスター自体にデプロイされる前にイメージを検証できます。詳細については、オンラインで検索するか、セッション後に質問してください。
セッションのまとめ:EKSセキュリティの3つの側面
簡単に振り返ると、クラスターをセキュアにする3つの側面について見てきました。まず、クラスターへのアクセスの保護です。既存のConfigMapによる方法(これは今後も存在し続けます)と、近日公開予定のCluster Access Managementという機能の2つのオプションがあります。後者は、アクセス設定をより合理化し、改善された体験を提供すると考えています。次に、クラスター内から外部へのアクセスを保護する方法について説明しました。ここでも2つのオプションがあります。数年前から存在するIRSAと、ポッドにIAM権限を付与するプロセス全体を合理化するEKS Pod Identityです。
最後に、クラスター内のアクセスを保護するためにVPC CNIとネイティブに統合されているネットワークポリシーについて説明しました。これらの機能に私たちは非常に興奮しています。皆さんが自分の壁を築くためのブロックを提供できていることを願っています。
※ こちらの記事は Amazon Bedrock を様々なタスクで利用することで全て自動で作成しています。
※ どこかの機会で記事作成の試行錯誤についても記事化する予定ですが、直近技術的な部分でご興味がある場合はTwitterの方にDMください。
Discussion