【AWS】構成図から IaC を出力するシステムの作り方（Bedrock / Terraform）

クラウドサービス使ってると、構成図を書くことがとても多いと思います。そして書くたびに「このまま IaC 出力できないかなぁ...」って思ったりしないでしょうか？この記事ではそんな夢に、少しだけ近づけるシステムの作り方をご紹介します:sleepy:

## 構成図
構成はとてもシンプルで、以下のような動作をします。

1. 構成図を S3 にアップロード
2. Lambda が動きだして、Bedrock で IaC 出力
3. Bedrock から Lambda に返ってきたコードを GitHub に出力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/af501aa6-6eb8-3302-b0b1-8e2f8a20adce.png)

## 参考資料
本システムは CI/CD の機能を追加して過去に LT しました。このスライドを読めば、楽しく全容がつかめるのでぜひご一読ください。

https://speakerdeck.com/hiyanger/pull-request-kara-terraform-plan-madezi-dong-dedong-zuo-surusisutemu

スライドでは CI/CD まで組んでいますが、本記事では IaC までの出力としています。CI/CD は HCP Terraform で組んでいるので、ここまでやりたい方は下の記事のハンズオンを組み合わせてみてください🙏

https://qiita.com/hiyanger/items/ff84c71775f6bc36363b#%E3%83%8F%E3%83%B3%E3%82%BA%E3%82%AA%E3%83%B3

## 作り方
ここからは実際にシステムを作っていきます。

:::note warn

LLM は「Claude 3.5 Sonnet」です。2024年10月時点でこの LLM は東京リージョンに存在していましたが、Lambda から Bedrock API を動作させることができませんでした。そのため本記事は、バージニアリージョンでシステムを作成しています。

また、本システムは上記の通り、Bedrock API を使った簡易的なシステムです。より精度を求めるのであれば、本記事のネタを元に RAG などの構築を検討してください。
:::

### 1. S3
S3 を作成しましょう。とくに意識することはありません。

![スクリーンショット 2025-01-05 1.38.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/ccb615bb-42ae-9f7f-c29d-efe235aa5f32.png)

### 2. Bedrock
使いたいモデルアクセスを有効化しましょう。リクエストされていなければリクエストします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/654f3ac1-1a83-8532-7fc2-7497e030b7a2.png)

### 3. GitHub
Lambda から GitHub へ `push` できるようにトークンを発行します。

1. 画面右上のプロフィールアイコン
2. Settings
3. Developer settings
4. Personal access tokens 
5. repo にチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/1afffec0-2926-8e6a-4666-7c6a4d5e81ea.png)

### 4. Lambda
本システムの肝になる Lambda です。

#### トリガー作成（S3）
Lambda は動かすためのトリガーが必要です。ここでは S3 がアップロードされたら動作するようにします。

![スクリーンショット 2025-01-05 1.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/634dd6b3-36ea-49aa-14d8-39c257f7a6b7.png)

#### Lambda
処理は以下のような流れです。

1. S3 から画像をダウンロード
2. Bedrock 呼び出し
3. Terraform コードを取得
4. GitHub へ push

コードに下記を記述します。

:::note warn

コードはとりあえず動くレベルのものなので、お仕事などで使う場合は内容を精査してからご使用ください。

後述の出力のためにプロンプトをそこそこ仕込んでいます。

:::

https://github.com/hiyanger/diagram-to-terraform-cicd-lambda/blob/master/diagram-to-terrform-cicd-refactoring.py

## 実際に動かしてみる

### S3 に構成図をアップロード
とりあえず、VPC と EC2 を使った簡易的な構成図（.jpg）を S3 にアップロードしてみましょう。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/4a0b4238-5fec-f1d7-fda5-8f424d680646.png">

### 出力された Terraform コード
S3 にアップしたら GitHub へ出力されたコードを確認してみます。

```hcl
provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support = true

  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "Public Subnet"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "Main IGW"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name = "Public Route Table"
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

resource "aws_instance" "example" {
  ami           = "ami-0c3fd0f5d33134a76" # Amazon Linux 2 AMI in Tokyo region
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.public.id
  
  tags = {
    Name = "Example Instance"
  }
}
```

以上です！

下記に当時実際に検証したときの情報をのせておきます。

https://zenn.dev/hiyanger/scraps/feed5feddfc01a

# ※ 派生版（Web からプロンプト入力させる版）
派生版として Web からプロンプトを入力して IaC（CI/CD） を生成するシステムも作ったので、よかったらこちらも使ってみてください。

https://speakerdeck.com/hiyanger/mouituso-aws-dekinakutemo-aws-dekiruyouninarusisutemuzuo-tuta

https://github.com/hiyanger/prompt-to-terraform-cicd

## さいごに（本システムの精度について）

記事冒頭で紹介したスライドを見ていただくとわかるのですが、このシステムは手書きの雑な構成図でも出力することができました。

しかし、AWS アイコンを使った構成図でもリソースが増えて、構成図が複雑になると Terraform のリソース出力がまちまちになってしまいました。Lambda のコードの通りですが、VPC と EC2 のシンプルな構成図でもそれなりのプロンプトを仕込む必要がありました。

現状では実用性を求めるならプロンプトを大量に仕込んだり、もしくはそこまでするなら、アイコンと IaC を紐づけたデータを作って RAG にしてしまった方が良さそうです。API だけで完結してくれるようになるには、まだまだ時間がかかりそうですね。AI の進化も難しくなってきた感がありますが、もう一歩進んだ進化に期待しましょう🧠