Aqua Platform Enterprise MicroEnforcerのサイドカーでFargateに起動したDVWAを防御してみた

2022.06.15

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

こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です!

aqua社が提供しているAqua Platform の Enterprise版を試す機会がありましたのでECS-Fargate上に検証環境向けセットアップをおこない手順をまとめました。

Aqua Platformとは?

Aqua Platformはaqua社が提供するソリューションでコンテナとクラウドネイティブアプリのために開発された、 フルライフサイクルなセキュリティソリューションになります。

aqua コンテナ・クラウドネイティブアプリのためのセキュリティソリューション

記事の前提について

今回の記事は、Aqua社と交渉の上、検証用のトライアルアカウントを利用しています。

コンテナイメージや、セットアップ用のドキュメントなどは、公式ドキュメントアクセス用のアカウントが必要となりますのでご留意ください。

検証環境について

今回、ECS Fargateを利用して構築してあることを前提にしております。

FargateでMicroEnforcerを使う方法は2種類あります。

今回はサイドカーコンテナを立ち上げて連携する方法をご紹介します。アプリケーションコンテナに直接組み込む方法は以下をご覧ください。

全体の構成図は以下になります。順番に構成図のリソースを作っていきます。

VPCの構築

既に使用したいVPCが決まっていれば、この手順は飛ばしてもらって構いません。

構成図の通り、2AZ間でパブリック/プライベートサブネットを作成し、1つのAZでNAT Gatewayを作成する構成を作成しました。

図で表すと以下のリソースまで作成できました。

ECRの作成

ECSでコンテナを起動するためDocker Imageを保存するレジストリを作成します。

今回作成するレジストリは以下の3つです。

  • aqua-console(Aqua ServerのDocker Image用)
  • aqua-gateway(Aqua GatewayのDocker Image用)
  • aqua-enforcer(Sidecar ContainerのDocker Image用)
  • aqua-container(Application ContainerのDocker Image用)

同様に残り3つのレジストリも作成していきます。

イメージのプッシュ(Aqua Server/Gateway)

MicroEnforcerのセットアップにあたり、Aqua Server/Gatewayを立ち上げる必要があるため先に、Docker Imageのプッシュを行います。

作業手順は以下の通りです。

  1. Dockerイメージの取得を行うためAquaにログインします。
  2. docker image pullでイメージを取得します。
  3. ECRへログイン
  4. docker image tagでイメージにタグ付けを行います。
  5. docker image pushでイメージをECRにプッシュします。

Aquaにログイン

docker login registry.aquasec.com

イメージ取得

docker pull registry.aquasec.com/console:2022.4
docker pull registry.aquasec.com/gateway:2022.4

ECRログイン

XXXXXXXXXXXX」、「ap-northeast-1」はご自身のAWSアカウントIDとECRを作成したリージョンに置き換えてください。

aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com

イメージタグ付け

docker image tag registry.aquasec.com/console:2022.4 XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-console:2022.4
docker image tag registry.aquasec.com/gateway:2022.4 XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-gateway:2022.4

イメージプッシュ

docker image push XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-console:2022.4
docker image push XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-gateway:2022.4

構成図としては以下まで作成できました。

Aqua Enterpriseのセットアップ

CloudFormationスタックの作成

aquaのガイドページに掲載されている手順に沿って導入を進めていきます。

※ ガイドページはログインが必要なページとなっております。

DEPLOY AQUA ENTERPRISE > Non-Kubernetes Platforms > Amazon Elastic Container Service (ECS)

こちらを参照すると、GitHubを参照するように記載がありますが迷って、問い合わせ確認したところ以下であることがわかりました。

GitHub - aquasecurity/deployments/server/ecs/cloudformation

上記のGitHubリポジトリからスタックの作成を行います。

READMEに構成が説明されており、以下のものが作成されます。

構築されるリソース

構築されるもの 用途
ALB Aqua Server(Aqua Console)用のALB
NLB Aqua GatewayとAqua Server用のNLB
Aqua Server (Aqua Console) Fargateで起動するアプリケーションサーバ
Aqua Gateway Fargateで起動するAqua ServerとAqua Enforcerの通信を処理するコンポーネント
Aqua Database RDSインスタンス 起動する設定やセキュリティポリシー、ユーザ管理、ログ履歴を保存。別途構築のRDSの指定も可能
Secrets Manager RDS接続情報の保存
AWS Lambda Random String 生成用
Cloudwatch Logs Console/enforcer/gateway、performance用の4個のロググループ と上記Lambdaのロググループ
S3 ALBのアクセスログ保管先バケット
IAM ECSのタスク用ロールと、Lambda用ロール

各コンポーネントの詳細については以下のブログを参照ください。

参考までに今回は、以下のパラメーターを使用しました。

キー
VpcId デプロイするVPCのID
VpcCidr 10.0.0.0/16
EcsInstanceSubnets 2AZにまたがるプライベートサブネットを2つ選択
LbSubnets 2AZにまたがるパブリックサブネットを2つ選択
SSLCert ALBに紐づけるACMのARN
Aqua LB Scheme internet-facing
Web Console Source 0.0.0.0/0
AquaServerImage XXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-console:2022.4
AquaGatewayImage XXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-gateway:2022.4
ActiveActive false
RDS instance type db.t3.medium
RDS storage size (GB) 50
Enable Multi-AZ RDS false
AuditRDS No
AuditRdsInstanceClass db.t3.medium
ClusterName aqua-ecs

ALBのレコード登録

ALBリスナーに設定した証明書のドメインでログインできるよう、Route53またはDNSサーバーのレコードを登録します。

私の場合は、Route53でドメインを管理しているため以下のエイリアスレコードを登録しました。

キー
レコード名 ACMと同じドメイン
レコードタイプ Aレコード
エイリアス 有効|Route53でのみ使用可能
Application LoadBalancerのエイリアス ALBのDNS名

構成図としては以下まで作成できました。

Aqua Consoleのセットアップ

Route53で登録したドメイン経由でALBにアクセスします。初回アクセス時は、ユーザー名とパスワードの登録を求められます。

今回は、検証のため以下の値を入力しました。

  • ユーザー名:administrator
  • パスワード:Admin1qaz@wsx

Enforcer Groupの作成

画面左ペインの「Administration」をクリックして、「Enforcers」をクリックします。

「Add Enforcer Group」をクリックして今回使用するMicroEnforcerのグループを作成します。

使用したパラメータは以下の通りです。

キー 備考
Enforcer Type Aqua MicroEnforcer
Group Name ECS-FargateMicroEnforcerGroup
Logical Name ECS-FargateMicroEnforcerLGroup
Aqua Gateway デフォルトの値(ip-10-0-135-9.ap-northeast-1.compute.internalなどの値)
Deployment Token ECS-FargateMicroEnforcerDeploymentToken

加えて、検知した際の挙動をブロックしたいため「Advanced settings」から「Enforcement Mode」を「Enforce」に変更します。

「Create Group」をクリックすると、Enforcer Groupが作成されます。

Aqua MicroEnforcerのセットアップ

サイドカー用イメージの作成

MicroEnforcerのサイドカー用のDockerfileのビルドに使うための作業ディレクトリを作成します。例:sidecar

MicroEnforcerのバイナリをAquaのドキュメントのリンクからダウンロードし作業ディレクトリの中に配置します。

policy.jsonとfirewall.jsonという空ファイルも作成します。

takakuni@sidecar % ls -ltr
total 33608
-rw-r--r--@ 1 takakuni.shinnosuke  staff       925  3 29 20:29 Dockerfile
-rw-r--r--@ 1 takakuni.shinnosuke  staff         0  3 29 20:31 firewall.json
-rw-r--r--@ 1 takakuni.shinnosuke  staff         0  3 29 20:31 policy.json
-rw-r--r--@ 1 takakuni.shinnosuke  staff  17203200  3 29 21:08 microenforcer

Dockerfile

FROM alpine
COPY microenforcer /bin/microenforcer

USER root
RUN ["chmod", "+x", "/bin/microenforcer"]
RUN ["/bin/microenforcer", "aqua-init"]
VOLUME ["/.aquasec"]

# Include the next line to embed an Image Profile
ADD policy.json /.aquasec/policy/policy.json
# Include the next line to embed a Firewall Policy
ADD firewall.json /.aquasec/policy/firewall.json

COPY microenforcer /.aquasec/bin/microenforcer

RUN addgroup -g 11433 -S aqua && \
adduser -h /home/aqua -g "aqua user" -s /sbin/nologin -G aqua -S -u 11431 aqua
USER aqua

ENV LD_PRELOAD='/.aquasec/bin/$PLATFORM/slklib.so'
ENV AQUA_MICROENFORCER="1"
ENV AQUA_DEBUG_TYPE=STDOUT
LABEL   name="Aqua MicroEnforcer" \
        vendor="Aqua Security Software Ltd." \
        summary="Aqua Security Microenforcer" \
        description="The Aqua Security MicroEnforcer provides runtime protection." \
        com.aquasec.component=microenforcer \
        com.aquasec.baseimage=alpine \
        product=aquasec \
        maintainer="admin@aquasec.com"

Dockerイメージをビルドして、ECRにリポジトリにプッシュします。

イメージのビルド

docker image build -t aqua-enforcer:latest --platform x86_64 .

イメージのタグ付け

docker image tag aqua-enforcer:latest XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-enforcer:latest

イメージのプッシュ

docker image push XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-enforcer:latest

アプリケーションコンテナの準備

今回は、DVWA(Damn Vulnerable Web Application)のDockerイメージを利用します。

Application Container用のECRリポジトリにDVWAのDockerイメージをプッシュします。

docker image pull vulnerables/web-dvwa
docker image tag vulnerables/web-dvwa:latest XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-container
docker image push XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-container

Application Containerの起動

ENTRYPOINTの取得

Application ContainerのDockerイメージで実行される予定の「ENTRYPOINT」を取得します。

以下で取得した出力が「null」の場合、何も指定する必要はありません。

値が出力された場合、控えておきます。

docker image inspect XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-container:latest -f "{{json .Config.Entrypoint}}"

私の場合は、["/main.sh"]が出力されました。

CMDの取得

同じくApplication ContainerのDockerイメージで実行される予定の「CMD」を取得します。

こちらも、取得した出力が「null」の場合、何も指定する必要はありません。

値が出力された場合、控えておきます。

docker image inspect XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-container:latest -f "{{json .Config.Cmd}}"

DockerイメージIDの取得

Application ContainerのDockerイメージで実行される予定の「CMD」を取得します。

値を控えておきます。

docker image inspect -f {{.Id}} XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-container:latest

タスク定義の作成

「Fargate」起動モードでタスク定義を作成していきます。

値は以下の通りで作成しました。(言及がないものは、デフォルト値です。)

設定 備考
タスク定義名 aqua-fargate-sidecar
タスクロール ecsTaskExecutionRole
オペレーティングシステムファミリー Linux
タスク実行ロール ecsTaskExecutionRole
タスクメモリ (GB) 0.5GB
タスク CPU (vCPU) 0.25GB

コンテナ設定(サイドカー)

タスク定義内のコンテナ設定です。

サイドカーコンテナは以下のように設定しました。

設定 備考
コンテナ名 aqua-sidecar-container
イメージ XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-enforcer
基本(環境) チェックを外す 極めて短い時間で実行するため

コンテナ設定(DVWA)

タスク定義内のコンテナ設定です。

アプリケーションコンテナ(DVWA)は以下のように設定しました。

設定 備考
コンテナ名 aqua-app-container
イメージ XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/aqua-container
ポートマッピング 80:tcp
エントリポイント(環境) "/.aquasec/bin/microenforcer","/main.sh" アプリケーションコンテナから見たサイドカーコンテナ上のmicroenforcerのパス、「ENTRYPOINTの取得」で控えた値
コマンド(環境) 「CMDの取得」で控えた値、私の場合は「null」のため指定無し

また、環境変数は以下を設定します。

設定 備考
AQUA_SERVER NLBのDNS:8444
AQUA_TOKEN ECS-FargateMicroEnforcerDeploymentToken
AQUA_IMAGE_ID sha256:ab0d83586b6e8799bb549ab91914402e47e3bcc7eea0c5cdf43755d56150cc6a 「DockerイメージIDの取得」で控えた値
LD_PRELOAD '/.aquasec/bin/$PLATFORM/slklib.so' ランタイムプロテクションへのパス

最後に、「ストレージとログ」の「ボリュームソース」で、サイドカーコンテナのボリュームをマウントするため、以下を設定します。

設定 備考
ソースコンテナ aqua-sidecar-container
読み取り専用 無効

「新しいタスク定義の作成」の画面に戻り、画面下部の「作成」をクリックします。

サービスの作成

タスク定義が完了したため、サービスを起動しタスクを立ち上げていきます。

今回は、検証のため以下のように設定しました。

(特に言及がないものは、デフォルト値で設定しています。)

設定 備考
起動タイプ FARGATE
オペレーティングシステムファミリー Linux
タスク定義(ファミリー) aqua-fargate-sidecar
タスク定義(リビジョン) latest
サービス名 aqua-fargate-sidecar-svc
タスクの数 1
クラスター VPC Aqua Enterpriseと同じVPC 任意のVPCでOK
サブネット パブリックサブネット 任意のサブネットでOK
セキュリティグループ 新しいセキュリティグループ 80番ポートが開いているセキュリティグループを作成

サービスが作成されると「タスク定義」に従いコンテナが起動します。

アプリケーションコンテナが「RUNNING」、サイドカーコンテナが「STOPPED」になっていればOKです。

Aqua Consoleにログインすると、アプリケーションコンテナが検知されていることがわかります。

これで、AWSリソースの作成は完了しました。

動作検証

事前動作確認

アプリケーションコンテナ(DVWAコンテナ)へログインしてMicroEnforcerが動作するかどうか確認します。

ユーザー名、パスワードに以下を入力してログインします。

  • ユーザー名:admin
  • パスワード:password

「Command Injection」を開き、; /bin/cat /etc/passwd ;を入力して送信すると。

/etc/passwdが出力されました。

今回は、/bin/catがコンテナ内で実行されないようランタイムポリシーの機能の一つである「Executables Blocked」を使用して、/bin/catをブロックしてみようと思います。

他の機能も知りたいという方は以下のブログをご覧ください。

Runtime policyの編集

実際に制御を行うランタイムポリシーを編集していきます。

Aqua Consoleから「Policy」、「Runtime Policies」を選択します。

「Aqua default runtime policy」を選択して編集していきます。

ランタイムポリシーの設定変更手順は以下の通りです。

  1. 「Enforcement Mode」を「Enforce」に変更します。
  2. 「Controls」から「Executables Blocked」を選択します。
  3. 「Executables Blocked」で「/bin/cat」を追加します。
  4. 「Save」をクリックします。再起動を求められる画面で、「OK」を選択します。

これで、/bin/catの実行をコンテナ内でブロックしたため、/etc/passwdが表示されなくなりました。

おわりに

以上、「Aqua Platform Enterprise MicroEnforcerのサイドカーでFargateに起動したDVWAを防御してみた」でした。

今回はサイドカータイプで実装しましたが、MicroEnforcerを直接アプリケーションコンテナに組み込むパターンもあるので是非ご覧いただければと思います。

以上、AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!