ResourceTagとRequestTagの挙動の違いを確認する

# 概要
AWSではリソースに対してタグを付与することができ、このタグを利用することで効率的にリソースを管理することが出来ます。
単純に特定のタグが付与されたリソースをフィルタリングするだけではなく、例えば特定のタグが付与されたリソースだけに特定の操作を実行したり、ユーザーに対して特定のタグが付与されたリソースにのみ操作を許可するなどが可能です。  
この"操作を制限するためのタグ利用"ですが、利用方法は以下の3種類があります。つまり、**この3種類の条件を正しく理解・活用出来ていないと、可能なはずの操作が出来なかったり・禁止したはずの操作が出来てしまったり、という問題が発生します。**
本記事ではLambdaの編集を例としてリソースタグ・リクエストタグを条件にIAMポリシーを設定し、実際の挙動を確認した結果をご紹介します。

|条件|条件キー |内容|
|---|---|---|
| リソース | ResourceTag/key-name  | それらのリソースのタグに基づいて、AWS サービスリソースへのアクセスを制御します。これを行うには、ResourceTag/key-name 条件キーを使用して、リソースにアタッチされたタグに基づいてリソースへのアクセスを許可するかどうか決定します。 |
| リクエスト | RequestTag/key-name  | リクエストで渡すことができるタグを制御します。これを行うには、aws:RequestTag/key-name 条件キーを使用して、AWS リソースのタグ付けを行うリクエストで渡すことができるタグキーバリューのペアを指定します。 |
| 認証プロセスの一部 | TagKeys  |aws:TagKeys 条件キーを使用して、特定のタグキーがリクエストに存在することができるかどうかを制御します。 |

以下の公式ドキュメントより引用

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_tags.html#access_tags_control-tag-keys


# ユースケース
タグを利用して操作をコントロールしたいケース

# ResourceTag
## ResourceTagの利用方法
ResourceTagは"それらのリソースのタグに基づいて、AWS サービスリソースへのアクセスを制御します。"
AWSリソースへのアクセス＝リソースの操作と考え、実際にやってみましょう。

### IAMポリシー
利用するユーザーにLambdaに関する参照権限(AWSLambda_ReadOnlyAccess)と、`"StringEquals": {"aws:ResourceTag/AccessControl": "allow"}`の条件でLambda関数に対するフルアクセスを付与します。(あと、Lambda作成時に必要なので`iam:PassRole`も付与しておきます)
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": [
                "lambda:*"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/AccessControl": "allow"
                }
            }
        },
        {
            "Sid": "Statement2",
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```


### Lambda関数のタグ
テストで利用するLambda関数として、`AccessControl: deny`・`AccessControl: allow`のタグが付与された二つの関数を用意します。
```
# aws lambda get-function --function-name test-function-1 --query [Configuration.FunctionName,Tags]
[
    "test-function-1",
    {
        "AccessControl": "allow"
    }
]

# aws lambda get-function --function-name test-function-2 --query [Configuration.FunctionName,Tags]
[
    "test-function-2",
    {
        "AccessControl": "deny"
    }
]
```

### ResourceTagでの制限の挙動
それでは、以下の操作をやってみます。
①`AccessControl: allow`のタグが付与された`test-function-1`を編集
②`AccessControl: deny`のタグが付与された`test-function-2`を編集
③`AccessControl: allow`のタグを付与する`test-function-3`の作成
④`AccessControl: deny`のタグを付与する`test-function-4`の作成
⑤タグを付与しない`test-function-5`の作成

①`AccessControl: allow`のタグが付与された`test-function-1`を編集
→ 問題なく編集出来ました。
```
# aws lambda update-function-configuration --function-name test-function-1
{
    "FunctionName": "test-function-1",
...略...
    }
}
```
②`AccessControl: deny`のタグが付与された`test-function-2`を編集
→ 権限エラーになり、編集出来ませんでした。
```
# aws lambda update-function-configuration --function-name test-function-2

An error occurred (AccessDeniedException) when calling the UpdateFunctionConfiguration operation: User: arn:aws:iam::xxxxxxxxxxxx:user/test-user is not authorized to perform: lambda:UpdateFunctionConfiguration on resource: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:test-function-2 because no identity-based policy allows the lambda:UpdateFunctionConfiguration action
```
③`AccessControl: allow`のタグを付与する`test-function-3`の作成
→ 問題なく作成出来ました。
![{732CCAC8-D665-4DEE-BD97-B315975FF42E}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/2a3eaee7-baea-f8f3-5fe4-c694c02d51e1.png)
![{47C6FC6E-68B9-4E69-938D-D2F7CC025BA9}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/6d6dd923-c438-d206-e39d-a28314564b36.png)

④`AccessControl: deny`のタグを付与する`test-function-4`の作成
→ 権限エラーになり、編集出来ませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/0d45ca45-fda4-6b68-fba7-344e190b9fda.png)



⑤タグを付与しない`test-function-5`の作成
→ 権限エラーになり、編集出来ませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/d1d5774d-2f3a-2b83-77d8-806d0e304d06.png)





# RequestTag
## RequestTagの利用方法
RequestTagは"リクエストで渡すことができるタグを制御します。"。
実際にタグ付与の操作を行ってみましょう。

### IAMポリシー
利用するユーザーにLambdaに関する参照権限(AWSLambda_ReadOnlyAccess)と、`"StringEquals": {"aws:RequestTag/AccessControl": "allow"}`の条件でLambda関数に対するフルアクセスを付与します。(あと、Lambda作成時に必要なので`iam:PassRole`も付与しておきます)
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": [
                "lambda:*"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/AccessControl": "allow"
                }
            }
        },
        {
            "Sid": "Statement2",
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```


### Lambda関数のタグ
テストで利用するLambda関数として、`AccessControl: deny`・`AccessControl: allow`のタグが付与された二つの関数を用意します。
```
# aws lambda get-function --function-name test-function-1 --query [Configuration.FunctionName,Tags]
[
    "test-function-1",
    {
        "AccessControl": "allow"
    }
]

# aws lambda get-function --function-name test-function-2 --query [Configuration.FunctionName,Tags]
[
    "test-function-2",
    {
        "AccessControl": "deny"
    }
]
```

### RequestTagでの制限の挙動
ResourceTagの場合と同様に、以下の操作をやってみます。
①AccessControl: allowのタグが付与されたtest-function-1を編集
②AccessControl: denyのタグが付与されたtest-function-2を編集
③AccessControl: allowのタグを付与するtest-function-3の作成
④AccessControl: denyのタグを付与するtest-function-4の作成
⑤タグを付与しないtest-function-5の作成

①AccessControl: allowのタグが付与されたtest-function-1を編集
→ 権限エラーになり、編集出来ませんでした。
```
# aws lambda update-function-configuration --function-name test-function-1

An error occurred (AccessDeniedException) when calling the UpdateFunctionConfiguration operation: User: arn:aws:iam::xxxxxxxxxxxx:user/test-user is not authorized to perform: lambda:UpdateFunctionConfiguration on resource: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:test-function-1 because no identity-based policy allows the lambda:UpdateFunctionConfiguration action
```
②AccessControl: denyのタグが付与されたtest-function-2を編集
→ 権限エラーになり、編集出来ませんでした。
```
# aws lambda update-function-configuration --function-name test-function-2

An error occurred (AccessDeniedException) when calling the UpdateFunctionConfiguration operation: User: arn:aws:iam::xxxxxxxxxxxx:user/test-user is not authorized to perform: lambda:UpdateFunctionConfiguration on resource: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:test-function-2 because no identity-based policy allows the lambda:UpdateFunctionConfiguration action
```

③AccessControl: allowのタグを付与するtest-function-3の作成
→ 問題なく作成出来ました。
![{3FA2BCFE-A484-4A84-95D1-5EAB41F799E9}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/0d66725a-ba6b-014d-d9f1-4b99e973797d.png)
![{5FA8E49E-E17E-4AB3-83E1-2FD46A3EC5D9}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/c352c342-9aa2-4fd7-b5a4-037b33c2624c.png)

④AccessControl: denyのタグを付与するtest-function-4の作成
→ 権限エラーになり、作成出来ませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/24e4b89e-d0e9-0701-6395-4c45cf2f4d61.png)

⑤タグを付与しないtest-function-5の作成
→ 権限エラーになり、作成出来ませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/55145e65-dd56-c0c3-7dde-9798a49153a2.png)

# ドキュメントからみる利用方法
Lambdaを例に実際に設定してみた例は上記の通りですが、実際にどのアクションに対してRequestTag/ResourceTagが有効かどうかは以下のドキュメントに記載があります。(各サービス毎)
基本的にはRequestTagは作成系にのみ有効で、既存リソースに対する操作制限にはResourceTagを利用することになるようです。

https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_awslambda.html

例えば、アクションがCreateFunctionの場合は条件キー(図の一番右の列)でRequestTagを利用出来るため、③-⑤の操作に影響を与えました。
また、このアクションのリソースタイプはfunctionであるため、functionについてはResourceTagも有効でした。

![{B9BA07AD-1429-4450-8401-51CDF1757449}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/882725e2-995d-1755-5fbc-8aae9a9c810e.png)

一方、アクションがUpdateFunctionConfigurationの場合は条件キーとしてResourceTagが利用出来ないため、条件に合致せず①-②の操作は実行出来なかったようです。(下の図の通り、LayerやVpcIdsは条件として機能する)
![{FE8288FD-EBB1-4E24-8556-2047CC90F57C}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/258a33df-4432-e3a3-1a59-bd496bb64978.png)

リソースについても、どのリソースでRequestTagを利用できるかは以下に示されています。

![{4E952E54-21FF-4E9D-A8B1-BF85697E4AE2}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662709/833095be-6e2d-75dc-c7f2-5182784777fb.png)

Lambdaについては表を一通り眺めればおおよそは理解出来るかと思いますが、EC2のような膨大なアクションを含むサービスの場合は確認するだけでかなり大変です。EC2インスタンスの起動停止や外部公開系の操作、ルーティングの編集など重要度の高いアクションだけでも確認しておくと良いでしょう。

https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_amazonec2.html




# まとめ 
本記事ではIAMポリシーでユーザーの操作を条件付きで制限する際に利用出来るResourceTagとRequestTagの違いについて確認しました。細かくアクションを確認していくのはかなり大変ですが、タグベースでのコントロールは適切な権限統制のために肝となる要素の一つと思いますので、誤った設定を行わないよう注意していきたいですね。