WSL環境にAWS コマンドラインインターフェイス(AWS CLI)を構築する

## イントロ

こんにちは。
最近お仕事でAWSを触りまくってます。インプットが多すぎてアウトプットできていなかったのですが、徐々に情報を発信していこうと思っています。まずは「**AWS コマンドラインインターフェイス(AWS CLI)**」です。いわゆる

```console
$ aws ec2 describe-instances
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "ami-04394efb326c1b2f0",
                    "InstanceId": "i-xxxxx",
                    "InstanceType": "t2.micro"...
$
```

的なヤツですね。WindowsのWSL環境にAWS CLIをインストールして、触っていこうと思います。


## まずはインストール


WSL を起動して、


```console
$ aws
Command 'aws' not found, but can be installed with:
まだ存在しない

$ unzip
Command 'unzip' not found, but can be installed with:
sudo apt install unzip

こっちもない
```

ってことで、unzipをインストールしてから、AWS CLIをインストールしていきます。


```console
$ sudo apt install unzip

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

$ unzip awscliv2.zip
Archive:  awscliv2.zip
   creating: aws/
   creating: aws/dist/
  inflating: aws/install
  ...

$ sudo ./aws/install
You can now run: /usr/local/bin/aws --version

$ aws --version
aws-cli/2.13.6 Python/3.11.4 Linux/5.15.90.1-microsoft-standard-WSL2 exe/x86_64.ubuntu.22 prompt/off$
```

インストール完了です。


### 設定する

いわゆるアカウントキー

```console
aws_access_key_id = AKIAxxxxxx
aws_secret_access_key = QbJYxxxxxx
```

等は取得済ってことですすめます。

```console
~$ aws configure
AWS Access Key ID [None]: AKIAxxxxxx
AWS Secret Access Key [None]: QbJYxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]:
$
```

設定完了です。

## データを取ってみる。

動かしてみます。


```console
$ aws ec2 describe-vpcs
{
    "Vpcs": [
        {
            "CidrBlock": "172.16.0.0/16",
            "DhcpOptionsId": "dopt-xxxx
            "State": "available",
            "VpcId": "vpc-xxxx
            "OwnerId": "xxxx",
            "InstanceTenancy": "default",
            "CidrBlockAssociationSet": [
                {

    ......
}
```

VPCのデータを取ってみましたが、なんらかデータが返ってきました。データ量が多すぎるので項目を絞ってみます。

```console
$  aws ec2 describe-vpcs \
    --query "Vpcs[*].[Tags[0].Value, VpcId, CidrBlock]" --output  table
----------------------------------------------------------------
|                         DescribeVpcs                         |
+-----------------+-------------------------+------------------+
|  062xxxxxxxxx   |  vpc-0c2e5bxxxxxxxxxxx  |  172.16.0.0/16   |
|  defaultVPC     |  vpc-9dxxxxxx           |  172.31.0.0/16   |
|  TmpVPCStack    |  vpc-0c29xxxxxxxxxxxxx  |  192.168.0.0/16  |
|  MyVPC          |  vpc-0cdbxxxxxxxxxxxxx  |  192.168.0.0/16  |
|  abcd-efghij-VPC|  vpc-08fxxxxxxxxxxxxxx  |  192.168.0.0/16  |
+-----------------+-------------------------+------------------+
$
```

VpcIdとCidrBlockとTags配列の最初の値(よくNameとかのキーで値が入っています)、を並べてみました。 ``--output table`` で表形式で出力できるようですね。


## TIPS

参考: [AWS CLIのフィルターとクエリーの使い方についてまとめてみた](https://dev.classmethod.jp/articles/aws-cli-filter-and-query-howto/) ほとんどこのサイトから得られた情報です。ありがとうございます。


### Tagsをちゃんと指定する

Tagsの最初の値とか曖昧な指定ではなく、Key名をちゃんと指定(``Key=='Name'``) してみます。
具体的には ``Tags[0]`` を ``(Tags[?Key=='Name'])[0] `` とKeyが 'Name' って値たちの最初、って変更してみると


```console
$ aws ec2 describe-vpcs \
    --query "Vpcs[*].[(Tags[?Key=='Name'])[0].Value, VpcId, CidrBlock]" --output  table
-----------------------------------------------------------------
|                         DescribeVpcs                          |
+------------------+-------------------------+------------------+
|  None            |  vpc-0c2e5bxxxxxxxxxxx  |  172.16.0.0/16   | <- Name がないヤツはNone
|  defaultVPC      |  vpc-9dxxxxxx           |  172.31.0.0/16   |
|  tmp-vpc         |  vpc-0c29xxxxxxxxxxxxx  |  192.168.0.0/16  |
|  stg-VPCStack-VPC|  vpc-0cdbxxxxxxxxxxxxx  |  192.168.0.0/16  |
|  abcd-efghij-VPC |  vpc-08fxxxxxxxxxxxxxx  |  192.168.0.0/16  |
+------------------+-------------------------+------------------+
$
```

ちゃんとKeyが'Name'って値を取得する事ができました！便利ですね。

### 条件でフィルタする

たとえばサブネットで、あるVPCに含まれるサブネット、とかは以下の通り。


```console
$ aws ec2 describe-vpcs --query "Vpcs[][VpcId,CidrBlock]" --output table
---------------------------------------------
|               DescribeVpcs                |
+------------------------+------------------+
|  vpc-0c2e5bxxxxxxxxxxx |  172.16.0.0/16   |
|  vpc-9dxxxxxx          |  172.31.0.0/16   |
|  vpc-0c29xxxxxxxxxxxxx |  192.168.0.0/16  |
|  vpc-0cdbxxxxxxxxxxxxx |  192.168.0.0/16  |
|  vpc-08fxxxxxxxxxxxxxx |  192.168.0.0/16  |
+------------------------+------------------+
$ 

vpc-0cdbxxxxxxxxxxxxx のSubnetを一覧してみる

$ aws ec2 describe-subnets \
--query "Subnets[*].[(Tags[?Key=='Name'])[0].Value,CidrBlock,SubnetId]" \
--filters "Name=vpc-id, Values=vpc-0cdbxxxxxxxxxxxxx" \
--output table

----------------------------------------------------------------------------
|                              DescribeSubnets                             |
+---------------------------+-----------------+----------------------------+
|  stg-VPCStack-public-003  |  192.168.4.0/24 |  subnet-0042cd4xxxxxxxxxx  |
|  stg-VPCStack-private-002 |  192.168.3.0/24 |  subnet-0c63408xxxxxxxxxx  |
|  stg-VPCStack-private-003 |  192.168.5.0/24 |  subnet-00e6a55xxxxxxxxxx  |
|  stg-VPCStack-private-001 |  192.168.1.0/24 |  subnet-02b5744xxxxxxxxxx  |
|  stg-VPCStack-public-001  |  192.168.0.0/24 |  subnet-044d4f1xxxxxxxxxx  |
|  stg-VPCStack-public-002  |  192.168.2.0/24 |  subnet-0ffc99cxxxxxxxxxx  |
+---------------------------+-----------------+----------------------------+
```

``--filters Name=vpc-id,Values=vpc-0cdbxxxxxxxxxxxxx`` って指定ができるようです。NameがVpcIdではなく vpc-id ってところが要注意。

条件はAnd条件を複数指定できるっぽい。下記はさらに「かつ、MapPublicIpOnLaunch=false」のヤツ、という指定をしています。

```console
$ aws ec2 describe-subnets \
--query "Subnets[*].[(Tags[?Key=='Name'])[0].Value,CidrBlock,SubnetId]" \
--filters \
 "Name=vpc-id, Values=vpc-0cdbxxxxxxxxxxxxx" \
 "Name=map-public-ip-on-launch, Values=false" \
--output table

----------------------------------------------------------------------------
|                              DescribeSubnets                             |
+---------------------------+-----------------+----------------------------+
|  stg-VPCStack-private-002 |  192.168.3.0/24 |  subnet-0c63408xxxxxxxxxx  |
|  stg-VPCStack-private-003 |  192.168.5.0/24 |  subnet-00e6a55xxxxxxxxxx  |
|  stg-VPCStack-private-001 |  192.168.1.0/24 |  subnet-02b5744xxxxxxxxxx  |
+---------------------------+-----------------+----------------------------+
$
```



### JSON形式で出力する。

```console
$ aws ec2 describe-subnets \
--query "Subnets[*].[(Tags[?Key=='Name'])[0].Value,CidrBlock,SubnetId]" \
--filters \
 "Name=vpc-id, Values=vpc-0cdbxxxxxxxxxxxxx" \
 "Name=map-public-ip-on-launch, Values=false" \
--output json

[
    [
        "stg-VPCStack-private-002",
        "192.168.3.0/24",
        "subnet-0c63408xxxxxxxxxx"
    ],
    [
        "stg-VPCStack-private-003",
        "192.168.5.0/24",
        "subnet-00e6a55xxxxxxxxxx"
    ],
    [
        "stg-VPCStack-private-001",
        "192.168.1.0/24",
        "subnet-02b5744xxxxxxxxxx"
    ]
]
```

項目名が出力されないようですね。明示的にプロパティ名を与えてあげないといけないようです。

```console
$ aws ec2 describe-subnets \
--query "Subnets[*].{name:(Tags[?Key=='Name'])[0].Value,cidr:CidrBlock,id:SubnetId}" \
--filters \
 "Name=vpc-id,Values=vpc-0cdbxxxxxxxxxxxxx" \
 "Name=map-public-ip-on-launch,Values=false" \
--output json

[
    {
        "name": "stg-VPCStack-private-002",
        "cidr": "192.168.3.0/24",
        "id": "subnet-0c63408xxxxxxxxxx"
    },
    {
        "name": "stg-VPCStack-private-003",
        "cidr": "192.168.5.0/24",
        "id": "subnet-00e6a55xxxxxxxxxx"
    },
    {
        "name": "stg-VPCStack-private-001",
        "cidr": "192.168.1.0/24",
        "id": "subnet-02b5744xxxxxxxxxx"
    }
]
```

ついでにjqと連動してみます。

```console
$ aws ec2 describe-subnets \
--query "Subnets[*].{name:(Tags[?Key=='Name'])[0].Value,cidr:CidrBlock,id:SubnetId}" \
--filters \
 "Name=vpc-id,Values=vpc-0cdb748dbc3f8eabe" \
 "Name=map-public-ip-on-launch,Values=false" \
--output json | jq '.[].cidr'

"192.168.3.0/24"
"192.168.5.0/24"
"192.168.1.0/24"
$
```

いままでAWSの管理画面から見ていたデータをこのようにコマンドラインから取得できるわけですね。便利です！

以上、お疲れさまでした。


## 関連リンク

- https://aws.amazon.com/jp/cli/ 公式
- [WSL2環境でaws-cliを使えるようにする](https://zenn.dev/bluesdd/articles/5e45b45c2afd11)
- [VPCのサブネットを抽出して、きれいに並べたい](https://iogi.hatenablog.com/entry/sort-vpc-subnets-by-ip-range)
- [AWS CLIのフィルターとクエリーの使い方についてまとめてみた](https://dev.classmethod.jp/articles/aws-cli-filter-and-query-howto/)
- [WSL環境にNode.js環境を構築する](https://qiita.com/masatomix/items/d69ac664a2fcbdb98f6c) 
- [AWS CDK で Infrastructure as Code する](https://qiita.com/masatomix/items/8fc3d52ee89489967c09)
- [AWS CDKのTIPS集](https://qiita.com/masatomix/items/7087e7813637ff5e9c36)