NEWSニュース&ブログ

AWSから簡単にパラメータシートを生成する

投稿日:2025-09-17

はじめに

 時間の経過とともに増えていくEC2インスタンス、作成者が不明なVPC、整理が行き届いていないサブネットやセキュリティグループなど、AWS環境は運用を続ける中で複雑化していく傾向があります。
容易にリソースを作成できる一方で、「現在の構成を正確に把握したい」というニーズが生じた際、マネジメントコンソール上で手作業で情報を集計するのは手間がかかり、漏れやミスにつながる可能性があります。
そこで今回は、AWS CLIでリソース情報(JSON形式)を取得し、Pythonを用いてExcel形式のパラメータシートを生成する方法をご紹介します。
この方法により、複雑化したAWS環境をワンコマンドで一覧化し、構成管理の効率化と正確性の向上が可能になります。

ゴールと要件

  • AWS上のEC2、VPC関連の全リソースを取得
  • 構成管理に使えるパラメータシート(Excel)形式で出力
  • いつでもワンコマンドで最新情報を取得できる再現性
  • 将来的にRDSやS3など他サービスも追加可能な構造

技術選定

技術 用途 採用理由
AWS CLI リソース情報取得 スクリプタブルで再現性・汎用性が高い
Python + pandas JSON → DataFrame加工 複雑なJSON整形と表形式変換が容易
openpyxl Excel出力 pandasとの親和性が高く、マルチシート出力対応

全体アーキテクチャ

このツールは、AWS環境からリソース情報を取得し、整形してExcel形式のパラメータシートにまとめるまでを2つのスクリプトで実現します。

[AWS環境] 
↓ (AWS CLI / aws_resources.sh)
[JSONファイル群]
↓ (Python / aws_resources_to_excel.py)
[パラメータシート]
 (Excel / aws_resources.xlsx)

📋 処理フロー

ステップ スクリプト名 処理内容 入力 出力
1 aws_resources.sh AWS CLIを使って、EC2 / VPC / Subnet / RouteTable / SecurityGroup の情報を取得 AWS環境 JSONファイル群(ec2_instances.json など)
2 aws_resources_to_excel.py JSONをDataFrameに整形し、リソースごとにシート分けして1つのExcelファイルに出力 JSONファイル群 aws_resources.xlsx(パラメータシート)

実装ハイライト

💻 JSON取得スクリプト(aws_resources.sh)

#!/bin/bash

#============================
# AWS リソース取得
# 取得対象: EC2 / VPC
#============================

# リージョン指定(デフォルトap-northeast-1)
REGION=${1:-ap-northeast-1}

# スクリプトのあるディレクトリ
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)

# 出力ディレクトリ
OUTDIR="${SCRIPT_DIR}/output_$(date +%Y%m%d%H%M%S)"
mkdir -p "$OUTDIR"

echo "AWS リージョン: $REGION"
echo "出力ディレクトリ: $OUTDIR"

#################################
# 1. EC2
#################################
aws ec2 describe-instances --region "$REGION" --output json > "$OUTDIR/ec2_instances.json"

#################################
# 2. VPC
#################################
aws ec2 describe-vpcs --region "$REGION" --output json > "$OUTDIR/vpcs.json"
aws ec2 describe-subnets --region "$REGION" --output json > "$OUTDIR/subnets.json"
aws ec2 describe-route-tables --region "$REGION" --output json > "$OUTDIR/route_tables.json"
aws ec2 describe-security-groups --region "$REGION" --output json > "$OUTDIR/security_groups.json"

#################################
# ZIP 圧縮
#################################
ZIPFILE="${SCRIPT_DIR}/aws_resources_${REGION}_$(date +%Y%m%d%H%M%S).zip"
cd "$SCRIPT_DIR" || exit 1
zip -r "$ZIPFILE" "$(basename "$OUTDIR")" > /dev/null

echo "取得完了: $OUTDIR"
echo "ZIPファイル作成: $ZIPFILE"

💻 Excel生成スクリプト(aws_resources_to_excel.py)

import json
import pandas as pd
from pathlib import Path

def get_name_tag(tags):
"""Nameタグの値を取得"""
return next((t["Value"] for t in tags if t["Key"] == "Name"), "")

# ==== JSONファイル読み込み ====
with open("ec2_instances.json", "r", encoding="utf-8") as f:
ec2_data = json.load(f)
with open("vpcs.json", "r", encoding="utf-8") as f:
vpcs_data = json.load(f)
with open("subnets.json", "r", encoding="utf-8") as f:
subnets_data = json.load(f)
with open("route_tables.json", "r", encoding="utf-8") as f:
rtb_data = json.load(f)
with open("security_groups.json", "r", encoding="utf-8") as f:
sg_data = json.load(f)

# ==== EC2 Instances ====
ec2_records = []
for reservation in ec2_data["Reservations"]:
for instance in reservation["Instances"]:
name_tag = get_name_tag(instance.get("Tags", []))
subnet_id = instance.get("SubnetId", "")
sg_list = [sg["GroupId"] for sg in instance.get("SecurityGroups", [])]
sg_names = [sg["GroupName"] for sg in instance.get("SecurityGroups", [])]

ec2_records.append({
"InstanceId": instance.get("InstanceId", ""),
"Name": name_tag,
"InstanceType": instance.get("InstanceType", ""),
"AvailabilityZone": instance.get("Placement", {}).get("AvailabilityZone", ""),
"State": instance.get("State", {}).get("Name", ""),
"PrivateIpAddress": instance.get("PrivateIpAddress", ""),
"PublicIpAddress": instance.get("PublicIpAddress", ""),
"SubnetId": subnet_id,
"SecurityGroupIds": ", ".join(sg_list),
"SecurityGroupNames": ", ".join(sg_names)
})
df_ec2 = pd.DataFrame(ec2_records)

# ==== VPCs ====
vpc_records = []
for vpc in vpcs_data["Vpcs"]:
vpc_records.append({
"VpcId": vpc.get("VpcId", ""),
"Name": get_name_tag(vpc.get("Tags", [])),
"CidrBlock": vpc.get("CidrBlock", ""),
"State": vpc.get("State", ""),
"IsDefault": vpc.get("IsDefault", False)
})
df_vpcs = pd.DataFrame(vpc_records)

# ==== Subnets ====
subnet_records = []
for sn in subnets_data["Subnets"]:
subnet_records.append({
"SubnetId": sn.get("SubnetId", ""),
"Name": get_name_tag(sn.get("Tags", [])),
"VpcId": sn.get("VpcId", ""),
"CidrBlock": sn.get("CidrBlock", ""),
"AvailabilityZone": sn.get("AvailabilityZone", "")
})
df_subnets = pd.DataFrame(subnet_records)

# ==== Route Tables ====
rtb_records = []
for rtb in rtb_data["RouteTables"]:
routes_str = "; ".join(
[f"{r.get('DestinationCidrBlock', r.get('DestinationIpv6CidrBlock', ''))} -> {r.get('GatewayId', r.get('NatGatewayId', r.get('TransitGatewayId', '')))}"
for r in rtb.get("Routes", [])]
)
rtb_records.append({
"RouteTableId": rtb.get("RouteTableId", ""),
"Name": get_name_tag(rtb.get("Tags", [])),
"VpcId": rtb.get("VpcId", ""),
"Routes": routes_str
})
df_rtb = pd.DataFrame(rtb_records)

# ==== Security Groups ====
sg_records = []
for sg in sg_data["SecurityGroups"]:
ingress_rules = []
for perm in sg.get("IpPermissions", []):
proto = perm.get("IpProtocol", "")
if "FromPort" in perm and "ToPort" in perm:
ports = f"{perm.get('FromPort')} - {perm.get('ToPort')}"
else:
ports = "ALL"
cidrs = ",".join([r.get("CidrIp", "") for r in perm.get("IpRanges", [])])
ingress_rules.append(f"{proto} {ports} {cidrs}")

sg_records.append({
"GroupId": sg.get("GroupId", ""),
"Name": get_name_tag(sg.get("Tags", [])),
"GroupName": sg.get("GroupName", ""),
"VpcId": sg.get("VpcId", ""),
"Description": sg.get("Description", ""),
"Ingress": "; ".join(ingress_rules)
})
df_sg = pd.DataFrame(sg_records)

# ==== Excel 出力 ====
out_path = Path("aws_resources.xlsx")
with pd.ExcelWriter(out_path, engine="openpyxl") as writer:
df_ec2.to_excel(writer, sheet_name="EC2 Instances", index=False)
df_vpcs.to_excel(writer, sheet_name="VPCs", index=False)
df_subnets.to_excel(writer, sheet_name="Subnets", index=False)
df_rtb.to_excel(writer, sheet_name="RouteTables", index=False)
df_sg.to_excel(writer, sheet_name="SecurityGroups", index=False)

print(f"Excelファイルを出力しました: {out_path.resolve()}")

工夫ポイントとハマりどころ

  • ReadOnlyAccessだけで実行可能なので環境を変更するリスクがない
  • SGルールの簡潔化:Protocol / Port / CIDR をまとめて1セルに表記
  • マルチSG・マルチルート対応:複数値はカンマ・セミコロンで連結
  • スキーマ統一:列順を決めてDataFrame化、Excel列幅も後で調整しやすく

実行手順

1. 事前準備

  • AWS CLIがインストールされていること
  • AWSアクセスキーが設定されていること
  • Python3が利用可能であること
  • 必要なPythonライブラリのインストール
    pip install pandas openpyxl

2. JSONファイル取得

  • (1) ターミナル(またはコマンドプロンプト)を開く
  • (2) aws_resources.sh のあるディレクトリへ移動
  • (3) 実行権限がない場合は付与
    chmod +x aws_resources.sh
  • (4) JSON取得スクリプトを実行 ※引数が無い場合は東京リージョン(ap-northeast-1)を取得します。
    ./aws_resources.sh <Region Name>

実行後に作成されるファイル:

  • ec2_instances.json(EC2インスタンス一覧)
  • vpcs.json(VPC一覧)
  • subnets.json(サブネット一覧)
  • route_tables.json(ルートテーブル一覧)
  • security_groups.json(セキュリティグループ一覧)

3. パラメータシート(Excel)生成

  • (1) JSONファイルのあるディレクトリで以下を実行

    python aws_resources_to_excel.py

📊 出力されるExcelの構成

シート名 内容
EC2 Instances EC2インスタンス一覧(InstanceId / Name / InstanceType / AZ / State / Private/Public IP / SubnetId / SecurityGroupIds / SecurityGroupNames)
VPCs VPC一覧(VpcId / Name / CidrBlock / State / IsDefault)
Subnets サブネット一覧(SubnetId / Name / VpcId / CidrBlock / AvailabilityZone)
RouteTables ルートテーブル一覧(RouteTableId / Name / VpcId / Routes)
SecurityGroups セキュリティグループ一覧(GroupId / Name / GroupName / VpcId / Description / Ingressルール)

実行例

今回はAWSマネジメントコンソール(CloudShell)で実行します。
必要に応じてAWSCloudShellFullAccessポリシーを付与してください。

📌 PythonライブラリのインストールからJSONファイル取得まで

PythonライブラリのインストールからJSONファイル取得まで

📌 Excelパラメータシートを生成するまで

Excelパラメータシートを生成するまで

📌 パラメータシート(Excel)の画面

Excelパラメータの画面

今後の拡張

  • RDS / S3 / ELB などのサービス追加
  • 自動化による定期実行(cron / GitHub Actions / Lambda)
  • Gitで構成履歴を管理し差分比較

まとめ

 AWS環境は時間とともに複雑化しやすく、手動でのリソース把握は非効率です。 今回紹介したスクリプトを使えば、現状の構成を即座にExcel化し、チーム全員で共有できます。
構成管理の可視化はトラブル予防にもつながります。小さなステップからでも導入してみましょう。

野口大貴(1992年生まれ 2022年入社)
株式会社システムサポート フューチャーイノベーション事業本部

ソリューションサービス事業部所属。
インフラエンジニア。AWS、Azureの基本設計から運用までを担当。開発もたまにやります。