Aqua EnterpriseでAmazon EKS環境にContainer Runtime Protectionを適用する
コンサル部のとばち(@toda_kk)です。
Aquaでは、クラウドネイティブなアプリケーションを対象としたRuntime Protection(ランタイム保護)の機能があります。
今回はAmazon EKS環境にContainer Runtime Protectionを適用してみたので、その手順や動作確認を記載します。
なお、EKS環境でAqua Enterpriseを構築する手順については、下記の記事をご参照ください。
また、Container Rutime Protectionにおいてポリシーとして適用できる項目の一覧については、下記の記事をご参照ください。
前提・注意点について
本記事における検証においては、Aqua社から提供いただいたトライアルアカウントを利用しています。Aquaのセットアップに必要なコンテナイメージや公式ドキュメントなどは、アクセス用のアカウントが必要となりますのでご留意ください。
AquaのRuntime Protectionについて
Aqua EnterpriseではRuntime Policyという形でポリシーを設定し、実行環境で許可/禁止したい操作を定義しておくことができます。操作の制限を強制するだけでなく、操作を監視し監査ログとして出力するだけにとどめる設定も可能です。
ポリシーを適用するためには、実行環境にEnforcerと呼ばれるコンポーネントをインストールすることが必要になります。
Runtime Policyには、下記の3種類があります。
- Container Runtime Policy: コンテナに適用できるポリシーです。
- Function Runtime policy: 2022年3月現在、AWS Lambdaにのみ適用できるポリシーです。Microsoft Azure functionsはサポートしていないようです。
- Host Runtime Policy: 上記以外のホストコンピューターに適用できるポリシーです。LinuxとWindowsどちらもサポートしています。
このうち、Container Runtime Policyは、コンテナセキュリティについてまとめたガイドラインである NIST SP800-190 における「コンテナのリスク」に対するランタイムセキュリティに該当します。
ポリシーは、Aqua Console(管理ダッシュボード)からGUIで設定可能です。また、事前に定義されたポリシーもいくつかあり、それをそのまま適用することもできます。
※以下、Aqua Enterpriseの公式ドキュメントを確認するためには、Aquaアカウントでのサインインが必要になります。
独自のContainer Runtime Policyを作成する
「Aqua default runtime policy」「CIS」「NIST」など、事前に定義されているポリシーをそのまま利用することもできますが、独自のポリシーを作成することもできます。
ちなみに、作成したポリシーはJSON形式でインポート/エクスポートできます。Kubernetesマニフェストなどといっしょに、Aquaのポリシーの内容もJSONでコード管理してしまっても良いかもしれません。
ポリシーを作成する際に設定する項目は下記の通りです。
- Policy Name: 作成するポリシーの名前です。
- Description: 作成するポリシーの説明です。この項目は必須ではありません。
- Scope: ポリシーを適用する対象を指定できます。
- Status: ポリシーを有効化/無効化できます。
- Enforcement Mode: Audit/Enforceの一方を選んで設定できます。
- Audit: ポリシーで定義した操作を監視し、監査ログとして出力します。
- Enforce: 監視するだけでなく、操作の制限を強制します。
- Controls: 監視や制限をしたい操作を設定する項目です。
このうちScope、Enforcement Mode、Controlsについて少し詳細に見ていきます。
Scope
Scopeは、ポリシーを適用する対象範囲です。設定できる項目は下記2つがあります。
- Application Scopes
- Additinal Scope Criteria
Application Scopes
Aqua Consoleの Administration → Application Scopes
から、ポリシーの適用範囲をApplication Scopeとして定義できます。
デフォルトでは「Global」のみが定義されていますが、独自に作成できます。
上図の作成画面のように、Workloads(EKSクラスターやNamespaceなど)やInfrastructure(起動しているVM)を指定して、ポリシーを適用したい対象を定義できます。
Additinal Scope Criteria
上述のApplication Scopeに加えて、ポリシーごとにさまざまな適用条件を追加できます。
選択肢からポチポチ選んで追加できますが、テキストボックスに条件式を直接書き加えることも可能です。
Scopeに関して、その他の詳細については下記の公式ドキュメントをご参照ください。
Enforcement Mode
上述の通り、Enforcement Modeには「Audit」「Enforce」の2種類があり、Runtime Policyごとに設定します。
さらに、「Enforce mode Change」という項目で、スケジューラーを設定できます。例えば、まずは「Audit」で設定して監査ログの出力のみしておいて、3日後からは「Enforce」に変更し実際に操作を制限する、といった設定することもできます。
Controls
上図のように、Controlsの項目がずらっと並んでいます。実際に制限したい操作を設定する項目になります。
例えば、「Block Container Exec」を有効にすると、実行中にコンテナに対して exec
コマンドを実行する操作を監視・制限できます。
一部のControlは、Enforcement Modeが「Audit」もしくは「Enforce」の場合にのみ適用できるようになっています。
また、監視対象となる環境にインストールされているEnforcer(Aqua Enforcer、Kube Enforcerなど)ごとに、設定できるControlが異なっています。Enforcerの種類については、下記の記事をご参照ください。
作成したポリシーの適用を確認してみる
では、実際に独自のポリシーを作成した上で、EKS環境に適用してみます。
「Audit」で不正な操作を検知する。
まず、下記のようなポリシーを作成します。
- Scope: Global
- Enforcement Mode: Audit
- Control: Block Container Exec のみ
- 「Allowed Processes」として許可するプロセスはデフォルトの状態
正しく適用されているか、動作確認してみます。
確認用に test-nginx
という名前でNginxのPodを作成し、 kubectl exec
コマンドを実行してみます。
$ kubectl run test-nginx --image=nginx:latest pod/test-nginx created $ kubectl get pods NAME READY STATUS RESTARTS AGE test-nginx 1/1 Running 0 70s $ kubectl exec test-nginx -it sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. # ls bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var boot docker-entrypoint.d etc lib media opt root sbin sys usr
Aqua Consoleの Security Reports → Audit
から、Aquaが検知した内容を確認できます。
Enforcement Modeを「Audit」で設定していたため、上記の操作がStatus「Detect」で出力されています。出力された情報を見てみると、検出したPolicyの名前や該当するControlの項目などがわかります。
「Enforce」で不正な検知をブロックする
続いて、Enforcement Modeを「Enforce」に変更して、上記の操作をブロックしてみます。
「Audit」の場合には特に設定しませんでしたが、「Enforce」のポリシーを適用したい場合には、まずEnforcer Groupと呼ばれるAquaリソースを設定変更する必要があります。
Enforcerはエージェントのようなコンポーネントであり、AquaではEnforcerを通して操作の検知や制限を実行しています。
そして、Enforcer Groupは管理対象となる環境にインストールされ稼働するEnforcerの集合です。
- Enforcers Overview
- Enforcers Screen (UI)
- Configuring Enforcers for Aqua Platform :: Aqua Security Workshop
- こちらのドキュメントは、AWSから提供されているWorkshopのものです。Workshopの内容については、下記の記事をご参照ください。
- AWS環境でAquaを導入するハンズオンをやってみた | DevelopersIO
Aqua Consoleで Administration → Enforcers
から、設定されているEnforcer Groupを確認できます。
公式の手順に従ってEKS環境にAquaを構築すると、Aqua Enforcer(aquayaml-default
)およびKube Enforcer(aquayaml-default-ke
)がインストールされることになります。
Aqua EnforcerはDaemonSetとしてデプロイされ、各ワーカーノードとなるEC2インスタンスにPodが起動します。また、Kube EnforcerはDeploymentとしてデプロイされ、Podが起動します。
$ kubectl get daemonsets -n aqua NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE aqua-agent 2 2 2 2 2 <none> 12h $ kubectl get deployment -n aqua NAME READY UP-TO-DATE AVAILABLE AGE aqua-gateway 1/1 1 1 12h aqua-kube-enforcer 1/1 1 1 12h aqua-web 1/1 1 1 12h starboard-operator 1/1 1 1 12h
Enforcer GroupはデフォルトではEnforcement Modeが「Audit Only」になっているなど、一部の設定が適用されない状態になっているため、不正な操作をブロックしたい場合には設定変更が必要になります。
まずは、Aqua Enforcerを選択し「Edit Group」から変更します。
「Advanced Settings」が「AUDIT ONLY」と表示されています。横の「Show Settings..」から、適用できるEnforcement Modeを変更できます。
Container ProtectionやHost Protectionの適用可否についても設定できます。すべて「Enabled」にしておきます。本番環境では、過剰な検出や制限を防ぐために適切な設定にしておくと良いかと思います。
Kube Enforcerでも同様に、設定変更します。
Enforcer Groupの設定を変更したら、次にContainer Runtime PolicyのEnforcement Modeを「Enforce」に変更します。
設定変更すると、基本的にはすぐに反映されますが、適用するControlの項目によっては起動中のコンテナの再起動が必要になりますので、ご注意ください。
さて、いよいよ不正なコマンドがブロックされるか動作確認してみます。先ほどと同じく、 test-nginx
という名前で作成したPodに対して kubectl exec
コマンドを実行してみます。
$ kubectl exec test-nginx -it sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. OCI runtime exec failed: runc did not terminate successfully: : unknown command terminated with exit code 126
すると、コマンドがブロックされました。
Auditから、先程の操作が出力されており、StatusおよびAqua Responseが「Block」になっていることが確認できます。
期待通りの制限が実施されていることを確認できました。
kube-systemのPodに対する操作を制限する
最後に補足となるのですが、Namespace kube-system
のPodに対して同じように不正な操作を制限したい場合には、追加でもう1つ設定が必要になります。
このまま同じように、 kube-system
のPodに対して kubectl exec
コマンドを実行すると、そのまま成功してしまいます。
$ kubectl get pods -n kube-system NAMESPACE NAME READY STATUS RESTARTS AGE kube-system aws-node-jttw6 1/1 Running 0 8h kube-system aws-node-t5sg9 1/1 Running 0 8h kube-system coredns-76f4967988-6k2r2 1/1 Running 0 8h kube-system coredns-76f4967988-v7grr 1/1 Running 0 8h kube-system kube-proxy-8frpj 1/1 Running 0 8h kube-system kube-proxy-hv969 1/1 Running 0 8h $ kubectl exec kube-proxy-8frpj -n kube-system -it sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. # ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
これは、Aqua全体の設定としてGlobal Bypassがデフォルトで設定されており、特定のLabelやNamespaceに該当する場合は操作の検知(Detect)や制限(Enforce)をしないようになっているためです。
Aqua Consoleから Settings → Enforcer
で確認、設定変更できます。
この中に、デフォルトでは下記の記述が含まれています。
container.label."io.kubernetes.pod.namespace"."kube-system"
kubernetes.namespace.kube-system
これらを削除することで、 Namespace kube-system
に対しても操作の制限ができるようになります。
$ kubectl exec kube-proxy-8frpj -n kube-system -it sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. OCI runtime exec failed: runc did not terminate successfully: : unknown command terminated with exit code 126
ただし、通常はaws-nodeやkube-proxyなどEKSクラスターが正常に動作する上で必要なリソースが kube-system
で動いているため、過度に操作を制限するとEKSクラスター自体が正常に動作しなくなるかもしれないので、扱いにはご注意ください。
Container Runtime PolicyによってEKS環境のランタイムを保護できる
今回は kubectl exec
コマンド実行を制限してみましたが、AquaではさまざまなControl項目が用意されており、動的なランタイムの保護にも対応できます。
Runtime Policyだけでなく、Enforcer GroupやGlobal Bypassの設定も必要な箇所もありましたが、かなり細かな設定も実現できるため、EKSをはじめAWSコンテナ環境におけるセキュリティの強力な選択肢になると思います。
以上、コンサル部のとばち(@toda_kk)でした。