yuj1osm's tech blog

クラウドやセキュリティなど

Amazon S3アクセスポイントを使用したアクセス制御

Amazon S3アクセスポイントを使用したアクセス制御について紹介します。

Amazon S3アクセスポイントとは

バケットに対して、アクセスポイントという単位でアクセス権限を設定することができます。

docs.aws.amazon.com

何が嬉しいのか

従来のバケットポリシーは、バケットに対して1つ設定するものだったので、アクセス要件が変わると既存のバケットポリシーを変更する必要がありました。
要件が追加されるたびにバケットポリシーが長く複雑になり、管理が大変になってしまいます。
さらに、既存のポリシーを変更するため、設定を誤ると影響範囲も広くなってしまいます。

アクセスポイントはバケットに対して複数作成することができ、アクセスポイントごとにポリシーを設定することができます。
そのため、アクセス要件ごとにポリシーを分けることができ、管理しやすくなり、影響範囲を最小限に抑えられます。

S3アクセスポイントを設定してみる

事前準備1:IAMユーザ作成

バケットにアクセスするためのIAMユーザを作成します。
アクセス権限は「AdministratorAccess」を付与します。
※テスト用なので実運用では最小権限にする。

事前準備2:バケット作成

バケットを作成して、ファイルを格納します。

アクセスポイント設定

バケットの設定画面から、「アクセスポイント」→「アクセスポイントの作成」を押下します。

アクセスポイント名を付け、ネットワークオリジンはインターネットを選択する。

アクセスポイントポリシーは、オブジェクトに対する「s3:GetObject」を許可します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<accountID>:user/testuser01"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:ap-northeast-1:<accountID>:accesspoint/ap-testuser01/object/*"
        }
    ]
}

アクセスポイントが作成されました。

アクセスポイント経由でアクセスしてみる

CloudShellから想定通りアクセスできました。

$ aws s3api get-object --bucket arn:aws:s3:ap-northeast-1:<accountID>:accesspoint/ap-testuser01 --key test.txt output.txt
{
    "AcceptRanges": "bytes",
    "LastModified": "2022-10-15T07:47:12+00:00",
    "ContentLength": 3,
    "ETag": "\"900150983cd24fb0d6963f7d28e17f72\"",
    "ContentType": "text/plain",
    "Metadata": {}
}

しかし、このままではアクセスポイントを経由しない場合もアクセスできてしまいます。

$ aws s3api get-object --bucket accesspoints-test-bucket --key test.txt output.txt 
{
    "AcceptRanges": "bytes",
    "LastModified": "2022-10-15T07:47:12+00:00",
    "ContentLength": 3,
    "ETag": "\"900150983cd24fb0d6963f7d28e17f72\"",
    "ContentType": "text/plain",
    "Metadata": {}
}

そこで、アクセスポイントを経由しないアクセスを拒否します。

バケットポリシーに以下を設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::accesspoints-test-bucket/*",
            "Condition": {
                "StringNotEquals": {
                    "s3:DataAccessPointArn": "arn:aws:s3:ap-northeast-1:<accountID>:accesspoint/ap-testuser01"
                }
            }
        }
    ]
}

アクセスポイントを経由した場合のみアクセスできました。

$ aws s3api get-object --bucket arn:aws:s3:ap-northeast-1:<accountID>:accesspoint/ap-testuser01 --key test.txt output.txt
{
    "AcceptRanges": "bytes",
    "LastModified": "2022-10-15T07:47:12+00:00",
    "ContentLength": 3,
    "ETag": "\"900150983cd24fb0d6963f7d28e17f72\"",
    "ContentType": "text/plain",
    "Metadata": {}
}
$ aws s3api get-object --bucket accesspoints-test-bucket --key test.txt output.txt 

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

まとめ

バケットポリシーでのアクセス制御はポリシーが複雑になりがちでした。
アクセスポイントを利用することで、要件ごとにポリシーを分けることができるため、管理がしやすくなりました。