ソースコードから理解する技術-UnderSourceCode

手を動かす(プログラムを組む)ことで技術を理解するブログ

AWS CLI、GolangでS3のPre Signed URLを取得してみる

AWS CLIGolangで、それぞれS3にあるオブジェクトのPre Signed URLを取得してみました。
やってみた背景としては、リクエストがあった時にS3に配置したオブジェクトを安全にリクエスト元へ渡したい、みたいな要件を耳に挟み

  • Pre Singed URLを作ればいいんじゃないのか
  • 取得元IPは固定だろうから、バケットにIP制限を別途つける

みたいなことを思いついたためです。

バケットにIP制限を付けるあたりは、以下が参考になりそうです。
S3でIP制限 - Qiita

AWS CLIでのPre Signed URL取得

事前にバケットを用意し、ファイルを入れておきます。
またAWS CLIのインストールも必要です。

以下のコマンドで取得できました。

# バケットの中身を確認
$ aws s3 ls s3://your-bucket/

# pre signed urlを発行。--expires-inで有効期間の秒を設定
$ aws s3 presign s3://your-bucket/sample.txt --expires-in 120
https://your-bucket.s3.amazonaws.com/sample.txt?AWSAccessKeyID=xxxxx

取得できたPre Signed URLをブラウザに張り付け、ファイルの中身が表示されることを確認します。
有効期間が過ぎたら再度アクセスして、今度はAccess Deniedになることも確認します。

AWS SDKでの取得

次にaws-sdk-goで取得してみます。
公式サイトのサンプルソースを改変し、以下のようなソースで実行してみました。

package main

import (
	"log"
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

func main() {
	region := os.Args[1]
	bucket := os.Args[2]
	key := os.Args[3]

	log.Printf("your region = %s, bucket = %s, key = %s\n", region, bucket, key)

	sess, err := session.NewSession(&aws.Config{
		Region: aws.String(region)},
	)

	svc := s3.New(sess)

	req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
	})
	urlStr, err := req.Presign(2 * time.Minute)

	if err != nil {
		log.Println("Failed to sign request", err)
	}

	log.Println("Pre signed url : ", urlStr)
}

ビルドし、引数にリージョン・バケット・キーを渡して実行してみます。

$ ./s3-pre-signed-url-get-sample region your-bucket your-key
2019/03/xx xx:xx:xx Pre signed url :  https://your-bucket.s3.amazonaws.com/sample.txt?AWSAccessKeyID=xxxxx

「Pre signed url : 」以降に出力されるPre Signed URLをブラウザに張り付け、ファイルの中身が表示されることを確認します。
こちらも無事、表示されるかと思います。

まとめ

AWS CLIaws-sdk-goを使ってPre Signed URLを取得できることが分かりました。
後はこれらをアプリに組み込み、リクエストがあり次第、取得したPre Signed URLをリクエスト元に返せばいいことになります。

今回作成したGolangのソースは以下にも載せてあります。
GitHub - SrcHndWng/s3-pre-signed-url-get-sample