【AWS】CloudShellでVPC内にSIEMを構築してみた

# はじめに

AWSサービスのログの可視化やセキュリティ分析を実現する **[SIEM on Amazon OpenSearch Service](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/README_ja.md)** をVPC内に構築したときのメモです。
AWS CloudShell (Amazon Linux 2023対応)でSIEM環境をデプロイする手順と注意点を共有します。

## 概要

**[SIEM on Amazon OpenSearch Service](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/README_ja.md)** をVPCのプライベートサブネットにデプロイするには CDK を使う必要があり、AWS CloudShell から実行しました。
- CloudShellでセットアップするスクリプト `auto_setup_on_cloudshell.sh` を利用してVPC内にデプロイを実行。
    - VPC内にデプロイする方法については「[高度なデプロイ](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment_ja.md)」を参照ください。
    - 参考：SIEM on Amazon OpenSearch Service - 高度なデプロイ
        - https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment_ja.md
        - ※本記事執筆時点ではCloudShellでデプロイする手順は記載されていません。
:::note warn
CloudShellは操作しないと20～30分でセッションが切れるため、作成実行中に放置するとデプロイに失敗する場合があります。
:::

- 「[再構築方法や失敗時の対応](#参考再構築失敗時の対応)」、「[環境の削除方法](#参考環境の削除)」についてもまとめています。
- EC2で構築する場合は「[参考：EC2/Amazon Linux 2023で構築](#参考ec2amazon-linux-2023で構築) 」を参照ください。

## 事前準備
- デプロイ先について、既存のVPCとサブネットを使うか、新規にVPCを作成するか決めておく必要があります。（後でcdk.jsonで設定）
  - 既存のVPC／サブネットを使う場合は、VPCとサブネットのIDをメモしておく。
  - 新規にVPCを作成する場合は、VPCのIPv4 CIDRブロック (例: 172.30.0.0/24) とサブネットのサイズ (ネットマスク 例: /26) を決めておく。

:::note warn
デフォルトでは、VPCエンドポイントが作成されます。（S3/SQS/SSM/STS）
VPCエンドポイントを作成したくない場合は、事前に `auto_setup_on_cloudshell.sh` スクリプトの修正が必要です。
- スクリプトの修正方法 → [参考：VPCエンドポイントを作成したくない場合](#参考vpcエンドポイントを作成したくない場合)
:::

## セットアップ手順
- 今回実行した環境：
  - AWS CloudShellのバージョン: `6.1.61-85.141.amzn2023.x86_64 (Amazon Linux 2023)`
  - SIEM on Amazon OpenSearch Serviceのバージョン: `2.10.2a`
    - ※CloudShellは2023/12/4からAmazon Linux 2023になり、`main`ブランチではエラーになるため、AL2023対応している **`develop`** ブランチで確認しています。

### 1. ダウンロードとスクリプト実行
- GitHubからダウンロードする (git clone)
    ```shell-session:CloudShell
    $ git clone https://github.com/aws-samples/siem-on-amazon-opensearch-service.git
    $ cd siem-on-amazon-opensearch-service/
    ```

    - 現時点ではAL2023に対応している **`develop`** ブランチに切り替えが必要だった
        ```
        $ git switch develop
        ```
- **`deployment/auto_setup_on_cloudshell.sh`** を実行する
    ```
    $ cd deployment/
    $ ./auto_setup_on_cloudshell.sh
    ```

### 2. 環境変数の設定
- AWSアカウントIDとリージョンが聞かれるので指定する。 (default のまま)
    ```shell-session:CloudShell
    ### 2. Setting Environment Variables ###
    Enter CDK_DEFAULT_ACCOUNT: default is [123456789012]: 
    Enter AWS_DEFAULT_REGION to deploy OpenSearch Service: default is [ap-northeast-1]: 
    ```
    
### 3. デプロイ先の指定
- パブリック か VPC にデプロイするか聞かれる → VPC内にデプロイする。
   ```shell-session:CloudShell
    Where do you deploy your system? Enter pulic or vpc: default is [vpc]: 
    ```
    - default: **`vpc`** (メッセージでは `pulic` になっているが `public`のtypo)

### 4. cdk.json の編集
- CloudShellで **`Next Procedure`** が表示されて、一旦スクリプトが止まる。
- Systems Manager(SSM) > パラメータストア に cdk.json が登録されているので、これを編集する必要がある。
  - 一旦、CloudShellは **`n`** で中断するか、そのまま放置する。
  - SSMパラメータストアで **`/siem/cdk/cdk.json`** を編集したら次へ進む
    ```shell-session:CloudShell
    ################################################
    # Next Procedure
    ################################################
    1. Go to Systems Manager / Parameter Store in selected region
       https://console.aws.amazon.com/systems-manager/parameters/siem/cdk/cdk.json/
    2. Check and Edit cdk.json file in Parameter Store
       If you want to update SIEM without changes, please just return 
       see more details https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment.md
    
    func_validate_json
    
    Have you finished editing the cdk.json? [Y(=continue) / n(=exit)]: 
    ```
    
- SSMパラメータストア で cdk.json を編集
    - マネジメントコンソールのSystems Manager > パラメータストア から設定ファイルのcdk.jsonを編集する。
        - 参考：[5-1. SIEM on OpenSearch Service を Amazon VPC 内にデプロイ
](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment_ja.md#5-1-siem-on-opensearch-service-%E3%82%92-amazon-vpc-%E5%86%85%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)

    - 名前: **`/siem/cdk/cdk.json`**
    - 値を編集

    - 例）既存のVPC/サブネットを使用する場合
      - vpc_type: **`"import"`** を指定
      - imported_vpc_id: VPCIDを指定
      - imported_vpc_subnets: プライベートサブネットのIDを複数指定 (3-AZ)
        ```json:SSMパラメータストア: /siem/cdk/cdj.json
        {
          "app": "python3 app.py",
          "versionReporting": false,
          "context": {
            "aws-cdk:enableDiffNoFail": "true",
            "vpc_type_comment": "vpc_type is new or import",
            "vpc_type": "import",
            "imported_vpc_id": "vpc-0123456789abcdefg",
            "imported_vpc_subnets": ["subnet-aaaaaaaaaaaaaaaaa", "subnet-bbbbbbbbbbbbbbbbb", "subnet-ccccccccccccccccc"],
            "aes_domain_name": "aes-siem",
            "s3_bucket_name":{
              "log": "",
              "snapshot": "",
              "geo": ""
            },
            "kms_cmk_alias": "aes-siem-key",
            "organizations": {
              "org_id": "",
              "management_id": "",
              "member_ids": []
            },
            "no_organizations": {
              "aws_accounts": []
            },
            "additional_s3_buckets": [],
            "additional_kms_cmks": []
          }
        }
        ```

    - 例）新規にVPCを作成してデプロイする場合
      - vpc_type: **`"new"`** を指定して、VPCのIPv4 CIDRブロックとサブネットのサイズ (ネットマスク) を指定する
        ```json:SSMパラメータストア: /siem/cdk/cdj.json
          "vpc_type": "new",
          "new_vpc_nw_cidr_block": "172.30.0.0/24",
          "new_vpc_subnet_cidr_mask": "26",
        ```

    - 参考）S3バケット名のカスタマイズする場合：**`s3_bucket_name`** で指定する
        - **`log`**: ログ収集用 (default: `aes-siem-[AWSアカウントID]-log`)
        - **`snapshot`**: スナップショット用 (default: `aes-siem-[AWSアカウントID]-snapshot`)
        - **`geo`**: GeoIPダウンロード用 (default: `aes-siem-[AWSアカウントID]-geo`)

    - 参考）**`kms_cmk_alias`**: KMSカスタマー管理型のキー(CMK)のエイリアスを指定
        - default: `aes-siem-key`

:::note warn
- 存在するS3バケットを指定するとエラーになる
- 存在するCMKのエイリアスを指定するとエラーになる
:::

### 5. CloudShellでデプロイ実行
- cdk.jsonの編集が終わったら、CloudShellで続きを実行する。**`y`** (=continue) でデプロイを進めていく。
    -  一度exitした場合は、再度 **`auto_setup_on_cloudshell.sh`** を実行すればOK
    ```shell-session:CloudShell: auto_setup_on_cloudshell.sh 実行
    Have you finished editing the cdk.json? [Y(=continue) / n(=exit)]: y
    ...
    Is this right? Do you want to continue? 
    Do you continue or exit? [Y(=continue) / n(=exit)]: y
    Continue
    cdk deploy
    
    ...
    Do you wish to deploy these changes (y/n)? y
    aes-siem: deploying... [1/1]
    aes-siem: creating CloudFormation changeset...
    ```
- cdk deployが実行されるので、しばらく待つ。
  - CloudFormationスタック **`aes-siem`** が作成されて実行される。

:::note warn
- 作成完了までに30～40分程度かかる。
    - `✨  Total time: 1966.55s` のようにかかった時間が表示される。
- CloudShellは20～30分間操作がないとセッションが切れるので注意。
    - 時々、CloudShellのターミナル内でマウスクリックするなどすればセッションは切れない。

:::
- 参考：CloudShellのセッションが切れた場合、CloudFormationでエラーになりロールバックされてしまうことがあります。
    ```console:CloudFormationエラー: 考えられる根本原因
    AesSiemDomainConfiguredR2	CREATE_FAILED
    CloudFormation did not receive a response from your Custom Resource. 
    Please check your logs for requestId [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx].
    If you are using the Python cfn-response module, you may need to update your
    Lambda function code so that CloudFormation can attach the updated version.
    ```
    - CloudShell実行中に `Currently in progress: aes-siem, AesSiemDomainDeployedR2` が表示された後、OpenSearch Serviceの作成中はしばらく応答が返らない状態になります。そのまま何も操作しないとセッションが切れてしまい、再接続したらデプロイに失敗していたことがありました。
       
:::note warn
デプロイに失敗した場合は、[再構築失敗時の対応](#参考再構築失敗時の対応) を参考に残骸リソースを削除してから、再度スクリプト実行する必要があります。
:::
    
### 6. 確認
作成状況はCloudFormationスタックのイベントやログを確認できます。
- デプロイ状況はCloudFormtaionスタック`aes-siem` のイベントなどで確認
- ログはCloudShell内の `auto_setup_on_cloudshell-yyyymmdd_hhmmss.log`で確認

作成完了すると、CloudFormation `aes-siem` スタックの **`出力`** タブから接続情報を確認（CloudShell上にも表示される。）

セットアップ後は、マネジメントコンソールの OpenSearch Service や OpenSearch Dashboardにログインして利用開始できる。
- 参考： [AWS サービスの設定方法](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/configure_aws_service_ja.md)

## 参考：VPCエンドポイントを作成したくない場合
デフォルトでは新たにVPCエンドポイントが作成されます。VPCエンドポイントを作成したくない場合は、cdk deployにオプション指定で対応できます。

- [deployment/auto_setup_on_cloudshell.sh](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/deployment/auto_setup_on_cloudshell.sh) スクリプトの cdk deploy 実行部分にオプションのパラメータを指定 (デフォルトではパラメータ無しで実行)
    ```shell:auto_setup_on_cloudshell.sh
    cdk deploy; status=$?
    ```
  - 指定できるパラメータは高度なデプロイの「6.[AWS CDKの実行](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment_ja.md#6-aws-cdk-%E3%81%AE%E5%AE%9F%E8%A1%8C)」を参照
  - CreateS3VpcEndpoint=false
    - VPCにS3ゲートウェイエンドポイントが設定済みの場合 `false` にする。
  - CreateSqsVpcEndpoint、CreateSsmVpcEndpoint、CreateStsVpcEndpoint
    - NATゲートウェイを使う場合や新たにVPCエンドポイントを作成しない場合 `false` にする。
    - `true` の場合、SQS/SSM/STSのVPCエンドポイントが作成されてサブネットに設定される。 (default)
  - 修正例）VPCエンドポイントを使わないようにパラメータを追加
    ```shell:auto_setup_on_cloudshell.sh
    cdk deploy \
      --parameters CreateS3VpcEndpoint=false \
      --parameters CreateSqsVpcEndpoint=false \
      --parameters CreateSsmVpcEndpoint=false \
      --parameters CreateStsVpcEndpoint=false \
      ; status=$?
    ```


## 参考：再構築／失敗時の対応
再構築する場合やエラーで失敗して再度デプロイする際に、同じ名前のリソースが既に存在する場合、`aes-siem`スタックの実行で失敗します。
下記のリソースについては、事前に削除するかcdk.jsonの設定で別名に変更するなど対応が必要になります。
- S3バケット **`aes-siem-[accountID]-log`**、**`aes-siem-[accountID]-snapshot`**、**`aes-siem-[accountID]-geo`** が存在する場合は削除するか、cdk.jsonでバケット名を変更する
- KMS CMKのエイリアス **`aes-siem-key`** を削除するか、cdk.jsonでエイリアス名を変更する（"kms_cmk_alias": "`aes-siem-key`"）
- OpenSearch Service の `aes-siem` ドメインを削除するか、cdk.jsonで別名を指定する（"aes_domain_name": "`aes-siem`"）
:::note warn
CMKはエイリアスを削除する必要がある。CMK自体の無効化や削除予約(最短7日後に削除)をしても、エイリアスは削除されません。
:::

:::note warn
スタック実行でエラーになった場合、S3バケットやCMKが残る場合があります。
CMKはエイリアスの無いキーが作成されている。作成されたCMKは、`説明：CMK for SIEM solution` で判別できます。
:::

## 参考：環境の削除
環境を削除する場合、CloudFormationスタック **`aes-siem`** を削除＋手動でいくつかリソースを削除する必要があります。
- 参考：[SIEM on Amazon OpenSearch Service: クリーンアップ](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/README_ja.md#%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97)

:::note warn
**`aes-siem`スタック削除時にログ収集用のS3バケットポリシーが削除される。**
S3バケットポリシーが削除されると、ログ記録ができなくなるため、ログ収集用S3バケットにログ出力している場合、事前にログ出力先を変更するなど対応を検討。
（ログ設定の変更漏れがあるか心配な場合、事前にS3バケットポリシーを控えておくと、バケットポリシーが消されたらすぐに再設定で対応できる。）
:::
### 1. CloudFormationスタック **`aes-siem`** を削除する
- ログ収集の仕組みが削除される（LambdaやIAMロールなど削除）
- VPCエンドポイントを作成していた場合は削除される
- OpenSearch ServiceやS3バケットは削除されない

### 2. OpenSearch Service **`aes-siem`** ドメインを削除する
- CloudFormationスタックを削除しても、OpenSearch Serviceのドメインは削除されないため、手動で削除が必要
    - CloudFormationスタックよりも先にOpenSearch Serviceを削除してもOK

### 3. その他、残っているリソース
- S3バケット (`log`、`snapshot`、`geo`で指定したもの)
- KMS CMK (キーエイリアス: `aes-siem-key`)
- セキュリティグループ: `aes-siem-AesSiemVpcNoinboundSecurityGroupXXXXXXXX-XXXXXXXXXXXX`
- CloudWatchロググループ: `/aws/OpenSearchService/domains/aes-siem/application-logs`
- CloudWatchロググループ: `/aws/lambda/aes-siem-` で始まるもの 12個
- デプロイ時にVPCを作成した場合、作成されたVPC、サブネット、ルートテーブルは削除されない。

## 参考：EC2/Amazon Linux 2023で構築
「[高度なデプロイ](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment_ja.md) 」に書かれているAmazon Linux 2023のセットアップを参考に、実行したコマンドをまとめると下記になります。（EC2/AL2023とCloudShellで確認）
```bash
sudo dnf install -y git
git clone https://github.com/aws-samples/siem-on-amazon-opensearch-service.git
cd siem-on-amazon-opensearch-service

export CDK_DEFAULT_ACCOUNT=`aws sts get-caller-identity --query 'Account' --output text`
export AWS_DEFAULT_REGION=ap-northeast-1
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y python3-devel python3-pip git jq tar
cd ./deployment/cdk-solution-helper/
chmod +x ./step1-build-lambda-pkg.sh
./step1-build-lambda-pkg.sh
chmod +x ./step2-setup-cdk-env.sh
./step2-setup-cdk-env.sh
source ~/.bashrc
cd ../../
source .venv/bin/activate
cd source/cdk && cdk bootstrap $CDK_DEFAULT_ACCOUNT/$AWS_DEFAULT_REGION

#
# cdk.json を設定後、cdk deployを実行
#
cdk deploy
```
- AWS CloudShell は2023/12/4にAmazon Linux 2023に移行されています。
- SIEM on Amazon OpenSearch Serviceの高度なデプロイも Amazon Linux 2023に対応しています。（Amazon Linux 2を使ったデプロイは非推奨になりました。）

- コマンドについては今度変更になる可能性がありますので、最新の「[高度なデプロイ](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment_ja.md) 」のドキュメントを参照ください。

## まとめ
- CloudShell用のスクリプトを使ってデプロイすることで、EC2やAWS Cloud9で実行する場合に比べて簡単にデプロイできると思います。
- CloudShellの場合は、無操作によるセッションタイムアウトでデプロイが失敗する場合があるため、デプロイ実行中に20分以上放置しないようにしましょう。
- 開発中のSIEM on Amazon OpenSearch Serviceを使ってみたい場合は、`develop`ブランチで試すことができます。（現時点ではdeployブランチでCloudShellのスクリプトもAmazon Linux 2023に対応済み）
:::note warn
CloudShellでデプロイする方法については、本記事執筆時点ではドキュメントには書かれていないため、自己責任でご利用ください。
:::