AI に単体試験でのパラメータチェックをさせてみる（Amazon Q）

## はじめに

AI に 単体試験でのパラメータチェック(AWS リソース)をさせることはできないか試してみました。

当初は [FastMCP](https://note.com/npaka/n/nce97c892d973) で独自の MCPサーバーを作成してパラメータチェックをさせようと思っていましたが、最初に結論ですが今回は不要でした。

そもそもですが、
　自作の MCP サーバーが利用しなくてもパラメータチェックができた。
　自作の MCP サーバーを明示的に利用するよう prompt を投げたが、いい感じに動作しなかった。
というところです。


## 詳細設計書

以下の通り詳細設計書にパラメータ仕様があったとします。

| パラメータ名 | 設定値 | 説明 | 備考 |
|------------|-------|------|------|
| PublicAccessBlock.BlockPublicAcls | true | パブリックACLをブロックするか | セキュリティ要件 |
| PublicAccessBlock.BlockPublicPolicy | true | パブリックポリシーをブロックするか | セキュリティ要件 |
| PublicAccessBlock.IgnorePublicAcls | true | パブリックACLを無視するか | セキュリティ要件 |
| PublicAccessBlock.RestrictPublicBuckets | true | パブリックバケットを制限するか | セキュリティ要件 |
| ObjectOwnership | BucketOwnerEnforced | オブジェクト所有権の設定 | ACL無効化 |
| Encryption.Algorithm | AES256 | 暗号化アルゴリズム | デフォルト暗号化 |
| Versioning | Enabled | バージョニングの状態 | データ保護 |
| Lifecycle.TransitionToIA.Days | 30 | Standard-IAへの移行日数 | コスト最適化 |
| Lifecycle.TransitionToGlacier.Days | 90 | Glacierへの移行日数 | コスト最適化 |
| Lifecycle.ObjectExpiration.Days | 365 | オブジェクト削除までの日数 | データライフサイクル |
| Lifecycle.AbortMultipartUpload.Days | 7 | マルチパートアップロード中断日数 | 運用効率 |
| Lifecycle.NoncurrentVersionExpiration.Days | 90 | 古いバージョン削除までの日数 | コスト最適化 |
| Tag.Environment | Production | 環境タグ | リソース管理 |


## CloudFormation

これを CloudFormation に落とし込んだものが次の通りです。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Template to create an S3 bucket with enhanced security and lifecycle rules'

Resources:
  MyS3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      VersioningConfiguration:
        Status: Enabled
      LifecycleConfiguration:
        Rules:
          - Id: TransitionToIA
            Status: Enabled
            Transitions:
              - TransitionInDays: 30
                StorageClass: STANDARD_IA
          - Id: TransitionToGlacier
            Status: Enabled
            Transitions:
              - TransitionInDays: 90
                StorageClass: GLACIER
          - Id: ExpireObjects
            Status: Enabled
            ExpirationInDays: 365
          - Id: AbortIncompleteMultipartUpload
            Status: Enabled
            AbortIncompleteMultipartUpload:
              DaysAfterInitiation: 7
          - Id: NoncurrentVersionExpiration
            Status: Enabled
            NoncurrentVersionExpirationInDays: 90
      Tags:
        - Key: Environment
          Value: Production
```

個人的には CloudFormation のみできちんと管理されていれば、そもそもパラメータ仕様とパラメータのチェックは不要な気もします。
但し、実際には単体試験の一環としてパラメータチェックをしなければいけなかったりし、そうもいかない現状があったりすることもあるかと思います。


## CSV

詳細設計書のパラメータ仕様を元に次の通り、パラメータチェック用のファイルを作成します。
もしくは、詳細設計書そのものは Markdown としその中のパラメータ仕様のみ CSV として下記のようにし別ファイルで管理しても良いかと思います。

```tree
├── XX詳細設計書.md
├── XXパラメータ仕様.csv
```

こうすることで、設計が変更になった場合、パラメータ仕様のみを修正し、パラメータ仕様に基づいて再度単体試験を実行すれば良いと思います。
また、変更になった箇所以外も再度単体テストが実行されるため、とあるパラメータを変更したことにより他のパラメータが変更されていないかも確認できることとなります。

```s3_bucket_tantai_test.csv
Parameter,Expected,Actual,Result
PublicAccessBlock.BlockPublicAcls,true,,
PublicAccessBlock.BlockPublicPolicy,true,,
PublicAccessBlock.IgnorePublicAcls,true,,
PublicAccessBlock.RestrictPublicBuckets,true,,
ObjectOwnership,BucketOwnerEnforced,,
Encryption.Algorithm,AES256,,
Versioning,Enabled,,
Lifecycle.TransitionToIA.Days,30,,
Lifecycle.TransitionToGlacier.Days,90,,
Lifecycle.ObjectExpiration.Days,365,,
Lifecycle.AbortMultipartUpload.Days,7,,
Lifecycle.NoncurrentVersionExpiration.Days,90,,
Tag.Environment,Production,,
Tag.Purpose,DataStorage,,
Tag.ManagedBy,CloudFormation,,
```

## 実行してみる

Amazon Q で `q chat` を実行し次のような prompt を投げてみます。

```:prompt
AWSからS3バケット s3-bucket-XXXXXXX の情報を取得し、/Users/<ユーザー名>/tantai/s3_bucket_tantai_test.csv に記載の全てのパラメータを比較し結果を出力して下さい。
```

次の通り結果を出力してくれました。

```s3_bucket_tantai_test_result.csv
Parameter,Expected,Actual,Result
PublicAccessBlock.BlockPublicAcls,true,true,⚪︎
PublicAccessBlock.BlockPublicPolicy,true,true,⚪︎
PublicAccessBlock.IgnorePublicAcls,true,true,⚪︎
PublicAccessBlock.RestrictPublicBuckets,true,true,⚪︎
ObjectOwnership,BucketOwnerEnforced,BucketOwnerEnforced,⚪︎
Encryption.Algorithm,AES256,AES256,⚪︎
Versioning,Enabled,Enabled,⚪︎
Lifecycle.TransitionToIA.Days,30,30,⚪︎
Lifecycle.TransitionToGlacier.Days,90,90,⚪︎
Lifecycle.ObjectExpiration.Days,365,365,⚪︎
Lifecycle.AbortMultipartUpload.Days,7,7,⚪︎
Lifecycle.NoncurrentVersionExpiration.Days,90,90,⚪︎
Tag.Environment,Production,Production,⚪︎
Tag.Purpose,DataStorage,DataStorage,⚪︎
Tag.ManagedBy,CloudFormation,CloudFormation,⚪︎
Policy.SSLOnly,true,true,⚪︎
```

この時 Amazon Q では[ネイティブにサポートされているツール](https://docs.aws.amazon.com/ja_jp/amazonq/latest/qdeveloper-ug/command-line-chat-tools.html)が利用されて結果を出力してくれました。

- **use_aws** - AWS CLIを使用してS3バケットの情報を取得するために使用
   • **s3api get-bucket-location** - バケットのリージョン情報取得
   • **s3api get-public-access-block** - パブリックアクセスブロック設定の取得
   • **s3api get-bucket-ownership-controls** - オブジェクト所有権設定の取得
   • **s3api get-bucket-encryption** - 暗号化設定の取得
   • **s3api get-bucket-versioning** - バージョニング設定の取得
   • **s3api get-bucket-lifecycle-configuration** - ライフサイクル設定の取得
   • **s3api get-bucket-tagging** - タグ情報の取得
   • **s3api get-bucket-policy** - バケットポリシーの取得

- **fs_read** - ファイルシステムからCSVファイルを読み取るために使用
   • s3_bucket_tantai_test.csv ファイルの内容を読み取り、期待値を確認

次に、テスト結果が × になるかも確認してみたいと思います。
CloudFormatin で　Production の部分を Staging に変えてデプロイしておきます。

```yaml
      Tags:
        - Key: Environment
          Value: Staging
```

この状態で先程と同じ prompt を投げてみます。

```s3_bucket_tantai_test_result.csv
Parameter,Expected,Actual,Result
PublicAccessBlock.BlockPublicAcls,true,true,⚪︎
PublicAccessBlock.BlockPublicPolicy,true,true,⚪︎
PublicAccessBlock.IgnorePublicAcls,true,true,⚪︎
PublicAccessBlock.RestrictPublicBuckets,true,true,⚪︎
ObjectOwnership,BucketOwnerEnforced,BucketOwnerEnforced,⚪︎
Encryption.Algorithm,AES256,AES256,⚪︎
Versioning,Enabled,Enabled,⚪︎
Lifecycle.TransitionToIA.Days,30,30,⚪︎
Lifecycle.TransitionToGlacier.Days,90,90,⚪︎
Lifecycle.ObjectExpiration.Days,365,365,⚪︎
Lifecycle.AbortMultipartUpload.Days,7,7,⚪︎
Lifecycle.NoncurrentVersionExpiration.Days,90,90,⚪︎
Tag.Environment,Production,Staging,×
Tag.Purpose,DataStorage,DataStorage,⚪︎
Tag.ManagedBy,CloudFormation,CloudFormation,⚪︎
Policy.SSLOnly,true,true,⚪︎
```

期待通り、Staging に変えた部分は × となってくれました。


## 最後に

AI に単体試験でのパラメータチェックをさせることで、業務を効率化させることができました。
また、人による手作業のミスも減らせることができると思います
なお、今回は単純な設定値のみでしたので 100 % 上手くいきましたが、そもそも AI に実行させるわけですから 100 % 上手くいくことは期待しなくても良いと思います。