ChatGPT を使って AWS リソースのパラメータをいい感じの Markdown 形式に加工してもらった

2023.03.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、大前です。

業務で AWS 環境の構築をよく行うのですが、構築した AWS 環境の設定値を Markdown 形式で記載したい場面が多々あります。

AWS が提供している API を利用することで AWS 環境の設定値を取得することができるのですが、現状は JSON や YAML 形式で返却されたデータを頑張って Markdown に加工したりする必要があります。

最近話題の ChatGTP を使ったら、自分で頑張って出力結果を加工しなくても、いい感じに Markdown 形式で AWS 環境の設定値を出力できないか?と思い立ったので、試してみました。

今回やりたいこと

今回は、SDK を利用して IAM Role の一覧を取得し、その結果を ChatGPT にいい感じに加工してもらおうと思います。

参考までに、AWS CLI で IAM Role の一覧を取得するコマンドを実行した際の結果は以下の様な内容になります。Path や RoleName など、設定値が羅列されている中に、AssumeRolePolicyDocument(信頼ポリシー)の JSON が混ざっていたりするので、加工するにはうってつけかと思います。

[coudshell-user@xxxxx]$ aws iam list-roles
{
    "Roles": [
        {
            "Path": "/service-role/",
            "RoleName": "EXAMPLEROLE01",
            "RoleId": "AAAAAAAAAAAAA",
            "Arn": "arn:aws:iam::000011112222:role/service-role/EXAMPLEROLE01",
            "CreateDate": "2021-04-20T01:55:29+00:00",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "access-analyzer.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            },
            "MaxSessionDuration": 3600
        },
        {
            "Path": "/",
            "RoleName": "EXAMPLEROLE02",
            "RoleId": "BBBBBBBBBBBB",
            "Arn": "arn:aws:iam::000011112222:role/EXAMPLEROLE02",
            "CreateDate": "2019-09-26T05:03:38+00:00",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "ec2.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    },
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "medialive.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            },
            "Description": "AllowMediaLiveAccessRole",
            "MaxSessionDuration": 3600
        },
        (中略)
    ]
}

事前準備

今回は Lambda で ChatGPT の API を叩きたいので、下記ブログを参考に、openai ライブラリを Lambda レイヤーとして用意しました。

Lambda 関数のランタイムは Python 3.9 を利用します。

また、OpenAI の API キーも必要なので、API キーを生成し、Lambda 関数の環境変数にセットしておきます。

やってみた

細かい指示なしで Markdown 形式の表に変換してもらう

まずは、細かい指示なしで、SDK から返却される結果を Markdown 形式の表に変換してもらいます。 SDK で 2つの IAM Role を取得し、取得した情報を ChatGPT に渡しています。

import os
import boto3
import openai

# APIキーの設定
openai.api_key = os.environ["OPENAI_API_KEY"]

def lambda_handler(event, context):
    
    # IAM Role 一覧取得
    iam_client = boto3.client('iam')
    iam_role_list = iam_client.list_roles(MaxItems=2) #今回はテストなので2つだけ取得

    # ChatGPT呼び出し
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "user", "content": f"以下のJSONをMarkdown形式の表に変換してください{iam_role_list}"},
        ],
    )
    print(response.choices[0]["message"]["content"].strip())

結果は以下です。特に何も指定しなくてもそれっぽい表に加工してくれました。注:IsTruncated、MarkerとResponseMetadataは表に含まれていません。 という文章も一緒に出力されているのがなかなか面白いです。

ただし、細かい指示がないためか、実行するたびにフォーマットが変わったりしてしまいました。

| Roles | Path | RoleName | RoleId | Arn | CreateDate | AssumeRolePolicyDocument | Description | MaxSessionDuration |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|  | /service-role/ | EXAMPLEROLE01 | AAAAAAAAAAAAA | arn:aws:iam::000011112222:role/service-role/EXAMPLEROLE01 | 2021-04-20 01:55:29 | {'Version': '2012-10-17', 'Statement': [{'Effect': 'Allow', 'Principal': {'Service': 'access-analyzer.amazonaws.com'}, 'Action': 'sts:AssumeRole'}]} |  | 3600 |
|  | / | EXAMPLEROLE02 | BBBBBBBBBBBB | arn:aws:iam::000011112222:role/EXAMPLEROLE02 | 2019-09-26 05:03:38 | {'Version': '2012-10-17', 'Statement': [{'Effect': 'Allow', 'Principal': {'Service': 'ec2.amazonaws.com'}, 'Action': 'sts:AssumeRole'}, {'Effect': 'Allow', 'Principal': {'Service': 'medialive.amazonaws.com'}, 'Action': 'sts:AssumeRole'}]} | AllowMediaLiveAccessRole | 3600 |

注:IsTruncated、MarkerとResponseMetadataは表に含まれていません。

指示を入れてみる

上記の様な、単純に JSON を Markdown の表に加工するだけであれば既存のツールでもできる範疇かと思います。 ですので、次は SYSTEM_PARAMETER として制約条件を指定し、ツールでは簡単に補えなさそうな加工をお願いしてみます。

  • 最初に「IAMロール一覧」と見出しレベル1で記載する
  • RoleNameは表に含めず、見出しレベル2で記載する
  • RoleName毎に表をそれぞれ作成する
import os
import boto3
import openai

# APIキーの設定
openai.api_key = os.environ["OPENAI_API_KEY"]

# 制約条件
SYSTEM_PARAMETER = """
与えられたJSONを、以下の制約条件をもとにMarkdown形式の表に変換してください。

制約条件:
・最初に「IAMロール一覧」と見出しレベル1で記載する
・RoleNameは表に含めず、見出しレベル2で記載する
・RoleName毎に表をそれぞれ作成する
"""

def lambda_handler(event, context):
    
    # IAM Role 一覧取得
    iam_client = boto3.client('iam')
    iam_role_list = iam_client.list_roles(MaxItems=2)
    
    # ChatGPT呼び出し
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": SYSTEM_PARAMETER},
            {"role": "user", "content": f"以下のJSONをMarkdown形式の表に変換してください{iam_role_list}"},
        ],
    )
    print(response.choices[0]["message"]["content"].strip())

結果は以下です。 だいぶ良い感じになりました!そのまま Markdown ファイルとして出力して使えそうです。

# IAMロール一覧
## EXAMPLEROLE01
|項目|値|
|:--|:--|
|Path|/service-role/|
|RoleId|AAAAAAAAAAAAA|
|Arn|arn:aws:iam::000011112222:role/service-role/EXAMPLEROLE01|
|CreateDate|2021-04-20 01:55:29+00:00|
|AssumeRolePolicyDocument|{'Version': '2012-10-17', 'Statement': [{'Effect': 'Allow', 'Principal': {'Service': 'access-analyzer.amazonaws.com'}, 'Action': 'sts:AssumeRole'}]}|
|MaxSessionDuration|3600|
## EXAMPLEROLE02
|項目|値|
|:--|:--|
|Path|/|
|RoleId|BBBBBBBBBBBB|
|Arn|arn:aws:iam::000011112222:role/EXAMPLEROLE02|
|CreateDate|2019-09-26 05:03:38+00:00|
|AssumeRolePolicyDocument|{'Version': '2012-10-17', 'Statement': [{'Effect': 'Allow', 'Principal': {'Service': 'ec2.amazonaws.com'}, 'Action': 'sts:AssumeRole'}, {'Effect': 'Allow', 'Principal': {'Service': 'medialive.amazonaws.com'}, 'Action': 'sts:AssumeRole'}]}|
|Description|AllowMediaLiveAccessRole|
|MaxSessionDuration|3600|

もっと指示を入れてみる

良い感じに加工できそうなことがわかったので、さらに指示を追加してみます。 例えば、信頼ポリシーは表の外で JSON のまま記載するなどをお願いしてみます。

import os
import boto3
import openai

# APIキーの設定
openai.api_key = os.environ["OPENAI_API_KEY"]

# 制約条件
SYSTEM_PARAMETER = """
与えられたJSONを、以下の制約条件をもとにMarkdown形式の表に変換してください。

制約条件:
・最初に見出しレベル1で「IAMロール一覧」と記載する
・RoleName毎に表をそれぞれ作成する
・RoleNameは表に含めず、見出しレベル2で記載する
・表の前には見出しレベル3で「パラメータ」と記載する
・AssumeRolePolicyDocumentは表に含めず、JSON形式のまま記載する
・AssumeRolePolicyDocumentの前には「信頼ポリシー」と見出しレベル3で記載する
・RoleIdは出力結果に含めない

期待される表の形式:
# IAM ロール一覧
## RoleName
### パラメータ
| Path | Description | Arn | CreateDate | MaxSessionDuration |
| --- | --- | --- | --- | --- |
| samplevalue1 | samplevalue2 | samplevalue3 | samplevalue4 | samplevalue5 |
### 信頼ポリシー
```
```
"""

def lambda_handler(event, context):
    
    # IAM Role 一覧取得
    iam_client = boto3.client('iam')
    iam_role_list = iam_client.list_roles(MaxItems=2)
    
    # ChatGPT呼び出し
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": SYSTEM_PARAMETER},
            {"role": "user", "content": f"以下のJSONをMarkdown形式の表に変換してください。{iam_role_list}"},
        ],
    )
    print(response.choices[0]["message"]["content"].strip())

結果は以下です。かなり良い感じの構成になりました。 元の JSON 形式のデータから下記のようなフォーマットに加工するような実装をしようとするとなかなか手間がかかるので、これはかなり嬉しい気がします。

# IAMロール一覧
## EXAMPLEROLE01
### パラメータ
| Path | Arn | CreateDate | MaxSessionDuration |
| --- | --- | --- | --- |
| /service-role/ | arn:aws:iam::000011112222:role/service-role/EXAMPLEROLE01 | 2021-04-20 01:55:29+UTC | 3600 |
### 信頼ポリシー
```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "access-analyzer.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
```
## EXAMPLEROLE02
### パラメータ
| Path | Arn | CreateDate | MaxSessionDuration | Description |
| --- | --- | --- | --- | --- |
| / | arn:aws:iam::000011112222:role/EXAMPLEROLE02 | 2019-09-26 05:03:38+UTC | 3600 | AllowMediaLiveAccessRole |
### 信頼ポリシー
```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "medialive.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
```

おわりに

ChatGPT を利用して AWS リソースの一覧をいい感じの Markdown に加工してみました。

単純に JSON 形式のデータを Markdown に変更するツールは多々ありますが、独自のフォーマットに加工したい場合は自力でスクリプトなどを組む必要があったかと思います。

ChatGPT を利用することで対話的にフォーマットを指定できるので、出力したいフォーマットが変わってもプロンプトを変化させるだけで良くなるので作業効率が上がりそうです。

実業務での活用も考えていきたいと思います。

以上、AWS 事業本部の大前でした。

参考