Service Screener v2 をコンテナ化してローカル環境で実行する

# はじめに
先日、[Service Screener v2 を使って AWS 環境の設定チェックを行う](https://qiita.com/kooohei/items/f77ca7f0e15cce421541)を行ったのですが、これをコンテナ化してローカル環境から実行できるようにしてみました。

# 環境
今回実施した環境は以下になります。
> OS：macOS
> チップ：Apple M1
> ミドルウェア：docker


## Docker ファイルの作成
*Amazon Linux 2023* ベースの Docker イメージを作成し、*AWS Service Screener v2* をセットアップして実行するためのものです。

```Dockerfile:Service Screener v2
FROM public.ecr.aws/amazonlinux/amazonlinux:2023

# 必要パッケージ
RUN dnf clean all && \
    dnf makecache && \
    dnf install -y unzip tar gzip less vim git shadow-utils \
                   python3 python3-pip python3-virtualenv && \
    dnf clean all

# AWS CLI (ARM64)
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "/tmp/awscliv2.zip" && \
    unzip /tmp/awscliv2.zip -d /tmp && \
    /tmp/aws/install && \
    rm -rf /tmp/aws /tmp/awscliv2.zip

# screener セットアップ
RUN cd /tmp && \
    python3 -m venv venv && \
    . venv/bin/activate && \
    python3 -m pip install --upgrade pip && \
    git clone https://github.com/aws-samples/service-screener-v2.git && \
    cd service-screener-v2 && \
    pip install -r requirements.txt && \
    python3 unzip_botocore_lambda_runtime.py

# ワークディレクトリ設定
WORKDIR /tmp/service-screener-v2

# ENTRYPOINT で環境変数に基づいて実行
ENTRYPOINT ["/bin/bash", "-c", "\
  source /tmp/venv/bin/activate && \
  python3 main.py -s ${SCREENER_SERVICES} -r ${SCREENER_REGIONS} && \
  aws s3 cp output.zip ${S3_UPLOAD_PATH}/output-$(/bin/date +%Y%m%d-%H%M%S).zip \
"]
```
*AWS CLI* のインストールは **ARM64** 対応になっているので注意してください。


## イメージの作成
作成したら build を行います。
```zsh:build
% docker build -t service-screener .
[+] Building 56.9s (9/9) FINISHED                                                                                                                                                  docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                                                                                               0.0s
 => => transferring dockerfile: 1.22kB                                                                                                                                                             0.0s
 => [internal] load metadata for public.ecr.aws/amazonlinux/amazonlinux:2023                                                                                                                       5.4s
 => [internal] load .dockerignore                                                                                                                                                                  0.0s
 => => transferring context: 2B                                                                                                                                                                    0.0s
 => [1/5] FROM public.ecr.aws/amazonlinux/amazonlinux:2023@sha256:b885fda4d431af6d651ebf90c4c8790add9b1c3bf181d5e8ca559d3d7d64e616                                                                 7.2s
 => => resolve public.ecr.aws/amazonlinux/amazonlinux:2023@sha256:b885fda4d431af6d651ebf90c4c8790add9b1c3bf181d5e8ca559d3d7d64e616                                                                 0.0s
 => => sha256:b885fda4d431af6d651ebf90c4c8790add9b1c3bf181d5e8ca559d3d7d64e616 770B / 770B                                                                                                         0.0s
 => => sha256:b742f5050dd6a7a09d4b1ea8174b2c9a52d38f8583a19cbc09b854c24cd1a184 528B / 528B                                                                                                         0.0s
 => => sha256:f573f40a8dcff60bbb6bbc76b44394b8614f9775e1adefc760030d8befdd72f0 664B / 664B                                                                                                         0.0s
 => => sha256:3851c1e87439f4d250c3c0908923968a64dd743e1e5cfc05b798a52dc5d1e215 54.96MB / 54.96MB                                                                                                   5.1s
 => => extracting sha256:3851c1e87439f4d250c3c0908923968a64dd743e1e5cfc05b798a52dc5d1e215                                                                                                          2.0s
 => [2/5] RUN dnf clean all &&     dnf makecache &&     dnf install -y unzip tar gzip less vim git shadow-utils                    python3 python3-pip python3-virtualenv &&     dnf clean all    25.7s
 => [3/5] RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "/tmp/awscliv2.zip" &&     unzip /tmp/awscliv2.zip -d /tmp &&     /tmp/aws/install &&     rm -rf /tmp/aws /tmp/  9.2s
 => [4/5] RUN cd /tmp &&     python3 -m venv venv &&     . venv/bin/activate &&     python3 -m pip install --upgrade pip &&     git clone https://github.com/aws-samples/service-screener-v2.git   8.8s 
 => [5/5] WORKDIR /tmp/service-screener-v2                                                                                                                                                         0.0s 
 => exporting to image                                                                                                                                                                             0.6s 
 => => exporting layers                                                                                                                                                                            0.6s 
 => => writing image sha256:195b7b173f69fe018865424f0d4279a076c045c93478d8e18f2bf4a8c5954bac                                                                                                       0.0s 
 => => naming to docker.io/library/service-screener                                                                                                                                                0.0s 
                                                                                                                                                                                                        
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/md03n3xkzzeh67hoxdgpdokl5

What's next:
    View a summary of image vulnerabilities and recommendations → docker scout quickview 
```

ビルドしたイメージができているか確認します。

```zsh:build 確認
% docker images                     
REPOSITORY         TAG       IMAGE ID       CREATED              SIZE
service-screener   latest    195b7b173f69   About a minute ago   729MB
```
ビルドが完了しました。


## 実行
`docker run` コマンドを利用して実行します。
このコマンドは、Docker コンテナを一時的に起動して、*Service Screener* を実行するためのものです。
```zsh:実行
% docker run --rm -it \                            
  -v ~/.aws:/root/.aws \
  -e SCREENER_SERVICES=ec2,s3 \
  -e SCREENER_REGIONS=ap-northeast-1 \
  -e S3_UPLOAD_PATH=s3://hengjiu-ss/screener-results \
  service-screener
 -- Acquiring identify info...

=================================================
Processing the following account id: 637423332162
=================================================

[info] Empty CF stacked created successfully, name:ssv2-630dd2f7e784
PREPARING -- S3::ap-northeast-1
PREPARING -- EC2::ap-northeast-1
... (S3Account) 
Public access configuration not set
... (S3Bucket) - hengjiu-ss
... (Compute Optimizer Recommendations) 
... (S3Bucket) - cf-templates-f9b7wq11t8b-ap-northeast-1
... (Cost Explorer Recommendations) 
... (S3Bucket) - service-screener-hengjiu
... (S3Macie) 
COMPLETED -- S3::ap-northeast-1 (3.822s)
... (EBS::Snapshots) 
... (EC2::Security Group) - sg-046d7a80c6bc84ee9
... (VPC::Virtual Private Cloud) - vpc-0a171286c3c63adcf
... (NACL::Network ACL) - acl-0c79e74bbdaac21b8
COMPLETED -- EC2::ap-northeast-1 (5.944s)
[info] Empty CF stacked deleted successfully, name:ssv2-630dd2f7e784
Total Resources scanned: 11.00 | No. Rules executed: 48.00
Time consumed (seconds): 6.307
Ec2pageBuilder class not found, using default pageBuilder
S3pageBuilder class not found, using default pageBuilder
... Running CP - TA, it can takes up to 60 seconds
Error: TA unable to generate. Access denied due to support level
Pages generated, download output.zip to view
CloudShell user, you may use this path:  =====>  /tmp/service-screener-v2/output.zip  <===== 
@ Thank you for using Service Screener, script spent 9.476s to complete @
upload: ./output.zip to s3://hengjiu-ss/screener-results/output-20250428-043955.zip
```

## オプション説明
各オプションの意味については以下になります。
```docker
docker run --rm -it \
```
- --rm: コンテナ終了後に自動で削除
- -it: 対話型ターミナルを有効（ログがリアルタイムで見られるようにするなど）

```docker:
-v ~/.aws:/root/.aws \
```
- **ボリュームマウント**: ホスト側の `~/.aws` ディレクトリ（認証情報や設定が入っている）を、コンテナ内の `/root/.aws` にマウントしコンテナ内で *AWS CLI* がホストの認証情報を使えるようになる

```docker:
-e SCREENER_SERVICES=ec2,s3 \
-e SCREENER_REGIONS=ap-northeast-1 \
-e S3_UPLOAD_PATH=s3://hengjiu-ss/screener-results \
```
- **環境変数の設定**:
  - SCREENER_SERVICES: スキャン対象のサービス（ここでは ec2 と s3）
  - SCREENER_REGIONS: 対象の AWS リージョン（ここでは東京）
  - S3_UPLOAD_PATH: スキャン結果のアップロード先 S3 バケット (ここでは s3://hengjiu-ss/screener-results)

```docker:
service-screener
```
- 実行する Docker イメージ名

ServiceScreener を実行し S3 へアップロードまで完了しました。

アップロード先の S3 バケットを確認すると無事出力されていることが確認できました。

```zsh:確認
% aws s3 ls s3://hengjiu-ss/screener-results/
2025-04-22 18:45:51    2468295 output-20250422-094549.zip
2025-04-28 13:39:57    2466632 output-20250428-043955.zip
```


# おわりに
前回の場合だと *ClouShell* のセットアップが必要だったり、EC2 とかで用意すると少なからずコストや維持が必要でした。
コンテナ化しておくことで docker が利用できる環境であればいつでも実行できるようになったのでとても便利になったと思います。


# 関連記事
https://qiita.com/kooohei/items/f77ca7f0e15cce421541

#### 参考
https://github.com/aws-samples/service-screener-v2