Aqua EnterpriseでAmazon EKS環境にContainer Runtime Protectionを適用する

2022.03.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンサル部のとばち(@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の集合です。

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)でした。