AWS CLI＋jqでAWSのリソース一覧のCSVを作成する





## はじめに
現状のAWSで使用しているリソース(EC2など)の一覧表(Excel)を作成するため、AWS CLIとjqを使ってcsv形式のリストを作成した。  
使用した環境は以下の通り。

- OS:Windows10
- PowerShell:5.1
- AWS CLI:2.2.11
- jq:1.6

## AWS CLIでリソース情報を出力できるようにする

AWS CLI = AWS Command Line Interface  
これをインストールするとコマンドライン(=スクリプト形式)でAWS上のリソースの操作、情報取得ができる。

[AWS CLIのメリットや使いどころ](https://qiita.com/shimosawa/items/1dbecbf7bf53d41e555e)

### コンソールでIAMユーザを作成する

- AWS CLIでリソース情報を読み取るためのIAMユーザを作成する。
- 「AWSアクセスの種類を選択」で、「プログラムによるアクセス」を選択する。
- アクセス権限として、「arn:aws:iam::aws:policy/ReadOnlyAccess」のポリシーのみを付与する。  
(リソース操作はできないが、ほとんど全てのリソース情報を読み取れてしまうので注意)

![無題の画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259842/276601ce-514e-eb92-ba02-2563eb6adf61.png)


- 表示されるアクセスキーIDと、シークレットアクセスキーをダウンロードして保存する。

### AWS CLIをインストールする(Windowsの場合)

参考：(https://gihyo.jp/admin/serial/01/awscli_diary/0001?page=1)

- [AWS CLIの公式ページ](https://aws.amazon.com/jp/cli/)から、インストーラをダウンロード
- インストーラでAWS CLIをインストール
- PowerShellで以下を実行し、バージョンが表示されていればOK

```
> aws --version

aws-cli/2.2.11 Python/3.8.8 Windows/10 exe/AMD64 prompt/off
```
ちなみに、pipでもインストール可能。

```
> pip3 install awscli
```

### AWS CLIの初期設定

以下を実行し、設定情報を入力する。  
(この設定は後から変更も可能)

```
> aws configure

AWS Access Key ID [None]: (ダウンロードしたアクセスキーID)
AWS Secret Access Key [None]: (ダウンロードしたシークレットアクセスキー)
Default region name [None]: ap-northeast-1a (確認したいリソースのリージョンを入力)
Default output format [None]: json
```

### 実際に出力してみる
以下のコマンドを実行する。

```
> aws ec2 describe-instances
```

以下のようにJSON形式でリソースの情報が表示される。

```
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "xxx",
                    "InstanceId": …
```

使用できるコマンドについては以下を参照。  
[AWS CLI Command Reference](https://docs.aws.amazon.com/ja_jp/cli/latest/reference/index.html)  
  
以下のように表示内容をファイル出力することも可能。

```
> aws ec2 describe-instances >> ec2.json
```

## jqをインストール 
jqはコマンドライン上で使用できるJSONパーサー。JSON形式のデータのフィルタリング等が可能。
 
[ここ](https://stedolan.github.io/jq/download/)からインストーラをダウンロード、インストールする。
  
Powershellで以下のコマンドでバージョン確認できればOK

```
> jq --version
jq-1.6
```

## リソースごとのcsvファイルを作成する

### EC2のリソース情報をjq経由でcsvファイルに出力する

実際に出力に使ったコマンドは以下の通り。

```
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | if .Tags then . else .Tags = [] end | [
 .InstanceId,
 ( .Tags[] | select(.Key == \"Name\") | .Value)// \"\",
 ( .Tags[] |  select(.Key == \"Owner\") | .Value ) // \"\",
 .InstanceType,
 .Placement.AvailabilityZone,
 .VpcId,
 .SubnetId,
 .KeyName,
 .PublicIpAddress,
 .SecurityGroups[].GroupName,
 .SecurityGroups[].GroupId,
 .BlockDeviceMappings[].Ebs.VolumeId ,
 .NetworkInterfaces[].Attachment.AttachmentId,
 .NetworkInterfaces[].Groups[].GroupName,
 .NetworkInterfaces[].Groups[].GroupId
 ] | @csv' >> ec2_list.csv

```
SecurityGroup、BlockDeviceMappings、NetworkInterfacesはアタッチしている数がインスタンスごとに変わるので、場合によっては行ごとに列数が変わってしまう。(Excel上で修正するか、そもそも出力しないか)  
  
以下、簡単な解説

```bash
# AWS CLIでJSON形式のデータを取得
aws ec2 describe-instances 

# jqを同時に呼び出してJSON形式のデータを加工、-rは要素についている""を外す
# jq -オプション 'フィルタ' の形式で実行
| jq -r　'.Reservations[] ... '

# "Instances"の中に[]で配列状に入っているデータを全て取得対象にする
.Instances[] 

#  "Tags" の項目がある場合は値をそのまま使用し、ない場合は[](空の配列)を返す
# if ～ then ～ else ～ end の形で必ず書く 
| if .Tags then . else .Tags = [] end 

# パイプ以降に[]をつけて出力したい項目を配列として出力する
# .InstanceId, 以降は出力したい項目を入力する
| [
 .InstanceId,

# Tagは取り出したいKeyの値をselect文で取り出す
# // "" で、取得値がnullだった時のデフォルト値を""(空文字)とする、""はPowerShellだとエラーになるので\でエスケープする
 ( .Tags[] | select(.Key == \"Name\") | .Value) // \"\",

# @csv を利用して、CSV形式で出力
 '... ] | @csv' >> ec2_list.csv

```

### EBSの場合

```
aws ec2 describe-volumes | jq -r '.Volumes[] | if .Tags then . else .Tags = [] end | [
 .VolumeId,
 ( .Tags[] | select(.Key == \"Name\") | .Value) // \"\",
 ( .Tags[] |  select(.Key == \"Owner\") | .Value ) // \"\",
 .AvailabilityZone,
 .Size,
 .Iops,
 .State,
 .SnapshotId,
 .Attachments[].InstanceId,
 .Attachments[].VolumeId
 ] | @csv' >> ebs_list.csv

```

### NetworkInterfaceの場合

```
aws ec2 describe-network-interfaces | jq -r '.NetworkInterfaces[] | [
 .NetworkInterfaceId,
 ( .TagSet[] | select(.Key == \"Name\") | .Value) // \"\",
 ( .TagSet[] |  select(.Key == \"Owner\") | .Value ) // \"\",
 .Description,
 .InterfaceType,
 .AvailabilityZone,
 .VpcId,
 .SubnetId,
 .Status,
 .Groups[].GroupName,
 .Groups[].GroupId,
 .Association.PublicIp,
 .Attachment.AttachmentId,
 .Attachment.InstanceId,
 .Attachment.InstanceOwnerId
 ] | @csv' >> nif_list.csv

```


参考 
[【小ネタ】aws-cliでEC2マネージメントコンソールの内容をCSVに出力する](https://dev.classmethod.jp/articles/aws-ec2-output-to-csvfile/)
[軽量JSONパーサー『jq』のドキュメント：『jq Manual』をざっくり日本語訳してみました](https://dev.classmethod.jp/articles/jq-manual-japanese-translation-roughly/)
[コマンドラインJSONプロセッサー jqの演算子と関数](https://tech.mktime.com/entry/127)
[配列やnull（特定のキーがない）があるJSONからjqでTSV作ってみた](https://dev.classmethod.jp/articles/jq-json-to-tsv-with-join-null/)



## 雑感
SecurityGroupなどはインバウンドルールの数がグループごとに全く異なる場合が多いので、csv出力に向いていない。JSONファイルをプログラムで処理した方がいいかも。  
  
IAMユーザは所属するグループ情報も取得したい場合は

```
aws iam list-groups-for-user \
--user-name USERNAME \
```
のようにユーザ名を指定する必要があるため、スクリプトを組んだ方がよい。もしくは、[[Former2]](https://dev.classmethod.jp/articles/former2/)を使ってCloudFormation形式のテンプレートに出力して変換するのもありかと。