8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

aws-sdk-java-v2に追加されたS3Presigner

Last updated at Posted at 2020-06-26

TL;DR

  • AWS SDK for Java 2.0に、S3Presignerが追加された
  • virtual-hosted styleにデフォルトで対応
  • httpsにデフォルトで対応
  • 有効期限の設定方法が変更
  • 署名付URLの生成には、S3Presignerを使用しましょう

はじめに

この記事は、JavaやScalaでAWSを利用するバックエンド、およびSRE業務に従事する人を対象にしています。

S3の署名付URLとは

S3には、オブジェクトのダウンロードとアップロードのために発行するURLに署名をつけることによって、そのオブジェクトへのアクセスを制限する仕組みがあります。

AWS SDK for Java 2.10.12以前

AWS SDK for Java 2.10.12以前では、AwsS3V4Signerを使用して、Presigned URLを生成していました。
以下、サンプルコードは、scalaで記述しています。

before.scala
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider
import software.amazon.awssdk.auth.signer.AwsS3V4Signer
import software.amazon.awssdk.auth.signer.params.Aws4PresignerParams
import software.amazon.awssdk.http.{SdkHttpFullRequest, SdkHttpMethod}

val request = SdkHttpFullRequest
  .builder()
  .encodedPath("bucket/key")
  .host("s3.ap-northeast-1.amazonaws.com")
  .method(SdkHttpMethod.GET)
  .protocol("https")
  .build()

val params = Aws4PresignerParams
  .builder()
  .expirationTime(Instant.now().plusSeconds(300)
  .awsCredentials(DefaultCredentialsProvider.create().resolveCredentials())
  .signingName("s3")
  .signingRegion("ap-northeast-1")
  .build()

AwsS3V4Signer.create().presign(request, params).getUri

// 生成される署名付URLの形式
// https://s3.ap-northeast-1.amazonaws.com/bucket/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200625T000000Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Credential=XXX&X-Amz-Signature=YYY

AWS SDK for Java 2.10.12以後

AWS SDK for Java 2.10.12から、S3Presignerが追加されました1。引き続きAwsS3V4Signerは使用できますが、S3Presignerを使うことが推奨されています。この理由については後述しますが、一方でS3Presignerの内部実装には、依然、AwsS3V4Signerが使用されています。

after.scala
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.s3.model.GetObjectRequest
import software.amazon.awssdk.services.s3.presigner.S3Presigner
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest

val presigner: S3Presigner = S3Presigner
    .builder()
    .region("ap-northeast-1")
    .build()

val request = GetObjectRequest
  .builder()
  .bucket("bucket")
  .key("key")
  .build()

val presignRequest = GetObjectPresignRequest
  .builder()
  .signatureDuration(Duration.ofSeconds(300))
  .getObjectRequest(request)
  .build()

presigner.presignGetObject(presignRequest).url.toURI

// 生成される署名付URLの形式
// https://bucket.s3.ap-northeast-1.amazonaws.com/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200625T000000Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Credential=XXX&X-Amz-Signature=YYY

何が変わった?

1. virtual-hosted style

生成されるURLを前後で比較すると、バケット名の位置が異なることがわかります。

"https://s3.ap-northeast-1.amazonaws.com/bucket/key" // 前: path style
"https://bucket.s3.ap-northeast-1.amazonaws.com/key" // 後: virtual-hosted style

両者の違いについては、以下を参照ください。

  1. パス形式のリクエスト
  2. 仮想ホスティング形式のリクエスト
val request = SdkHttpFullRequest
  .builder()
  .encodedPath("key")
  .host("bucket.s3.ap-northeast-1.amazonaws.com")
  .method(SdkHttpMethod.GET)
  .protocol("https")
  .build()

なお、AwsS3V4SignerでもSdkHttpFullRequestを上記のようにすることで、virtual-hosted styleの署名付URLが生成できますが、S3Presignerは実装方法を意識する必要がありません。

2. protocolの指定方法

AwsS3V4Signerでは、.protocol("https")の部分にある通り、プロトコルの指定ができました。しかし、 S3Presignerにはプロトコルを指定するメソッドがありません。これについては、内部的にhttpsがデフォルトで指定されていることに起因します。使用するシーンは想像しにくいですが、以下のようにendpointを上書きすることで、httpを選択することも可能です。

val presigner: S3Presigner = S3Presigner
    .builder()
    .region("ap-northeast-1")
    .endpointOverride(new URI("http://s3.ap-northeast-1.amazonaws.com"))
    .build()

3. 有効期限の指定方法

AwsS3V4Signerでは、有効期限として設定したい未来の日時を指定する方法でした。しかし、S3Presignerでは有効期間をDurationとして指定する方法が採用されています。

// 前
val params = Aws4PresignerParams
  .builder()
  .expirationTime(Instant.now().plusSeconds(300)

// 後
val presignRequest = GetObjectPresignRequest
  .builder()
  .signatureDuration(Duration.ofSeconds(300))

まとめ

Amazon S3 path-style 廃止予定 – それから先の話 –

AWSは2020年9月30日以降で作成されるバケットについて、path styleをサポートしないことを発表しています。このため、S3Presignerへの変更は早期に対応しておく必要があると言えます。

  1. 追加までの経緯は、こちら

8
2
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
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?