AWS S3へのファイルアップロードと署名付URLによるアクセス制限
AWS S3へのファイルアップロードと署名付URLによるアクセス制限方法を記述する。
目次
AWS S3へのファイルアップロードと署名付URLによるアクセス制限
1.概要
S3にアップロードされた各種ドキュメントファイル(画像、PDF、動画など)に対して有効期限内であればアクセス可能な署名付URLを発行する。
署名付URLは以下のような形式で生成され、署名付URLを発行した都度X-Amz-Signature部分の値が変化するため、
署名付URLは特定システムログイン者のみ知るURLとすることが可能であり、アクセス制御として利用が可能である。
署名付URL
https://<S3バケット名>/<S3オブジェクト名>?
X-Amz-Algorithm=<リクエストの署名を作成するのに使用したハッシュアルゴリズム>&
X-Amz-Date=20221121T053410Z&
X-Amz-SignedHeaders=host&
X-Amz-Expires=299&
X-Amz-Credential=<認証情報スコープ:アクセスキー、日付、対象とするリージョン、リクエストするサービス、および終了文字列>&
X-Amz-Signature=<シグネチャ:都度変化する>
システム構成
2.処理シーケンス
3.ポイント
- S3にファイル類をアップロードした時点では基本的な権限設定としてはインターネットから不特定多数によるアクセスは不可能となっている。
- 署名付URL発行した時点から有効期限の間だけは、インターネットからアクセスは不可能となっている。※有効期限が切れるとアクセス時は「AccessDenied」となる
- 有効期限内の署名付URLは不特定多数からのアクセスは可能となるが、署名がランダムに付与されているためOAuthのアクセスークンと同様の位置づけと考えセキュリティ的には問題無い。
- S3に保管されたファイルをユーザが参照するため、ファイルサイズの大きなファイルを安価なストレージに配置する事でWebサーバの負荷やWebサーバ付近の回線帯域を圧縮可能。
4.ソースコード
package jp.a_frontier.aws;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.time.Instant;
import java.util.Date;
import com.amazonaws.AmazonClientException;
import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
public class S3_Signature {
public static void main(String[] args) throws IOException {
AWSCredentials credentials = null;
try {
credentials = new ProfileCredentialsProvider("default").getCredentials();
} catch (Exception e) {
throw new AmazonClientException(
"Cannot load the credentials from the credential profiles file. " +
"Please make sure that your credentials file is at the correct " +
"location (C:\\Users\\XXXXXX\\.aws\\credentials), and is in valid format.",
e);
}
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion("ap-northeast-1")
.build();
String bucketName = "MyBucketName";
String objectKey = "aa.pdf";
System.out.println("===========================================");
System.out.println("Getting Started with Amazon S3");
System.out.println("===========================================\n");
System.out.println("Listing buckets");
for (Bucket bucket : s3.listBuckets()) {
System.out.println(" - " + bucket.getName());
}
System.out.println();
S3Object object = s3.getObject(new GetObjectRequest(bucketName, objectKey));
System.out.println("Content-Type: " + object.getObjectMetadata().getContentType());
Date expiration = new Date();
expiration.setTime(Instant.now().toEpochMilli() + 1000 * 60 * 1);// 有効期限1分
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey)
.withMethod(HttpMethod.GET) // GET のみ許可する
.withExpiration(expiration);
URL presignedUrl = s3.generatePresignedUrl(request);
System.out.println("presignedUrl="+presignedUrl);
}
}