3
0

More than 1 year has passed since last update.

Amazon S3 Presigned URLのアクセス制御を深堀りする

Last updated at Posted at 2022-09-04

はじめに

S3へのアクセスを制御するために様々な機能がありますが、これらはIAMのアクセス制御と混同して考えられることが多く、両方の機能の関連について、質問を非常に多く受けています。
以前に S3のアクセス制御はまずシンプルに捉えて対応すべき という記事を書きましたが、この記事に書いたように、S3バケットポリシーとIAMポリシーには以下のような違いがあります。

  • S3バケットポリシーは、S3側で、エンティティから行われるアクセスの制御
  • IAMポリシーの場合、エンティティ側で、S3に対して行うアクセスの制御

このように、両者では設定箇所および制御する操作の矢印の方向が異なります。

基本はこの2つでS3バケットやオブジェクトに対するアクセス制御を行いますが、この2つに加えて、全く異なるアクセス制御の要素が加わることがあります。

その代表例と言える 「Presigned URL」 を今回は取り上げます。

Presigned URLとは

誰でも一時的にS3オブジェクトの操作を可能にするためのURLです。

URLを知っていれば、誰でも、インターネット経由でS3オブジェクトの操作が可能となります。

最も基本的な使い方として、クラウドストレージのBoxのように、URLを知っている人に期限付きでファイルをダウンロード(s3:GetObject)させることができます。
さらに、URLの発行の仕方によっては、ダウンロード以外の操作も可能にします。

Presigned URLは、オブジェクトの一時ダウンロードURLを発行する用途として広く認識されていますが、その本質は 「URLを発行するIAMユーザーまたはロールで可能なS3に対する操作を、URLを介して、期限付きでできるようにする」 です。(詳細は後述)

コマンドの発行方法は2通りあり、AWS CLIの「aws s3 presign」を実行するか、AWS SDKで各言語のコマンド(Pythonの場合「generate_presigned_url」)を実行します。
コマンドを実行する時に、操作名、バケット名、オブジェクトキー、HTTPメソッド (GET または PUT)、および有効期限の日時を指定します。

記事執筆時点でCLIには操作名を指定するオプションがありませんので、「s3:GetObject」以外の操作をできるようにしたい場合はSDK一択となります。

Presigned URLの発行とアクセス許可

AWS CLIでURLを発行する場合、暗黙的に「s3:GetObject」の操作が指定されます。

AWS SDKでURLを発行する場合、クエリの記述方法は以下の通りで、1つの任意の操作をClientMethodパラメータで指定できます。
ここに ClientMethod='put_object' と書けば「s3:PutObject」の操作を指定できます。

usage (Python)
url = s3_client.generate_presigned_url(
            ClientMethod=client_method,
            Params=method_parameters,
            ExpiresIn=expires_in
        )
sample query (Python)
s3_client = boto3.client('s3')
client_action = 'put_object'
url = s3_client.generate_presigned_url(
        s3_client, client_action, {'Bucket': args.bucket, 'Key': args.key}, 86400)

IAMポリシー/S3バケットポリシーと「Presigned URL」の関係

前述の方法でURLを発行できますが、このURLを介して何でも操作が可能になるわけではなく、「URLを発行したIAMユーザーが可能なS3の操作」が「URLにつき1つ」発行されたURLを介してできるようになります。

ここで「URLを発行したIAMユーザーが可能なS3の操作」とは、冒頭に紹介した記事でも取り上げている、以下のフローで評価されて決まります。
image.png
引用: IAM Policies and Bucket Policies and ACLs! Oh, My! (Controlling Access to S3 Resources)

また、URLを介して実行可能なコマンドには、Presigned URLの仕様上の制限があり、全てのコマンドが実行できるわけではありません。
参考: Presigned URLs

URLを介したコマンド実行までの間にAWS側でアクセス制御の変更が行われる場合

通常「IAMユーザーがURLを発行」することと「誰かがURLを介してコマンドを実行」することは連続しておらず、必ず両方の操作の間にいくらか時間があります。

URL発行当時のアクセス制御が、コマンドが実行されるまでの間に変更された場合、コマンド実行時点の(変更された)アクセス制御が有効となります。

例えば、URLを発行する時にIAMユーザーが「s3:PutObject」の権限を持っていたとしても、誰かがURLを介してコマンドを実行するまでの間に「s3:PutObject」がIAMポリシーまたはS3バケットポリシーでDenyされた場合、URLを介して「s3:PutObject」を実行できなくなります。

見方を変えれば、IAMユーザーは自身の権限を超えた操作を可能とするURLを発行できないと言えますし、自身の権限を(Presigned URLの仕様上の制限内で)誰にでも渡すことができるとも言えます。

まとめ

以上の内容をまとめると、以下の図のようになります。
image.png
Presigned URLを知る者なら誰でもS3オブジェクトに対する操作が可能となりますが、その操作はURLを発行したIAMユーザーの権限で可能な操作の中から、暗黙または明示的に指定された1つの操作となります。

「一時ダウンロード用途」として良く使われるPresigned URLですが、このアクセス制御の仕組みが分かると、開発の幅が広がりますし、トラブルシューティングにも役立つと思われます。

一つ不便な点として、現状はAWS SDKを使用しない限り「s3:GetObject」以外の操作を許可できない点がありますが、Presigned URLでは誰にでもアクセス権限を渡すことができますから、発行できる前提条件が限られているほうが、セキュリティの観点で良いとも言えます。

参考文献

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0