AWS CLI のオプションで JSON 形式のポリシーを渡したいとき

記事タイトルとURLをコピーする


コーヒーが好きな木谷映見です。

S3 ゲートウェイ型 VPC エンドポイントを AWS CLI で作成しようとした際、エンドポイントポリシーの指定の仕方で少し迷ったので、手順をまとめます。

AWS CLI で JSON 形式のエンドポイントポリシーを設定したい

AWS CLI で JSON 形式のエンドポイントポリシーを組み込む方法ですが、おそらく IAM ポリシーの作成コマンドが参考になるだろうと思い調べたら、いい例がありました。

awscli.amazonaws.com

上記コマンドリファレンスの最下部に Examples が載っていましたので、参考にして VPC エンドポイントポリシーを作成します。

構成例

以下のように、特定の IAM ロールが付与された EC2 インスタンスから特定の S3 バケットへのアクセスを許可する VPC エンドポイントポリシーが付与された S3 ゲートウェイ型 VPC エンドポイントを AWS CLI で作成します。

ポリシードキュメントの .json ファイルを作成し読み込むパターン

今回は AWS CLI を CloudShell で実行していきます。
ナビゲーションバーの CloudShell アイコンをクリックして CloudShell を開きます。

CloudShell が開いたら、以下コマンドを実行し、vim でポリシードキュメントを作成します。

vim vpc_endpoint_policy.json

:set paste と入力し、Enter を押下します。

i を押下して編集モードに移行します。

以下のポリシードキュメントを貼り付けます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::emiki",
                "arn:aws:s3:::emiki/*"
            ],
            "Condition": {
                "ArnEquals": {
                    "aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"
                }
            }
        }
    ]
}

インデント崩れしません。

esc を押下し、ノーマルモードに戻ります。
:wq と入力し、ファイルを保存して閉じます。

以下 cat コマンドでポリシードキュメントを確認します。
貼り付けたポリシーが表示されれば OK です。

cat vpc_endpoint_policy.json
  • 実行結果
[cloudshell-user@ip-10-0-187-211 ~]$ cat vpc_endpoint_policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::emiki",
                "arn:aws:s3:::emiki/*"
            ],
            "Condition": {
                "ArnEquals": {
                    "aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"
                }
            }
        }
    ]
}
[cloudshell-user@ip-10-0-187-211 ~]$

以下コマンドを実行し、S3 ゲートウェイ型 VPC エンドポイントを作成します。
create-vpc-endpoint — AWS CLI 2.9.4 Command Reference

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-06261122d9080ac9e \
  --service-name com.amazonaws.ap-northeast-1.s3 \
  --route-table-ids rtb-0b9d6dcf281069286 \
  --vpc-endpoint-type Gateway \
  --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
  --policy-document file://$(pwd)/vpc_endpoint_policy.json
  • --vpc-id vpc-06261122d9080ac9e \:VPC ID を設定します。
  • --service-name com.amazonaws.ap-northeast-1.s3 \:今回は S3 の VPC エンドポイントを作成するので、com.amazonaws.ap-northeast-1.s3 を指定します。
  • --route-table-ids rtb-0b9d6dcf281069286 \:ゲートウェイ型 VPC エンドポイントはルートテーブルにルートが追加されます。ルートを追加するルートテーブル ID を設定します。
  • --vpc-endpoint-type Gateway \:ここでゲートウェイ型を指定します。
  • --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \:タグ付けします。
  • --policy-document file://$(pwd)/vpc_endpoint_policy.json :作成したポリシードキュメントの .json ファイルを指定しています。

  • 実行結果

[cloudshell-user@ip-10-0-187-211 ~]$ aws ec2 create-vpc-endpoint \
>   --vpc-id vpc-06261122d9080ac9e \
>   --service-name com.amazonaws.ap-northeast-1.s3 \
>   --route-table-ids rtb-0b9d6dcf281069286 \
>   --vpc-endpoint-type Gateway \
>   --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
>   --policy-document file://$(pwd)/vpc_endpoint_policy.json
{
    "VpcEndpoint": {
        "VpcEndpointId": "vpce-084701c6521612593",
        "VpcEndpointType": "Gateway",
        "VpcId": "vpc-06261122d9080ac9e",
        "ServiceName": "com.amazonaws.ap-northeast-1.s3",
        "State": "available",
        "PolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::emiki\",\"arn:aws:s3:::emiki/*\"],\"Condition\":{\"ArnEquals\":{\"aws:PrincipalArn\":\"arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole\"}}}]}",
        "RouteTableIds": [
            "rtb-0b9d6dcf281069286"
        ],
        "SubnetIds": [],
        "Groups": [],
        "PrivateDnsEnabled": false,
        "RequesterManaged": false,
        "NetworkInterfaceIds": [],
        "DnsEntries": [],
        "CreationTimestamp": "2022-12-06T05:29:25+00:00",
        "Tags": [
            {
                "Key": "Name",
                "Value": "gateway-vpcendpoint-s3"
            }
        ],
        "OwnerId": "123456789012"
    }
}
[cloudshell-user@ip-10-0-187-211 ~]$

ポリシードキュメントを変数に格納するパターン

わざわざポリシードキュメントファイルを作成しなくても、変数に JSON を丸ごとぶっこんでしまうこともできました。

変数 POLICY に、ポリシードキュメントの JSON を格納します。

POLICY='
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::emiki",
                "arn:aws:s3:::emiki/*"
            ],
            "Condition": {
                "ArnEquals": {
                    "aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"
                }
            }
        }
    ]
}'

変数に格納できているか echo "${POLICY}" で確認します。

  • 実行結果
[cloudshell-user@ip-10-0-187-211 ~]$ echo "${POLICY}"

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::emiki",
                "arn:aws:s3:::emiki/*"
            ],
            "Condition": {
                "ArnEquals": {
                    "aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"
                }
            }
        }
    ]
}
[cloudshell-user@ip-10-0-187-211 ~]$

以下コマンドを実行し、S3 ゲートウェイ型 VPC エンドポイントを作成します。

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-06261122d9080ac9e \
  --service-name com.amazonaws.ap-northeast-1.s3 \
  --route-table-ids rtb-0b9d6dcf281069286 \
  --vpc-endpoint-type Gateway \
  --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
  --policy-document "${POLICY}"
  • 実行結果
[cloudshell-user@ip-10-0-187-211 ~]$ aws ec2 create-vpc-endpoint \
>   --vpc-id vpc-06261122d9080ac9e \
>   --service-name com.amazonaws.ap-northeast-1.s3 \
>   --route-table-ids rtb-0b9d6dcf281069286 \
>   --vpc-endpoint-type Gateway \
>   --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
>   --policy-document "${POLICY}"
{
    "VpcEndpoint": {
        "VpcEndpointId": "vpce-0ccffdd1ddec30c0e",
        "VpcEndpointType": "Gateway",
        "VpcId": "vpc-06261122d9080ac9e",
        "ServiceName": "com.amazonaws.ap-northeast-1.s3",
        "State": "available",
        "PolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::emiki\",\"arn:aws:s3:::emiki/*\"],\"Condition\":{\"ArnEquals\":{\"aws:PrincipalArn\":\"arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole\"}}}]}",
        "RouteTableIds": [
            "rtb-0b9d6dcf281069286"
        ],
        "SubnetIds": [],
        "Groups": [],
        "PrivateDnsEnabled": false,
        "RequesterManaged": false,
        "NetworkInterfaceIds": [],
        "DnsEntries": [],
        "CreationTimestamp": "2022-12-06T05:42:13+00:00",
        "Tags": [
            {
                "Key": "Name",
                "Value": "gateway-vpcendpoint-s3"
            }
        ],
        "OwnerId": "123456789012"
    }
}
[cloudshell-user@ip-10-0-187-211 ~]$

ポリシードキュメントをそのまま CLI コマンドと同時に流すパターン

きれいではないですが、JSON の改行が無ければ一気にポリシーまで記述してコマンドを流すことができました。

  • 実行コマンド①(JSON の改行なし、スペースなし)
aws ec2 create-vpc-endpoint \
--vpc-id vpc-06261122d9080ac9e \
--service-name com.amazonaws.ap-northeast-1.s3 \
--route-table-ids rtb-0b9d6dcf281069286 \
--vpc-endpoint-type Gateway \
--tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
--policy-document '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": "*","Action": "s3:*","Resource": ["arn:aws:s3:::emiki","arn:aws:s3:::emiki/*"],"Condition": {"ArnEquals": {"aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"}}}]}'
  • 実行結果①
[cloudshell-user@ip-10-0-187-211 ~]$ aws ec2 create-vpc-endpoint \
> --vpc-id vpc-06261122d9080ac9e \
> --service-name com.amazonaws.ap-northeast-1.s3 \
> --route-table-ids rtb-0b9d6dcf281069286 \
> --vpc-endpoint-type Gateway \
> --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
> --policy-document '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": "*","Action": "s3:*","Resource": ["arn:aws:s3:::emiki","arn:aws:s3:::emiki/*"],"Condition": {"ArnEquals": {"aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"}}}]}'
{
    "VpcEndpoint": {
        "VpcEndpointId": "vpce-0b8c2bf41f655eed7",
        "VpcEndpointType": "Gateway",
        "VpcId": "vpc-06261122d9080ac9e",
        "ServiceName": "com.amazonaws.ap-northeast-1.s3",
        "State": "available",
        "PolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::emiki\",\"arn:aws:s3:::emiki/*\"],\"Condition\":{\"ArnEquals\":{\"aws:PrincipalArn\":\"arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole\"}}}]}",
        "RouteTableIds": [
            "rtb-0b9d6dcf281069286"
        ],
        "SubnetIds": [],
        "Groups": [],
        "PrivateDnsEnabled": false,
        "RequesterManaged": false,
        "NetworkInterfaceIds": [],
        "DnsEntries": [],
        "CreationTimestamp": "2022-12-06T05:43:37+00:00",
        "Tags": [
            {
                "Key": "Name",
                "Value": "gateway-vpcendpoint-s3"
            }
        ],
        "OwnerId": "123456789012"
    }
}
[cloudshell-user@ip-10-0-187-211 ~]$

  • 実行コマンド②(JSON の改行なし、スペースあり)
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-06261122d9080ac9e \
  --service-name com.amazonaws.ap-northeast-1.s3 \
  --route-table-ids rtb-0b9d6dcf281069286 \
  --vpc-endpoint-type Gateway \
  --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
  --policy-document '  {      "Version": "2012-10-17",      "Statement": [          {              "Effect": "Allow",              "Principal": "*",              "Action": "s3:*",              "Resource": [                  "arn:aws:s3:::emiki",                  "arn:aws:s3:::emiki/*"              ],              "Condition": {                  "ArnEquals": {                      "aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"                  }              }          }      ]  }'
  • 実行結果②
[cloudshell-user@ip-10-0-161-113 ~]$ aws ec2 create-vpc-endpoint \
>   --vpc-id vpc-06261122d9080ac9e \
>   --service-name com.amazonaws.ap-northeast-1.s3 \
>   --route-table-ids rtb-0b9d6dcf281069286 \
>   --vpc-endpoint-type Gateway \
>   --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
>   --policy-document '  {      "Version": "2012-10-17",      "Statement": [          {              "Effect": "Allow",              "Principal": "*",              "Action": "s3:*",              "Resource": [                  "arn:aws:s3:::emiki",                  "arn:aws:s3:::emiki/*"              ],              "Condition": {                  "ArnEquals": {                      "aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"                  }              }          }      ]  }'
{
    "VpcEndpoint": {
        "VpcEndpointId": "vpce-0e56c93537b38657a",
        "VpcEndpointType": "Gateway",
        "VpcId": "vpc-06261122d9080ac9e",
        "ServiceName": "com.amazonaws.ap-northeast-1.s3",
        "State": "available",
        "PolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::emiki\",\"arn:aws:s3:::emiki/*\"],\"Condition\":{\"ArnEquals\":{\"aws:PrincipalArn\":\"arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole\"}}}]}",
        "RouteTableIds": [
            "rtb-0b9d6dcf281069286"
        ],
        "SubnetIds": [],
        "Groups": [],
        "PrivateDnsEnabled": false,
        "RequesterManaged": false,
        "NetworkInterfaceIds": [],
        "DnsEntries": [],
        "CreationTimestamp": "2022-12-06T03:36:54+00:00",
        "Tags": [
            {
                "Key": "Name",
                "Value": "gateway-vpcendpoint-s3"
            }
        ],
        "OwnerId": "123456789012"
    }
}
[cloudshell-user@ip-10-0-161-113 ~]$

失敗談

JSON の改行を含んだままコマンドを実行すると、bash のコマンド文字列解析時に JSON の途中のスペースを引数の区切りと誤認してしまい、こんな感じになります。

  • 実行コマンド
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-06261122d9080ac9e \
  --service-name com.amazonaws.ap-northeast-1.s3 \
  --route-table-ids rtb-0b9d6dcf281069286 \
  --vpc-endpoint-type Gateway \
  --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
  --policy-document '
  {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": "*",
              "Action": "s3:*",
              "Resource": [
                  "arn:aws:s3:::emiki",
                  "arn:aws:s3:::emiki/*"
              ],
              "Condition": {
                  "ArnEquals": {
                      "aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"
                  }
              }
          }
      ]
  }'
  • 実行結果
[cloudshell-user@ip-10-0-161-113 ~]$ aws ec2 create-vpc-endpoint \
> --vpc-id vpc-06261122d9080ac9e \
> --service-name com.amazonaws.ap-northeast-1.s3 \
> --route-table-ids rtb-0b9d6dcf281069286 \
> --vpc-endpoint-type Gateway \
> --tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=gateway-vpcendpoint-s3}]" \
> --policy-document '
> {
> ."Version": "2012-10-17",
> ."Statement": [
> .{
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."Effect": "Allow",
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."Principal": "*",
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."Action": "s3:*",
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."Resource": [
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."arn:aws:s3:::emiki",
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."arn:aws:s3:::emiki/*"
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .],
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."Condition": {
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."ArnEquals": {
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> ."aws:PrincipalArn": "arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCoreRole"
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .}
> .
./             ../            .bash_history  .bash_logout   .bash_profile  .bashrc        .config/       .viminfo       .zshrc         
> .}
> .}
> .]
> }'

An error occurred (InvalidPolicyDocument) when calling the CreateVpcEndpoint operation: Please provide a valid VPC Endpoint policy
[cloudshell-user@ip-10-0-161-113 ~]$

うわあ

以上、小ネタでした。

emi kitani(執筆記事の一覧)

AS部LX課。2022/2入社、コーヒーとサウナが好きです。執筆活動に興味があります。AWS認定12冠。