Y_Yamashitaのブログ

勉強したことのアウトプット・メモ中心。たまに日記とか。

JAWS-UG CLI専門支部 #181R SQS入門を噛みしめながら復習する(①事前作業編)

はじめに

先日、JAWS-UG CLI専門支部 #181R SQS入門に参加した。

jawsug-cli.connpass.com

CloudShell、Cloud9を使ってSQSを作成、メッセージの送付/受信/削除を実施した。忘れないうちに、再度復習を実施する。
前回の復習同様、出来るだけ一つ一つのコマンドの中身を噛みしめながら復習していく。

※とか何とか言っていたら、噛みしめ過ぎてしまい、事前作業だけで1記事分のボリュームになってしまった。。仕方ないので、2回に分けて記載することにする。

IAMロールへのポリシーアタッチ

今回はCloud9でSQSを扱うので、Cloud9用のIAMロールに対し、IAMポリシー"AmazonSQSFullAccess"をアタッチする。IAMポリシーのアタッチはCloudShellで実施する。

変数の準備

前回のハンズオン同様、まずは変数を用意する。

[cloudshell-user@ip-10-0-167-94 ~]$ IAM_ROLE_NAME='handson-cloud9-environment-role'
[cloudshell-user@ip-10-0-167-94 ~]$ IAM_POLICY_NAME='AmazonSQSFullAccess'
[cloudshell-user@ip-10-0-167-94 ~]$ 
[cloudshell-user@ip-10-0-167-94 ~]$ echo ${IAM_ROLE_NAME} ; echo ${IAM_POLICY_NAME}
handson-cloud9-environment-role
AmazonSQSFullAccess
[cloudshell-user@ip-10-0-167-94 ~]$ 
[cloudshell-user@ip-10-0-167-94 ~]$ set | grep IAM_*
IAM_POLICY_NAME=AmazonSQSFullAccess
IAM_ROLE_NAME=handson-cloud9-environment-role
[cloudshell-user@ip-10-0-167-94 ~]$ 

続いて、"AmazonSQSFullAccess"のARNを取得する。IAMロールにポリシーをアタッチする際に、ポリシー名ではなくARNで指定する必要があるため。

[cloudshell-user@ip-10-0-167-94 ~]$ IAM_POLICY_ARN=$( \
>   aws iam list-policies \
>     --scope AWS \
>     --max-items 1000 \
>     --query "Policies[?PolicyName==\`${IAM_POLICY_NAME}\`].Arn" \
>     --output text \
> ) \
>   && echo "${IAM_POLICY_ARN}"
arn:aws:iam::aws:policy/AmazonSQSFullAccess
[cloudshell-user@ip-10-0-167-94 ~]$

ARNの取得部分のコマンドの詳細は以下。

コマンド 内容
aws iam list-policies IAMポリシーの一覧を表示する
--scope AWS AWS管理ポリシーに絞る
--max-items 1000 表示の最大数を1000にする
--query "Policies[?PolicyName==${IAM_POLICY_NAME}].Arn" PolicyNameが"AmazonSQSFullAccess"(変数IAM_POLICY_NAMEの中身)のポリシーの、ARN部分を指定する
--output text 結果をJSON形式ではなくテキスト形式で出力する

ちなみに、aws iam list-policiesコマンドをそのまま出力した結果はこんな感じだった。(※全部出力するととんでもない量になるので、headで冒頭20行だけ出してみた)

[cloudshell-user@ip-10-0-35-205 ~]$ aws iam list-policies --scope AWS | head -n 20
{
    "Policies": [
        {
            "PolicyName": "AWSDirectConnectReadOnlyAccess",
            "PolicyId": "ANPAI23HZ27SI6FQMGNQ2",
            "Arn": "arn:aws:iam::aws:policy/AWSDirectConnectReadOnlyAccess",
            "Path": "/",
            "DefaultVersionId": "v4",
            "AttachmentCount": 0,
            "PermissionsBoundaryUsageCount": 0,
            "IsAttachable": true,
            "CreateDate": "2015-02-06T18:40:08+00:00",
            "UpdateDate": "2020-05-18T18:48:22+00:00"
        },
        {
            "PolicyName": "AmazonGlacierReadOnlyAccess",
            "PolicyId": "ANPAI2D5NJKMU274MET4E",
            "Arn": "arn:aws:iam::aws:policy/AmazonGlacierReadOnlyAccess",
            "Path": "/",
            "DefaultVersionId": "v2",
[cloudshell-user@ip-10-0-35-205 ~]$ 
[cloudshell-user@ip-10-0-35-205 ~]$ 
[cloudshell-user@ip-10-0-35-205 ~]$ aws iam list-policies --scope Local | head -n 20
{
    "Policies": [
        {
            "PolicyName": "AWSQuickSightIAMPolicy",
            "PolicyId": "ANPATO53NFKUB4O64JFIN",
            "Arn": "arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSQuickSightIAMPolicy",
            "Path": "/service-role/",
            "DefaultVersionId": "v1",
            "AttachmentCount": 1,
            "PermissionsBoundaryUsageCount": 0,
            "IsAttachable": true,
            "CreateDate": "2021-05-06T14:26:15+00:00",
            "UpdateDate": "2021-05-06T14:26:15+00:00"
        },
        {
            "PolicyName": "handson-Cloud9EnvironmentOwner-policy",
            "PolicyId": "ANPATO53NFKUB6T4HF7QC",
            "Arn": "arn:aws:iam::xxxxxxxxxxxx:policy/handson-cloud9/handson-Cloud9EnvironmentOwner-policy",
            "Path": "/handson-cloud9/",
            "DefaultVersionId": "v1",
[cloudshell-user@ip-10-0-35-205 ~]$

頭にPoliciesがあって、その中にPolicyName, PolicyId, Arnなどが格納されているのが分かる。そのため、先ほどの--queryでは、Arnを指定するためにPolicies[].Arnという記載を行っていた事が分かる。
また、--scopでAWSを指定した場合とLocalを指定した場合で出力が変わっていることも分かる。AWSを指定した場合は、AWS管理ポリシー(AWSがあらかじめ用意しているポリシー)が出力されていて、Localを指定した場合は、カスタマー管理ポリシー(ユーザーが自分で作成したポリシー)が出力されている。そのため、Localの方のポリシーは、ArnにアカウントID(xxxでマスキングしている所)が含まれている。

IAMロールへのIAMポリシーのアタッチ

だいぶ脱線してしまったが、これで変数の取得が終わったので、IAMロールにIAMポリシーをアタッチする。IAMロールへのポリシーのアタッチはaws iam attach-role-policyコマンドを使用する。(管理ポリシーの場合。インラインポリシーの場合はaws iam put-role-policyコマンドになる。管理ポリシーとインラインポリシーの違いはこちらを参照。)

[cloudshell-user@ip-10-0-35-205 ~]$ aws iam attach-role-policy \
>   --role-name ${IAM_ROLE_NAME} \
>   --policy-arn ${IAM_POLICY_ARN}
[cloudshell-user@ip-10-0-35-205 ~]$

問題なくアタッチされたようなので、確認してみる。ロールにアタッチされた管理ポリシーを確認するには、aws iam list-attached-role-policiesコマンドを使用する。(インラインポリシーの場合はaws iam list-role-policies

[cloudshell-user@ip-10-0-35-205 ~]$ aws iam list-attached-role-policies \
>   --role-name ${IAM_ROLE_NAME} \
>   --query "AttachedPolicies[?PolicyName == \`${IAM_POLICY_NAME}\`].PolicyName" \
>   --output text
AmazonSQSFullAccess
[cloudshell-user@ip-10-0-35-205 ~]$

問題なくアタッチされていることを確認した。念のためマネコンでも確認してみる。

f:id:YuY_83:20210606004214p:plain
IAMポリシーアタッチ確認
問題なくアタッチされていた。加えて、ReadOnlyAccessもアタッチされている。先ほどのコマンドで、queryでPolicyNameでフィルタしなければ、両方出力されるだろうか。

[cloudshell-user@ip-10-0-35-205 ~]$ aws iam list-attached-role-policies \
>   --role-name ${IAM_ROLE_NAME} \
>   --query "AttachedPolicies[].PolicyName" \
>   --output text
AmazonSQSFullAccess     ReadOnlyAccess
[cloudshell-user@ip-10-0-35-205 ~]$ 
[cloudshell-user@ip-10-0-35-205 ~]$

想定通り、二つとも出力された。

おわりに

当日のハンズオンでは5分くらい?であっという間に終わらせた事前準備だが、あれこれ脱線して調べてみると、色々気づきがあって面白い。とはいえ、SQS入門というタイトルなのに、今回はSQSのことを何もしていない。。さすがにこのままではアレなので、次回はちゃんとSQSに関する作業を復習してブログにする。

CloudShellでIAMポリシー/IAMロールを削除しようとして詰まった話

はじめに

先日、以下のハンズオンを実施した。

docs.aws.amazon.com

Lambdaの使い方がよく分かっていないこともあり、関数の作成や呼び出しは手順通りマネジメントコンソールで実行。問題なく関数呼び出しが出来た。

手順の最後にチュートリアル環境の削除手順があり、これもマネコンでの作業手順が記載されているが、せっかく最近CloudShellを触ったので、せめて最後の削除だけはCloudShellで実行してみることにした。そうしたら、IAMポリシー/IAMロールの削除で思うようにいかなかった場面があったので、備忘として記載することにした。

IAMポリシー削除

まずは以下のWEBページでCLIの削除手順を軽く確認。

docs.aws.amazon.com

最初はポリシーのリストを確認するようなので、とりあえずやってみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam list-policies | grep AWSLambdaS3E*
            "PolicyName": "AWSLambdaS3ExecutionRole-50e074db-f735-45b9-867f-2f1ca04f5ce5",
            "Arn": "arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaS3ExecutionRole-50e074db-f735-45b9-867f-2f1ca04f5ce5",
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

表示されたので、消そうとしてみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam delete-policy \
> --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaS3ExecutionRole-50e074db-f735-45b9-867f-2f1ca04f5ce5

An error occurred (DeleteConflict) when calling the DeletePolicy operation: Cannot delete a policy attached to entities.
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

「エンティティにアタッチされているポリシーは削除できない」というエラーが出てしまった。

ただ、ハンズオンの手順だと、いきなりポリシーを削除することになっている。マネコンとCLIでは勝手が違うのだろうか。

試しにマネコン上での削除を試みる。

f:id:YuY_83:20210603230939p:plain
マネコンのIAMポリシー削除確認画面

マネコンだとエンティティのデタッチを自動で実施してくれるのか。うーむ、マネコン、侮れん。

再度CloudShellに戻って、ポリシーに割り当たっているエンティティについて確認する。aws iam list-entities-for-policy --policy-arnコマンドで、指定したIAMポリシーにアタッチされているエンティティのリストが表示される模様。想定では、ハンズオンで作成したIAMロールが表示されるはず。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam list-entities-for-policy \
> --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaS3ExecutionRole-50e074db-f735-45b9-867f-2f1ca04f5ce5
{
    "PolicyGroups": [],
    "PolicyUsers": [],
    "PolicyRoles": [
        {
            "RoleName": "my-s3-function-role",
            "RoleId": "AROATO53NFKUGNFFORV4I"
        }
    ]
}
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

想定通り表示された。今度はCLI上でデタッチをやってみる。デタッチについてはaws iam detach-role-policyコマンドで、デタッチしたいロールと、現在アタッチされているポリシーを指定する模様。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam detach-role-policy \
> --role-name my-s3-function-role \
> --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaS3ExecutionRole-50e074db-f735-45b9-867f-2f1ca04f5ce5
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

デタッチコマンドが通ったので、改めてエンティティのアタッチ状況を確認する。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam list-entities-for-policy --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaS3ExecutionRole-50e074db-f735-45b9-867f-2f1ca04f5ce5
{
    "PolicyGroups": [],
    "PolicyUsers": [],
    "PolicyRoles": []
}
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

デタッチされた模様。では、改めてポリシーを削除する。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam delete-policy --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaS3ExecutionRole-50e074db-f735-45b9-867f-2f1ca04f5ce5
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

削除成功。

IAMロール削除

続いて、IAMロールを削除する。まずはコマンドを以下のWEBページで確認する。

docs.aws.amazon.com

とりあえず、ページに記載の通りにやってみる。aws iam list-rolesコマンドを実行したら、現在作成されているロールがJSON形式で全て表示された。よくページ見たら、「対象ロール名が分からない場合」と書いてあった。今回は必要なかったな。

気を取り直して、次のコマンドから実行する。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam list-instance-profiles-for-role --role-name my-s3-function-role
{
    "InstanceProfiles": []
}
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$  
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam list-role-policies --role-name my-s3-function-role
{
    "PolicyNames": []
}
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

特に何も割り当たっていないように見えるので、削除コマンドを実行する。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam delete-role --role-name my-s3-function-role

An error occurred (DeleteConflict) when calling the DeleteRole operation: Cannot delete entity, must detach all policies first.
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

消せない。「ロールを消したきゃ、まずポリシーからデタッチしろ」とエラーが出た。なんでだ?

他のコマンドで改めてポリシーのアタッチ状況を確認してみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam list-attached-role-policies --role-name my-s3-function-role
{
    "AttachedPolicies": [
        {
            "PolicyName": "AWSLambdaBasicExecutionRole-b6e2f444-ac64-4852-8685-d03f9e4b131c",
            "PolicyArn": "arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaBasicExecutionRole-b6e2f444-ac64-4852-8685-d03f9e4b131c"
        }
    ]
}
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

なんか割り当たってる!?状況がよく飲み込めていないが、とりあえずこれをデタッチして、再度削除を試みる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam detach-role-policy \
> --role-name my-s3-function-role \
> --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/service-role/AWSLambdaBasicExecutionRole-b6e2f444-ac64-4852-8685-d03f9e4b131c
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam list-attached-role-policies --role-name my-s3-function-role
{
    "AttachedPolicies": []
}
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws iam delete-role --role-name my-s3-function-role
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

消せた。。いったい全体どういうことなのか。

改めて調べてみた

IAMポリシーには「管理ポリシー」と「インラインポリシー」があり、最初に実行したaws iam list-role-policiesインスタンスポリシーの一覧を、後で実行したaws iam list-attached-role-policiesは管理ポリシーの一覧を表示するものらしい。

管理ポリシーとインラインポリシーの違いについては、ザックリいうと、複数のIAMアイデンティティ(ユーザー、グループ、ロール)に割り当て可能なものが管理ポリシーで、特定のIAMアイデンティティと完全に紐づけされるものがインラインポリシーらしい。IAMにおいては通常は管理ポリシーを利用するのがベストプラクティスな模様。インラインポリシーは、特定のアイデンティティにのみ適用したいポリシーがあり、他とポリシーを共有することによって意図せぬ変更が発生することを避けたいケースで使う。

なお、バケットポリシーのようなリソースベースのポリシーは、必ずインラインポリシーになる模様。

管理ポリシーとインラインポリシーの違いについては、以下のサイトを参考にした。

dev.classmethod.jp

docs.aws.amazon.com

qiita.com

dev.classmethod.jp

おわりに

最初はCloudShellで設定を削除するだけのつもりだったが、思いがけずポリシーの種類の勉強になった。実際に手を動かすと、「なんか上手くいかない → 色々調べる → 知らないまま使っていたものの仕組みが分かる」という学習効果が得られるので、今後も積極的に手を動かしていきたい。

JAWS-UG CLI専門支部 #179R AWS CLI環境入門(Cloud9)を噛みしめながら復習する(あとLinuxも)

はじめに

5/20(木)に「JAWS-UG CLI専門支部 #179R AWS CLI環境入門(Cloud9)」に参加した。

jawsug-cli.connpass.com

ハンズオン型の勉強会だったのだが、入門と言いながらかなりのボリュームで、当日はついていくのがやっと。内容をきちんと理解できたとはいえない状態なので、改めて噛みしめながら復習してみる。ついでにLinuxも久しぶりに触ったので、あわせて復習する。

当日のハンズオンではCloud9用のVPC/IAM/EC2インスタンスの構築等をCloudShellで実施したが、今回のブログでは、一番最初に実施したVPCの作成のみを取り上げる。

CloudShellの起動と環境確認

自分はAWS初心者のため、この勉強会で始めてCloudShellを触った。マネジメントコンソールのアイコンから起動できることも知らなかった。

f:id:YuY_83:20210529225104p:plain
CloudShellの起動
f:id:YuY_83:20210529225306p:plain
起動後の画面はこんな感じ

これってどういう環境なんだ?と思ったら、Amazon Linux 2 上で動いている環境らしい。 ↓のブログで詳しく紹介されているので、後で詳しく読んでみようと思う。

dev.classmethod.jp

とりあえず、自分も何となく環境確認してみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ uname -a
Linux ip-10-xxx-xxx-xxx.ap-northeast-1.compute.internal 4.14.225-168.357.amzn2.x86_64 #1 SMP Mon Mar 15 18:00:02 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

unameコマンド打てた。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ who
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

whoを打ったが特に何も表示されず。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ printenv
# 気になったものだけ記載
HOSTNAME=
PWD=/home/cloudshell-user
AWS_REGION=ap-northeast-1
HOME=/home/cloudshell-user

HOSTNAMEは空欄。ホームディレクトリは"/home/cloudshell-user"、リージョンは東京リージョンだった。 リージョンについては、CloudShellを立ち上げたリージョンが設定されるのかと思う。

とりあえず、環境確認はこのくらいにして、ハンズオンの復習に入る。

VPCの構築

この手順では、VPCをCloudShellから作成する。手順に入る前に、全体の流れを確認する。

  1. VPCタグ名、VPCアドレスレンジ用のシェル変数を設定
  2. タグ文字列用のシェル変数を設定
  3. 設定した変数を使用してVPCを作成
  4. VPCが存在していることを確認

先に項番3について触れておくと、VPCの作成には"aws ec2 create-vpc"コマンドを使う。加えて、今回はサブコマンドで"--cidr-block"と"--tag-specifications"を使用し、VPCアドレスレンジとタグを指定する。サブコマンドの引数には"10.0.0.0/16"等の値を直接指定する事も可能だが、今回のハンズオンでは変数に格納し、変数を指定するようにしている。そのため、まず変数の設定を先に実施する。

1. VPCタグ名、VPCアドレスレンジ用のシェル変数を設定

まずは変数の設定

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ EC2_VPC_TAG_NAME='handson-cloud9-vpc-repeat'
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ EC2_VPC_CIDR='10.10.0.0/16'

勉強会で作ったVPCが残っているので、VPCのタグ名は変更した。アドレスレンジは重複していても問題ないはずだが、何となく変更。

続いて変数の確認。ハンズオン手順書には無いが、Linuxの復習も兼ねてsetコマンド打ってみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ set | grep EC2_VPC*
EC2_VPC_CIDR=10.10.0.0/16
EC2_VPC_TAG_NAME=handson-cloud9-vpc-repeat
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

ちゃんと表示された。 手順書の確認方法でも確認してみる。手順書の方法は下記。

cat << END

# 0. AWS_REGION:"ap-northeast-1" AWS_REGION="${AWS_REGION}"

# 1. EC2_VPC_TAG_NAME:"handson-cloud9-vpc" EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"

# 2. EC2_VPC_CIDR:"10.0.0.0/16" EC2_VPC_CIDR="${EC2_VPC_CIDR}"

END

すっかり忘れていたが、"cat <<"の後の文字は終了指定文字なので、別にENDじゃなくても何でもいいのね。試しに違う文字でやってみる。大文字と小文字が区別されるのかも確かめてみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ cat << START
> 
>   # 0. AWS_REGION:"ap-northeast-1"
>        AWS_REGION="${AWS_REGION}"
> 
>   # 1. EC2_VPC_TAG_NAME:"handson-cloud9-vpc-repeat"
>        EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"
>   # 2. EC2_VPC_CIDR:"10.10.0.0/16"
>        EC2_VPC_CIDR="${EC2_VPC_CIDR}"
> 
> END
> start
> START

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"

  # 1. EC2_VPC_TAG_NAME:"handson-cloud9-vpc-repeat"
       EC2_VPC_TAG_NAME="handson-cloud9-vpc-repeat"
  # 2. EC2_VPC_CIDR:"10.10.0.0/16"
       EC2_VPC_CIDR="10.10.0.0/16"

END
start
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

問題なく表示されたし、大文字と小文字は区別されていた。最後の"START"は終了指定文字なので表示されず。

そういえば、変数の参照時に$をつけるのは覚えていたが、{}の意味を覚えておらず調べ直した。参照する変数を明確にする場合は変数を{}で囲むのか。

色々と寄り道したけど、これでVPCタグ名、VPCアドレスレンジ用のシェル変数設定は終わり。

2. タグ文字列用のシェル変数を設定

続いてはタグ文字列用のシェル変数を設定。だがその前に、タグ文字列(--tag-specificationsの引数)がどのような指定方法なのか、awsコマンドのリファレンスで確認しておく。

docs.aws.amazon.com

上記ページによると、リソースタイプを文字列で、タグをキーと値から成るリストで記載する必要があるとのこと。具体的には以下のような形式。

ResourceType=string,Tags=[{Key=string,Value=string},{Key=string,Value=string}] ...

今回は、タグのキーは"NAME"とし、値は項番1で作成した変数"EC2_VPC_TAG_NAME"を指定する。また、変数の設定が成功したら、echoコマンドで変数の中身を表示する。(&&を使用する)

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ STRING_EC2_VPC_TAG="ResourceType=vpc,Tags=[{Key=Name,Value=${EC2_VPC_TAG_NAME}}]" \
>   && echo ${STRING_EC2_VPC_TAG}
ResourceType=vpc,Tags=[{Key=Name,Value=handson-cloud9-vpc-repeat}]
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

問題なく表示された。

そういえば、Linuxでコマンドを途中で改行する時の\も随分久しぶりに使った。久しぶり過ぎて、無駄にビビったw

3. 設定した変数を使用してVPCを作成

いよいよVPCを作成する。上述した通り、"aws ec2 create-vpc"コマンドを使用する。成功するとJSON形式でVPC設定が出力される。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws ec2 create-vpc \
>   --cidr-block ${EC2_VPC_CIDR} \
>   --tag-specifications ${STRING_EC2_VPC_TAG}
{
    "Vpc": {
        "CidrBlock": "10.10.0.0/16",
        "DhcpOptionsId": "dopt-xxxxxxxx",
        "State": "pending",
        "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
        "OwnerId": "XXXXXXXXXXXX",
        "InstanceTenancy": "default",
        "Ipv6CidrBlockAssociationSet": [],
        "CidrBlockAssociationSet": [
            {
                "AssociationId": "vpc-cidr-assoc-xxxxxxxx",
                "CidrBlock": "10.10.0.0/16",
                "CidrBlockState": {
                    "State": "associated"
                }
            }
        ],
        "IsDefault": false,
        "Tags": [
            {
                "Key": "Name",
                "Value": "handson-cloud9-vpc-repeat"
            }
        ]
    }
}
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

問題なく作成された。

4. VPCが存在していることを確認

最後にVPCが存在していることを確認する。これもCloudShell上で実施する。手順書のコマンドは以下。

aws ec2 describe-vpcs \

--filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME} \

--query 'Vpcs[].Tags[?Key == `Name`].Value' \

--output text

VPC設定を表示させたうえでフィルタしているのは何となく分かるが、正確な所は分からないので、コマンドリファレンスを調べてみる。

docs.aws.amazon.com

あれ、サブコマンドに--filtersはあるが、--queryと--outputが無い。

と思ったら、以下のURLに説明があった。

docs.aws.amazon.com

--queryと--outputは、特定のAWSコマンドのサブコマンドではなく、AWS CLI共通のフィルタ方式らしい。で、内容としては、--filterで対象のVPCを指定し、--queryで対象の設定値を指定し、--outputで出力形式を指定している、という事のようだった。

折角なのでフィルタせずに色々試してみる。まずは"aws ec2 describe-vpcs"コマンドだけ実施してみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws ec2 describe-vpcs
{
    "Vpcs": [
        {
            "CidrBlock": "10.0.0.0/16",
            "DhcpOptionsId": "dopt-xxxxxxxxxx",
            "State": "available",
            "VpcId": "vpc-xxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxx",
            "InstanceTenancy": "default",
            "CidrBlockAssociationSet": [
                {
                    "AssociationId": "vpc-cidr-assoc-xxxxxxxxxxx",
                    "CidrBlock": "10.0.0.0/16",
                    "CidrBlockState": {
                        "State": "associated"
                    }
                }
            ],
            "IsDefault": false,
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "handson-cloud9-vpc"
                }
            ]
        },
        {
            "CidrBlock": "10.10.0.0/16",
            "DhcpOptionsId": "dopt-xxxxxxxx",
            "State": "available",
            "VpcId": "vpc-xxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxx",
            "InstanceTenancy": "default",
            "CidrBlockAssociationSet": [
                {
                    "AssociationId": "vpc-cidr-assoc-xxxxxxxxxx",
                    "CidrBlock": "10.10.0.0/16",
                    "CidrBlockState": {
                        "State": "associated"
                    }
                }
            ],
            "IsDefault": false,
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "handson-cloud9-vpc-repeat"
                }
            ]
        }
    ]
}

設定されているVPCが全てJSON形式で表示された。

続いて、--output textだけつけてみる。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws ec2 describe-vpcs \
>   --output text
VPCS    10.0.0.0/16     dopt-xxxxxx   default False   xxxxxxxxxxx    available       vpc-xxxxxxx
CIDRBLOCKASSOCIATIONSET vpc-cidr-assoc-xxxxxxxxxxxx        10.0.0.0/16
CIDRBLOCKSTATE  associated
TAGS    Name    handson-cloud9-vpc
VPCS    10.10.0.0/16    dopt-xxxxxxx   default False   xxxxxxxxxxx      available      vpc-xxxxxxx
CIDRBLOCKASSOCIATIONSET vpc-cidr-assoc-xxxxxxxxxxxx        10.10.0.0/16
CIDRBLOCKSTATE  associated
TAGS    Name    handson-cloud9-vpc-repeat
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

値だけが出力された。コンパクトだけど見づらい。。

次は--filterと--outputをつける。↑の形式で、今回作ったVPCだけが表示されるはず。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws ec2 describe-vpcs \
>  --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
>  --output text
VPCS    10.10.0.0/16    dopt-xxxxxxx   default False   xxxxxxxxxxx      available      vpc-xxxxxxx
CIDRBLOCKASSOCIATIONSET vpc-cidr-assoc-xxxxxxxxxxxx        10.10.0.0/16
CIDRBLOCKSTATE  associated
TAGS    Name    handson-cloud9-vpc-repeat
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ 

想定通りだった。

最後に--queryをつける。'Vpcs[].Tags[?Key == `Name`].Value'は、上記のJSONのフルパスを指定している。?Key == `Name`の部分は"タグのキーがNAMEのものだけを対象とする"という意味。

[cloudshell-user@ip-10-xxx-xxx-xxx ~]$ aws ec2 describe-vpcs \
>   --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
>   --query 'Vpcs[].Tags[?Key == `Name`].Value' \
>   --output text
handson-cloud9-vpc-repeat
[cloudshell-user@ip-10-xxx-xxx-xxx ~]$

これでこの手順は一通り完了。

おわりに

当日のハンズオンでは時間の都合もあり、ものの数分で完了させたが、改めてじっくりやってみると、たくさん学びがあった。この後の手順も復習したいと思う。(比較的似た手順が多いので、今後はブログでここまで長く書くことはないと思うが。。)