13
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS】S3バケットへシークレットキーを渡さずにファイルをアップロードしてもらう方法

Posted at

こんな時どうする?

ケース1

自分が管理するS3バケットに対して、他の人にファイルをアップロードしてもらいたい

  • 相手からファイルをもらって自分でアップロードする?
  • その人のために新しくアクセスキーとシークレットキーを発行する?

ケース2

SPAなどでフロントエンド側からS3バケットへファイルを直接アップロードしたい

  • フロントエンドからバックエンドへ一旦ファイルをアップロードして、サーバーで受け取ったファイルをS3へアップロードする?

サーバーサイドのバリデーションが必要な場合は有効な方法ですが、サーバーに負荷がかかってしまいます。


どちらのケースでも他の人やフロントエンド側にシークレットキーを渡さずにアップロードしたいものです。

注意

この記事で紹介している方法は、署名バージョン2です。
2014年1月30日以降の新しいリージョンでは署名バージョン4のみがサポートされるため、それらのリージョンへのリクエストは署名バージョン4で行う必要があります。
Authenticating Requests (AWS Signature Version 4)

やり方

S3の「署名付きURL」という仕組みを使います。

ファイルアップロード用の「署名付きURL」を作るにはプログラムが必要です。
(表示用の署名付きURLであればAWSコンソールから取得することができます)

流れ

  1. アクセスキーとシークレットキーを使って署名付きURLを生成します
  2. 相手側に生成した署名付きURLを送ります
  3. 署名付きURLに向けてファイルをアップロードします

署名付きURLを作る時にはシークレットキーが必要ですが、作ったURLを使う時はシークレットキーは必要ありません。

(SPAのケースだと「署名付きURL」の生成はサーバーサイドで行う必要があります)

準備

  • AWS CLI のインストールと設定が済んでいること
  • node のインストールと設定が済んでいること
  • S3バケットを作成する
  • S3バケットにアクセスできるユーザーを作る
  • ユーザーのアクセスキー・シークレットキーを作る
  • AWS CLIにユーザーのアクセスキー・シークレットキーを設定する

この辺りの詳細は割愛します。

署名付きURLの生成

パッケージインストール

shell
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner

サンプルプログラム

generatePresignedUrl.js
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');

// 署名付きURLを生成する関数
const generatePresignedUrl = async (region, bucketName, objectKey, expires) => {
    const client = new S3Client({ region: region });
    const params = { Bucket: bucketName, Key: objectKey };

    try {
        const url = await getSignedUrl(client, new PutObjectCommand(params), { expiresIn: expires });
        console.log("署名付きURL:", url);
    } catch (error) {
        console.error("エラーが発生しました:", error);
    }
};

// コマンドライン引数の処理
const parseArgs = () => {
    const args = process.argv.slice(2);
    if (args.length < 4) {
        console.error("使用法: node generatePresignedUrl.js <リージョン> <バケット名> <オブジェクトキー> <署名付きURLの有効期限>");
        process.exit(1);
    }
    return {
        region: args[0],
        bucketName: args[1],
        objectKey: args[2],
        expires: args[3]
    };
};

// メイン関数
(async () => {
    const { region, bucketName, objectKey, expires } = parseArgs();
    await generatePresignedUrl(region, bucketName, objectKey, expires);
})();

サンプルプログラム実行して「署名付きURL」生成

shell
node generatePresignedUrl.js リージョン バケット名 ファイル名 有効期限秒数

ここから相手側で行う処理です

署名付きURLを相手側に伝えます
(あるいはサーバーサイドからフロントエンドへURLを送ります)

ファイルをアップロードする
次の例はcurlコマンドを使っていますが他のツールでも構いません。プログラムでアップロードすることも難しくないでしょう。

shell
curl -X PUT "署名付きURLを貼り付ける" \
-H "Content-Type: image/jpeg" \
-H "x-amz-content-sha256: UNSIGNED-PAYLOAD" \
--data-binary "@ファイル名"

注意

  • 「Content-Type: image/jpeg」はアップロードするファイルに応じて変更してください

  • ファイル名の前にある@は必要です。curlコマンドはファイル名の前に@を付けると「Content-Length」を自動で算出してヘッダーに差し込んでくれます

シークレットキーを渡さずにファイルのアップロードができました

署名バージョン4

今回は「署名バージョン2」についてのサンプルでしたが、今機会があれば「署名バージョン4」についてもお伝えできればと思います。

参考

署名付き URL を使用したオブジェクトのアップロード

Create a presigned URL for Amazon S3 using an AWS SDK

13
4
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
13
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?