S3の署名付きURL
(内部を度外視すると)感覚的には「期限付きURLの発行」と呼んだほうがわかりやすい
S3のobjectはdefaultでprivateになっている
docs
参考
2022/1頃からGUI上からの生成できるようになった
なんか割とずっと勘違いしてる気がしてきたmrsekut.icon
メンタルモデルの構築に失敗している
アップロード時に使用するケース
clientが直接S3にアップロードするための署名付きURLを提供する
こういうフローになる
クライアントからサーバーへ署名付きURLを要求するリクエストを送る。
サーバーがAWS S3に対して署名付きURLを生成するリクエストを送る。
AWS S3が署名付きURLをサーバーに返す。
サーバーが署名付きURLをクライアントに返す。
クライアントがそのURLを使用してS3に直接アップロードする。
署名付きURLを使わずに直接サーバーに送る場合は以下のようになる
クライアントからサーバーへ画像を送る。
サーバーがその画像をAWS S3にアップロードする。
何が嬉しいか?
AWSのcredentialをclientに持ってこなくて良い
それは上記の2つのフローどっちでも満たしているだろうmrsekut.icon
サーバー側にファイルを送る必要がないので、サーバーの負荷を軽減できる
でかいファイルの移動が1回で済むのも大きいか
閲覧時に使用するケース
privateなファイルに対して一時的にアクセスを許可するために使う
アクセスできる期限を設けることができる
そのため、主にprivateな画像に対してのみ使う
署名付きURLを作成することで、一時的に他の人もそのリソースを見れるようにできる
特定のIAMの権限で発行できる
雑な流れ
backet名やfile名を指定して、S3から署名付きURLをもらう
そのURLに対して、画像の実体をPUTする
なんで「一度URLのみ発行」の仕組みを採用している #?? 一時的に共有したいからか
ユーザーが多数の場合、それぞれに対して認証情報(IAM ユーザーなど)を用意するのは手間がかかります。代わりに署名付き URL を提供することで一時的なファイルの授受を簡便に行えます。セミナーの参加者に一定期間ファイルを配布したい、サイズの大きなファイルの受け渡しを S3 バケットへのアップロードで行いたい、というケースがあるでしょう。ref 漏洩した場合も被害を最小限に抑えられる
アップロードにもそういう権限を使うってことか
POSTする時
例えばこんな感じのコードで発行できる
code:ts
import aws from 'aws-sdk';
export const getUrlFromS3 = async (filename: string, filetype: string) => {
const s3 = new aws.S3();
const params = {
Bucket: process.env.BUCKET,
Key: filename,
Expires: 60,
ContentType: filetype,
};
const url = s3.getSignedUrl('putObject', params);
return url;
};
publicにする場合は、ACL: 'public-read'をつける
privateな画像を期限付きURLを発行してGETする
特定のIPからgetしたときは常に見えるようにしたい #?? 引数にgetObjectを指定する
署名付きURLの生成に権限は必要ない
error対処
閲覧可能な有効期限を指定できる
そのobjectにアクセスできる人を制限できる
有効期限を指定する
これは署名付きURL自体の期限?
リソースそのものの期限か?
署名付きURLの構造
code:example
?X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=<your-access-key-id>/20130721/us-east-1/s3/aws4_request
&X-Amz-Date=20130721T201207Z
&X-Amz-Expires=86400
&X-Amz-SignedHeaders=host
&X-Amz-Signature=<signature-value>
関連