cdk-serverless-clamscanを使って既存S3バケットへウイルススキャンを設定してみた

この記事は デジタルキューブ ＆ ヘプタゴン Advent Calendar 2023 の 12月15日分の記事です。

https://qiita.com/advent-calendar/2023/digitalcube-heptagon

S3バケットへアップロードしたファイルへのウイルススキャンの方法として、[AWS Developer Tools Blog](https://aws.amazon.com/jp/blogs/developer/virus-scan-s3-buckets-with-a-serverless-clamav-based-cdk-construct/)で[cdk-serverless-clamscan](https://github.com/awslabs/cdk-serverless-clamscan)が紹介されています。

ブログではCDKで新規にS3バケットを作り、作成S3バケットへのウイルススキャン設定方法が紹介されていますが、本記事では既存バケットに対してcdk-serverless-clamscanを動かすまでについてを紹介します。

# はじめに

S3バケットのウイルススキャン方法について有償サービス以外で何か方法はないかと探していたところ、AWSのブログ記事を見つけ試してみました。

しかしAWS CDK/TypeScriptの初心者のため、[AWS CDK Workshop](https://cdkworkshop.com/ja/)でAWS CDKに触れてみてデプロイするまでの流れを把握してからcdk-serverless-clamscanの設定を行なっています。

# cdk-serverless-clamscan

[cdk-serverless-clamscan](https://github.com/awslabs/cdk-serverless-clamscan)は、S3バケットにアップロードされたファイルに対しLambdaを使って[ClamAV](https://www.clamav.net/)でのウイルスチェックを実行するコンストラクト（コンストラクト：私は構築されるAWSリソース群のライブラリだと理解）です。コンストラクトでは、S3バケットへアップロードされたファイルをLambdaからマウントされたEFSへ一時的にダウンロードし、ファイルスキャンを実行、実行結果はS3のファイルにタグとして付与されます。実行結果はLambdaやEventBrideなどに渡すことも可能です。


![serverless-clamscan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255474/709330d6-0a11-e38c-668d-d819b31256ca.png)

# CDKの作成

CDKプロジェクト作成の手順は[AWSのブログ記事中](https://aws.amazon.com/jp/blogs/developer/virus-scan-s3-buckets-with-a-serverless-clamav-based-cdk-construct/)の**Create and deploy our cdk application**にある手順と内容が重複しますが、実際に実行した情報を記載します。

- CDKアプリケーションの作成
```bash
mkdir CdkTest
cd CdkTest
cdk init app --language typescript
```

- `package.json`を以下内容へ修正します。
```json
{
  "name": "cdk_test",
  "version": "0.1.0",
  "bin": {
    "cdk_test": "bin/cdk_test.js"
  },
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk"
  },
  "devDependencies": {
    "@types/jest": "^26.0.10",
    "@types/node": "10.17.27",
    "aws-cdk": "^2.11.0",
    "jest": "^26.4.2",
    "ts-jest": "^26.2.0",
    "ts-node": "^9.0.0",
    "typescript": "~3.9.7"
  },
  "dependencies": {
    "aws-cdk-lib": "^2.11.0",
    "cdk-serverless-clamscan": "^2.1.29",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.16"
  }
}
```


- `lib/cdk_test-stack.ts`の内容は以下内容にします。`既存バケット名を入力`へはウイルススキャンを設定したいバケット名を入力します。
```typescript
import { Stack, StackProps, RemovalPolicy, CfnOutput } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { ServerlessClamscan } from 'cdk-serverless-clamscan';
import * as s3 from 'aws-cdk-lib/aws-s3';


export class CdkTestStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    
    // 既存バケット用のServerlessClamscan
    const sc = new ServerlessClamscan(this, 'rClamscan', {
      acceptResponsibilityForUsingImportedBucket: true,
    });
    // 既存バケット読み込み
    const importedBucket = s3.Bucket.fromBucketName(
      this, 
      'imported-bucket-from-name',
      '既存バケット名を入力'
    );
    // 既存バケットへのclamscan設定
    sc.addSourceBucket(importedBucket);

    //バケットポリシーを出力
    const bucketbolicy = sc.getPolicyStatementForBucket(importedBucket);
    new CfnOutput(this, 'bucketbolicy', {
      description: 'bucketbolicy',
      value: JSON.stringify(bucketbolicy)
    });

  }
}
```

- 依存関係のあるパッケージのインストールとCDKデプロイ。CDKアプリケーションを初めてアカウントにデプロイしたので手順中に`cdk bootstrap`が含まれています。
```bash
npm install
cdk bootstrap
cdk deploy
```
## バケットポリシー

デプロイ後にS3バケット用のバケットポリシーが出力されます。内容はDenyルールになっていため、既存のS3バケットに設定する際は注意が必要です。

# 動作確認
デプロイが終了後の動作確認。

- アップロード用のファイルを用意
- 検知されるかの確認のため、[テストウイルス](https://success.trendmicro.com/jp/solution/1305101)もダウンロードし用意
- S3バケットへファイルをアップロード
- ファイルのタグを確認。アップロード直後のタグは以下状態となっています。
 ![avscan-tag-progress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255474/4c436b41-312d-af9a-cdf1-6bb36859d55a.png)
- スキャンが終了後、ウイルスファイルの場合はタグは以下に更新されることが確認できます。
![avscan-tag-infected.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255474/4897c99d-1da6-b185-94b6-01006e24bbca.png)
- 正常ファイルの場合は`scan-status`は`CLEAN`に更新されます。


# 課題

- ClamAVのスキャナーアップデート時の更新

[コンストラクトの説明](https://construct-hub-testing.dev-tools.aws.dev/packages/cdk-serverless-clamscan/v/2.6.31/api/ServerlessClamscan?lang=typescript)に、使用するウイルス検索エンジンのClamAVでスキャナーの更新があった際は`cdk deploy`を実行する説明が記載されています。スキャナーに更新があった際の自動更新は設定されていないため、別途仕組みを作る必要があります。

# 参考URL

https://aws.amazon.com/jp/blogs/developer/virus-scan-s3-buckets-with-a-serverless-clamav-based-cdk-construct/
https://construct-hub-testing.dev-tools.aws.dev/packages/cdk-serverless-clamscan/v/2.6.31?lang=typescript
https://github.com/awslabs/cdk-serverless-clamscan