CDKでIaC ganeratorを使ってみた:S3編

# はじめに
2024/2/6に発表された情報で、IaC generatorにおいて、コンソールで作成した既存のAWS環境をスキャンして、cdkへ変換できるようになりました。
>https://aws.amazon.com/jp/blogs/news/import-entire-applications-into-aws-cloudformation/


# 何がすごいのか
- コンソールで作成したAWS環境を、CDKを使用したコードに変換することができる
- コンソールで作成したAWS環境をコード管理することができる

# コンソールで作成したS3をコード化＆追加で変更してみた
今回は、新規でS3バケットを作成し、ライフサイクルポリシーを設定しているリソースをスキャンしてCDK化します。CDKをデプロイし、既存リソースのS3と同期します。リソースとCDKが同期したら、CDKにライフサイクルの設定を追記し、再度デプロイを行い、既存のS3バケットにCDKで作成したリソースが追加されるかを試します。

# ポイント
- タグキーを使用して、スキャンしたいリソースを絞る
読み取りリソースの数が多いとエラーとなってしまうので、
リソースにタグ(key, value)を設定し、cdkに変換するコマンドで、設定したkeyを指定します。

今回は、
key=migrate-cdk,
value=test
にしました。

## 前提条件
CDバージョン: v2.126.0

CDK バージョン確認
```
cdk --version
```

私の場合は、2.116.1と古かったので、下記のコマンドでアップデートしました。
```
npm install -g aws-cdk
```

## S3バケットをコンソールで作成




CLIでコードを変換
```
cdk migrate --language typescript --from-scan new  --stack-name cdk-migrate-test-s3 --filter tag-key=migrate-cdk
```

実行結果
```
✅ Scan Complete!mental feature and development on it is still in progress. We make no guarantees about the outcome or stability of the functionality.
Using the latest successful scan which is 0 days, 0 hours, and 7 minutes old.
Applying filters to resource scan.wait, this can take 10 minutes or longer.
finding related resources.
Found 1 resources.
Generating CFN template from scanned resources.
Please wait, template creation in progress. This may take a couple minutes.
[CREATE_IN_PROGRESS] Template Creation in Progress
Template successfully generated!
 ⏳  Generating CDK app for cdk-migrate-test-s3...
Applying project template app for typescript
Initializing a new git repository...
・
（中略）
・
Executing npm install...
✅ All done!
 ⚠️  Some resources could not be migrated completely. Please review the README.md file for more information.
```

変換が完了しました。私の場合は、約30分かかりました。


CloudFormationのIaCジェネレータにテンプレートが作成され、
cdk-migrate-test-s3というフォルダと、CDKのファイル群が生成されます。

変換されたコードがこちらになります。
```/cdk-migrate-test-s3/lib/cdk-migrate-test-s3-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

export interface CdkMigrateTestS3StackProps extends cdk.StackProps {
}

export class CdkMigrateTestS3Stack extends cdk.Stack {
  public constructor(scope: cdk.App, id: string, props: CdkMigrateTestS3StackProps = {}) {
    super(scope, id, props);

    // Resources
    const s3Bucket00testmigratecdkscans300yPmn6 = new s3.CfnBucket(this, 'S3Bucket00testmigratecdkscans300yPMN6', {
      publicAccessBlockConfiguration: {
        restrictPublicBuckets: true,
        ignorePublicAcls: true,
        blockPublicPolicy: true,
        blockPublicAcls: true,
      },
      bucketName: 'test-migrate-cdk-scan-s3',
      ownershipControls: {
        rules: [
          {
            objectOwnership: 'BucketOwnerEnforced',
          },
        ],
      },
      bucketEncryption: {
        serverSideEncryptionConfiguration: [
          {
            bucketKeyEnabled: true,
            serverSideEncryptionByDefault: {
              sseAlgorithm: 'AES256',
            },
          },
        ],
      },
      
      lifecycleConfiguration: {
        rules: [
          {
            status: 'Enabled',
            id: 'test-1year',
            prefix: '/test',
            noncurrentVersionExpiration: {
              noncurrentDays: 30,
            },
            expirationInDays: 364,
          },
        ],
      },
      
      versioningConfiguration: {
        status: 'Enabled',
      },
      tags: [
        {
          value: 'test',
          key: 'migrate-cdk',
        },
      ],
    });
    s3Bucket00testmigratecdkscans300yPmn6.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN;
  }
}

```
cdk diffで比較してみます。

```
cdk diff
```
実行結果
```

Stack cdk-migrate-test-s3
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Could not create a change set, will base the diff on template differences (run again with -v to see the reason)
Parameters and rules created during migration do not affect resource configuration.
Parameters
[+] Parameter BootstrapVersion BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}

Conditions
[+] Condition CDKMetadata/Condition CDKMetadataAvailable: {"Fn::Or":[{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"af-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-northwest-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-3"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"il-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"sa-east-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}]}

Resources
[+] AWS::S3::Bucket S3Bucket00testmigratecdkscans300yPMN6 S3Bucket00testmigratecdkscans300yPMN6

Other Changes
[+] Unknown Rules: {"CheckBootstrapVersion":{"Assertions":[{"Assert":{"Fn::Not":[{"Fn::Contains":[["1","2","3","4","5"],{"Ref":"BootstrapVersion"}]}]},"AssertDescription":"CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."}]}}


✨  Number of stacks with differences: 1
```


## CDKをデプロイ
```
cdk deploy
```
## 実行結果
CDKとAWS環境を同期することができました。
```
✨  Synthesis time: 6.31s

cdk-migrate-test-s3: creating stack for resource migration...
cdk-migrate-test-s3: importing resources into stack...
cdk-migrate-test-s3: creating CloudFormation changeset...
cdk-migrate-test-s3 | 0/2 | 9:25:33 | IMPORT_IN_PROGRESS   | AWS::CloudFormation::Stack | cdk-migrate-test-s3 User Initiated
cdk-migrate-test-s3 | 0/2 | 9:25:35 | IMPORT_IN_PROGRESS   | AWS::S3::Bucket | S3Bucket00testmigratecdkscans300yPMN6 Resource import started.
cdk-migrate-test-s3 | 0/2 | 9:25:38 | IMPORT_IN_PROGRESS   | AWS::S3::Bucket | S3Bucket00testmigratecdkscans300yPMN6
cdk-migrate-test-s3 | 1/2 | 9:25:39 | IMPORT_COMPLETE      | AWS::S3::Bucket | S3Bucket00testmigratecdkscans300yPMN6 Resource import completed.
cdk-migrate-test-s3 | 1/2 | 9:25:41 | UPDATE_IN_PROGRESS   | AWS::S3::Bucket | S3Bucket00testmigratecdkscans300yPMN6 Apply stack-level tags to imported resource if applicable.
cdk-migrate-test-s3 | 0/2 | 9:26:06 | UPDATE_COMPLETE      | AWS::S3::Bucket | S3Bucket00testmigratecdkscans300yPMN6
cdk-migrate-test-s3 | 1/2 | 9:26:08 | IMPORT_COMPLETE      | AWS::CloudFormation::Stack | cdk-migrate-test-s3

 ✅  cdk-migrate-test-s3

✨  Resource migration time: 42.24s


 ✅  cdk-migrate-test-s3

✨  Resource migration time: 42.24s

cdk-migrate-test-s3: applying CDKMetadata and Outputs to stack (if applicable)...
cdk-migrate-test-s3:  start: Building 4110a55191e1b6658121e64fb4f2dd5aab310d58df30f23bababfe8cc69f352d:current_account-current_region
cdk-migrate-test-s3:  success: Built 4110a55191e1b6658121e64fb4f2dd5aab310d58df30f23bababfe8cc69f352d:current_account-current_region
cdk-migrate-test-s3:  start: Publishing 4110a55191e1b6658121e64fb4f2dd5aab310d58df30f23bababfe8cc69f352d:current_account-current_region
cdk-migrate-test-s3:  success: Published 4110a55191e1b6658121e64fb4f2dd5aab310d58df30f23bababfe8cc69f352d:current_account-current_region
cdk-migrate-test-s3: deploying... [1/1]

 ✅  cdk-migrate-test-s3 (no changes)

✨  Deployment time: 0.15s
```

## 変換したCDKコードにライフサイクルを追記


下記が追加したCDKになります。
```/cdk-migrate-test-s3/lib/cdk-migrate-test-s3-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

export interface CdkMigrateTestS3StackProps extends cdk.StackProps {
}

export class CdkMigrateTestS3Stack extends cdk.Stack {
  public constructor(scope: cdk.App, id: string, props: CdkMigrateTestS3StackProps = {}) {
    super(scope, id, props);

    // Resources
    const s3Bucket00testmigratecdkscans300yPmn6 = new s3.CfnBucket(this, 'S3Bucket00testmigratecdkscans300yPMN6', {
      publicAccessBlockConfiguration: {
        restrictPublicBuckets: true,
        ignorePublicAcls: true,
        blockPublicPolicy: true,
        blockPublicAcls: true,
      },
      bucketName: 'test-migrate-cdk-scan-s3',
      ownershipControls: {
        rules: [
          {
            objectOwnership: 'BucketOwnerEnforced',
          },
        ],
      },
      bucketEncryption: {
        serverSideEncryptionConfiguration: [
          {
            bucketKeyEnabled: true,
            serverSideEncryptionByDefault: {
              sseAlgorithm: 'AES256',
            },
          },
        ],
      },
      
      lifecycleConfiguration: {
        rules: [
          {
            status: 'Enabled',
            id: 'test-1year',
            prefix: '/test',
            noncurrentVersionExpiration: {
              noncurrentDays: 30,
            },
            expirationInDays: 364,
          },
          {
            status: 'Enabled',
            id: 'test-1year-hoge',
            prefix: '/hoge',
            noncurrentVersionExpiration: {
              noncurrentDays: 30,
            },
            expirationInDays: 364,
          },
        ],
      },
      
      versioningConfiguration: {
        status: 'Enabled',
      },
      tags: [
        {
          value: 'test',
          key: 'migrate-cdk',
        },
      ],
    });
    s3Bucket00testmigratecdkscans300yPmn6.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN;
  }
}

```

## ライフサイクルを追加したCDKをテンプレートに変換
```
cdk synth
```

## デプロイでライフサイクルを追加
```
cdk deploy
```
## 実行結果
![変更後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671603/452f94ea-c18d-f8ba-234f-1132f5fa5932.png)

「test-1year-hoge」という、ライフサイクルを追加することができました。

# 感想
　過去にコンソールで作成した環境は、CDK化して管理することをあきらめていましたが、既存環境をスキャンしてCDK化できるようになったので、CDKで管理・運用できる幅が広がったので、正直この機能は誕生して嬉しかったです。CDKのスキャンで、どこまでコードと実環境が同期できるのか、今後も様々なパターンを試してみます。