michimani.net

IAM の Condition によるアクセス制御を試してみる

2020-07-05

AWS 認定ソリューションアーキテクト - プロフェッショナルの勉強をしている中で、 IAM の Condition によるアクセス制御の話が出てきたので、 S3 へのアクセスで実際に試してみようと思います。

目次

IAM ポリシーの作成

アクセス制御用の IAM ポリシーを作成します。今回は次のような制御を考えます。

ListObjects または ListObjectsV2 API を実行するためには s3:ListBucket のアクセス許可が必要なので、このアクションに対して Condition エレメントで条件を指定します。

Condition エレメント

IAM ポリシーの Condition エレメントでは、予め用意されている StringEqualsNumericGreaterThan といった条件演算子によって, リクエストに含まれるコンテキストの値と条件の一致をチェックします。

条件演算子は次のような種類に分けられています。

今回の条件は 「S3 に対する ListObjects または ListObjectsV2 API で取得できるオブジェクトのキー数の最大数を 2 とする」 なので、文字列条件演算子の NumericLessThanEquals を使用して次のように記述します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*"
            ],
            "Resource": "arn:aws:s3:::iam-condition-test-bucket"
        },
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::iam-condition-test-bucket",
            "Condition": {
                "NumericLessThanEquals": {
                    "s3:max-keys": "2"
                }
            }
        }
    ]
}

この JSON の内容で IAM ポリシーを作成します。

s3:max-keys の条件演算子を指定すると、 ListObjects または ListObjectsV2max-keys オプションを指定する必要があります。指定しない場合はそもそも条件に一致しないことになります。

If the key that you specify in a policy condition is not present in the request context, the values do not match.

その他、 Condition の詳細については下記の公式ドキュメントも合わせて。

ちなみに、 arn:aws:s3:::iam-condition-test-bucket は今回の確認用に先に作成しておいた S3 バケットで、バケット内にはオブジェクトが 4 つ格納されています。

$ aws s3api create-bucket \
--bucket iam-condition-test-bucket \
--create-bucket-configuration LocationConstraint=ap-northeast-1
{
    "Location": "http://iam-condition-test-bucket.s3.amazonaws.com/"
}

$ aws s3api list-objects-v2 \
--bucket iam-condition-test-bucket \
--query "Contents[].[Key]" \
--output text

sample_0.json
sample_1.json
sample_2.json
sample_3.json

ListObjectsV2 リクエストを実行

今回は AWS CLI で ListObjectsV2 リクエストを実行してみます。

AmazonS3ReadOnlyAccess ポリシーをアタッチした IAM ユーザで実行

まずは S3 への Read Only 権限 (AmazonS3ReadOnlyAccess) を持つ IAM ユーザで ListObjectsV2 を実行してみます。

$ aws s3api list-objects-v2 \
--bucket iam-condition-test-bucket
{
    "Contents": [
        {
            "Key": "sample_0.json",
            "LastModified": "2020-07-05T09:43:05+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        },
        {
            "Key": "sample_1.json",
            "LastModified": "2020-07-05T09:42:12+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        },
        {
            "Key": "sample_2.json",
            "LastModified": "2020-07-05T09:42:17+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        },
        {
            "Key": "sample_3.json",
            "LastModified": "2020-07-05T09:42:51+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        }
    ]
}

バケット内のオブジェクトがすべて取得できました。

Condition 付きの IAM ポリシーをアタッチした IAM ユーザで実行

では、先ほど作成した IAM ポリシーを適当な IAM ユーザにアタッチして ListObjectsV2 を実行してみます。

$ aws s3api list-objects-v2 \
--bucket iam-condition-test-bucket

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

AccessDenied エラーとなり、オブジェクトの一覧が取得できませんでした。

なので、条件に合うように --max-keys オプションを指定して実行してみます。

$ aws s3api list-objects-v2 \
--bucket iam-condition-test-bucket \
--max-keys 2
{
    "IsTruncated": true,
    "Contents": [
        {
            "Key": "sample_0.json",
            "LastModified": "2020-07-05T09:43:05+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        },
        {
            "Key": "sample_1.json",
            "LastModified": "2020-07-05T09:42:12+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        }
    ],
    "Name": "iam-condition-test-bucket",
    "Prefix": "",
    "MaxKeys": 2,
    "EncodingType": "url",
    "KeyCount": 2,
    "NextContinuationToken": "17DiagPib4DkESmD7teHiRKAUOX3+2+PwEfdQ/orj+JJiIY9+KzSt0FY73/EOModsutwA/GSThwc="
}

取得できました。残りのオブジェクトを取得するためには、レスポンスの NextContinuationToken を使って次のようにリクエストします。

$ aws s3api list-objects-v2 \
--bucket iam-condition-test-bucket \
--max-keys 2 \
--continuation-token 17DiagPib4DkESmD7teHiRKAUOX3+2+PwEfdQ/orj+JJiIY9+KzSt0FY73/EOModsutwA/GSThwc=
{
    "IsTruncated": false,
    "Contents": [
        {
            "Key": "sample_2.json",
            "LastModified": "2020-07-05T09:42:17+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        },
        {
            "Key": "sample_3.json",
            "LastModified": "2020-07-05T09:42:51+00:00",
            "ETag": "\"ff2238a281fccd41c7698ef7a1e2236d\"",
            "Size": 21,
            "StorageClass": "STANDARD"
        }
    ],
    "Name": "iam-condition-test-bucket",
    "Prefix": "",
    "MaxKeys": 2,
    "EncodingType": "url",
    "KeyCount": 2,
    "ContinuationToken": "17DiagPib4DkESmD7teHiRKAUOX3+2+PwEfdQ/orj+JJiIY9+KzSt0FY73/EOModsutwA/GSThwc="
}

今回の条件は "s3:max-keys": "2" なので、次のリクエストでは AccessDenied になります。

$ aws s3api list-objects-v2 \
--bucket iam-condition-test-bucket \
--max-keys 3

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

まとめ

IAM の Condition エレメントを使用して S3 への ListObjects または ListObjectsV2 API のリクエストを制御してみました。

Condition を使用したアクセス制御としては、 EC2 インスタンスに特定のタグがなければ起動できないようにする例がありました。

また、今回は個人の AWS アカウント内での制御でしたが、 AWS Organizations の SCP (サービスコントロールポリシー) を使うことで組織内の AWS アカウントに対しても統一されたアクセス制御をすることができます。

このあたりは SAP の試験でもよく出てくる部分みたいなので、しっかり理解していきたいところです。


comments powered by Disqus