Claude CodeでCDKリバースエンジニアリング
こんにちは、ナイル 自動車産業DX事業部 CTOの大浜です。
AWS上のインフラを構築する際、CDKやTerraformといったツールを利用してCode化する、というIaC(Infrastructure as Code)はごく一般的なものになりつつあります。
しかし、既に本番稼働しているサービスがある場合、そのすべてをIaC化する、というのはサービス継続や費用対効果の面でなかなか難しいものがありますね。
また、構成がある程度以上複雑で試行錯誤しながら作る場合、いきなりIaCを書き始めるよりはまずAWSコンソール上インフラを立ち上げ、ある程度設計が固まってからIaC化に着手する、という手法が現実的な場合も多いかと思います。
とはいえ、IaCに慣れてしまった身としては、コンソールから手作業で作成されているインフラでいざ修正やトラブルがあった場合、設計書や現実のコンソールを見ながらの対応となり、「コードがあれば…」と思うシーンも多いのではないでしょうか。
今回はそういった課題に対するソリューションとして、「まず、AWSコンソールでインフラを構築した後、それをClaude CodeでCDKに変換する」といった実験を行ってみました。
これがスムーズにできれば、「設計書」としてのCDKの活躍の幅が広がりますし、場合によっては出来上がったコードをもとに環境の移転や再構成も簡単に実現できそうです。
対象の構成
今回、事業部では新たにとあるSaaSサービスが提供しているAPIを利用することとなりました。これは機密データを扱う関係上、専用線を自社データセンターに敷設するか、AWS Direct Connectなどのサービスを利用して専用線をクラウドに引き込むことが求められています。
Direct Connectの制約上、通信先のネットワークはIPアドレス範囲が指定されるため、新たにVPCを作って専用線との通信を確立したうえで、そのネットワークに対してピアリング接続やALBなどの外部接続を通して既存環境からアクセスできるようにする必要があります。
また、DNSサーバもデータセンター側にあるものを参照することになるため、VPC上にあるRoute53 Resolverにアウトバウンドエンドポイントを追加し、DNS問い合わせを転送できる必要があります。
さらにネットワークを保護するためにVPCをprivateとpublicに分離し、データセンターに直接アクセスできるネットワークをNAT経由でのみインターネットに接続できるようにすることで、より安全な構成となるでしょう。
ネットワーク構成図としてはこのような感じでしょうか。

…と、分かったように書いていますが、
これらはすべて手探りでAWSの膨大なドキュメントとcurlとdigにお世話になりながら解明していった構成となります。
長年インフラ構築に携わっていても、それが専門でない限り専用線とクラウドの接続のようなミッションはそう何度も出会えるわけではありません。
実際にはAWSコンソールの独特な用語を理解しながら、少しずつ設定を進め、通信状況を確認しながら割り出していくことになります。
今回のケースではIPアドレスでの通信が開通した後、名前解決を転送するのにRoute53を利用する、というのは発想として中々出てこなくて調査にだいぶ苦労した感があります。
このあたりの資料に大変お世話になりました
Route 53 ResolverによるDX環境の名前解決
単一アカウントの AWS 環境でハイブリッドネットワークの DNS 解決を設定
こうした試行錯誤をIaCでやる、というのはコーディングそのものに掛かる時間や1回のdeploy/rollbackに掛かる時間を考えるとあまり現実的ではなく、結局のところAWSコンソールで少し設定を変えてdig、少し設定を変えてcurl、と手探りで進めていくのが一番シンプルで早かったりします。
リバースエンジニアリングしてCDK化
さてこうして構成が出来上がったわけですが、これを使って本稿の目的通り、AIを使ってCDKコードに変換していきます。
AIエージェントはClaude Code + VSCode Extensionを用い、モデルはAWS Bedrock上にあるclaude-sonnet-4を利用しています。
余談ですが、AWSを利用している場合Bedrock上のモデルを使うと新たにAPI課金が発生しない(AWSの料金に含まれる)ため、AI利用に会社への予算申請が必要なことの多い日本の企業ユーザには大変おすすめです。
この環境にAWS公式から出ているCore/Documentation/CDKの3つのMCPサーバと、filesystemやgithubなど、開発手順をサポートしてくれるMCPサーバ群を導入しておきます。
AWS MCP Servers
https://github.com/awslabs/mcp/tree/main/src/core-mcp-server
https://github.com/awslabs/mcp/tree/main/src/aws-documentation-mcp-server
https://github.com/awslabs/mcp/tree/main/src/cdk-mcp-server
Claude Codeに上記のURLを書いて「このMCPサーバを導入して」と依頼するだけで.mcp.jsonを適切に書き換えてくれるので、導入自体は非常に簡単です。Access Tokenやcredential等の機密情報の取り扱いだけ、自身で気をつける必要があるぐらいでしょうか。
このように環境を整えたら、AIにリバースエンジニアリングを依頼します。
* AWSアカウント上のxxx-vpcには以下のようなオブジェクトが設置されています。
* AWSに接続して実際の設定を調査の上、VPC自体と必要なオブジェクトを作成するCDKコードを生成してください。
* IPアドレスやCIDR、タグ等は実際の値をそのまま利用してください。
* なお、CDKで実現できない設定が存在する場合は、aws cliコマンドとしてREADME.mdに記載してください。
### オブジェクト
* 以下のような構成のxxx-vpcを構築する
* private-subnetおよびpublic-subnet各1つ
* public-subnet上に1つのNATゲートウエイ。private-subnetはNAT経由でインターネット通信を行う
* 既存のdevelopment-vpc/production-vpcに対するピアリング接続(PCX)
* Direct Connectに接続するVirtual Private gateway(VPW)
* private-subnetのルートテーブルにPCXとVPWにルーティングするルートを記載
* VPC内のDNSクエリを転送するRoute53 ResolverとRule
このぐらいの記述から初めて大丈夫そうです。実際の設定はClaudeがaws cliを何度も実行して調べてくれます。
ただし、一般的でないオブジェクトの記載を省略すると存在に気づけないらしく「無いもの」として扱われてしまう場合があるので注意が必要です。
実は構成図や初回のプロンプトに書き忘れていたクライアントVPN接続がVPC内に存在していたのですが、見事にスルーされていました。
大体20分ぐらいで初回のCDKコード出力が終わったかと思います。
この後、先ほど忘れていたネットワーク検証のためのクライアントVPN接続を追加し、Fargateで検証用コンテナを立ち上げるなどのStackを追加して完了となります。
実際の出力の一部
import aws_cdk as cdk
from aws_cdk import (
Stack,
aws_ec2 as ec2,
aws_certificatemanager as acm,
aws_route53resolver as route53resolver,
aws_logs as logs,
Tags,
)
from constructs import Construct
class xxxVpcStack(Stack):
"""xxx VPC Stack - Reproduces existing xxx-vpc configuration"""
def __init__(self, scope: Construct, construct_id: str, site_module, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# VPC Configuration based on existing xxx-vpc
# CIDR: 10.90.13.0/24
self.vpc = ec2.Vpc(
self,
"xxxVpc",
vpc_name="xxx-vpc",
ip_addresses=ec2.IpAddresses.cidr("10.90.13.0/24"),
max_azs=1, # Using only ap-northeast-1a based on existing config
subnet_configuration=[
ec2.SubnetConfiguration(
name="xxx-subnet-private1",
subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS,
cidr_mask=27, # 10.90.13.0/27
),
ec2.SubnetConfiguration(
name="xxx-subnet-public",
subnet_type=ec2.SubnetType.PUBLIC,
cidr_mask=27, # 10.90.13.128/27
),
],
nat_gateways=1,
enable_dns_hostnames=True,
enable_dns_support=True,
)
...(以下続く)結果と考察
結果、概ね数時間程度で手作業作成のVPC環境をCDKに移植できました。
良かった点は次の通り
既にいくつかcdkアプリのあるリポジトリに新しいapp.pyを追加する形だったので、既存のStack構成ルールを引き継いで書いてくれた
概ねきちんとネットワーク構成を再現してくれた
最終的にcdk deployが通り、オブジェクトを全て再現できた
自分でほぼコードを書くことがなく、cdkアプリが完成した
対してうーん、となった点
一部現実と合わないIPアドレスとなった
一般的にsubnet構成する場合public→privateの順にIPアドレス範囲(CIDR)を割り当てていくことが多いかと思いますが、今回はDirect Connectの制約上、private-subnetのIPアドレス範囲が前に来るような特殊な設定になっていました。
しかしこれがAIには理解できなかったようで、「一般的な」ルールに従って記述してしまい、通信ができない、というエラーとなってしまいました。
膨大なデータから「普通はこう」という判断をしがちなAI特有の課題かなと思います
cdk deployが通るまでに2-3回修正が必要だった
上記CIDRが逆になっていたことによる問題の他、ゲートウェイの構築が終わっていないのにルートテーブルの編集が並行して動いてしまってエラーとなっていました。
これは自身でcdkを書いてもたまに起こる現象で、回避策も用意されています。AIに指示してすぐ修正できました。
そして広がるCDKの夢
少し特殊なネットワーク構成の再現実験でしたが、数時間でcdkを組み上げられたのはかなり秀逸な実験結果となりました。
cdk、terraformなどのIaCはその再現性、冪等性、修正容易性など様々なメリットがあるものの、自分で書くとなると膨大なコマンド群とそれぞれのオプション群をドキュメントから拾い出し、一つ一つ記載していかなければならないという点がコンソール画面からの構築に比べてはるかに手がかかり、普及を妨げていた面も否めません。
この記事ではAIエージェントを使うことによってVPCという基盤にあたるリソースに対してもリバースエンジニアリングの可能性が示されましたが、RDSやEC2、ECS、Lambdaなど、より上位層のリソースであればもっと簡単に移植できるでしょう。
これまで導入をためらっていた膨大な既存リソースを抱えている層も積極的な導入検討が進むことを期待しています。
