オブジェクトをアップロードするための署名付き URL の生成 - Amazon Simple Storage Service

オブジェクトをアップロードするための署名付き URL の生成

署名付き URL の作成者がそのオブジェクトへのアクセス許可を持っている場合、署名付き URL を使用して、URL で識別されるオブジェクトにアクセスすることができます。つまり、オブジェクトをアップロードするための署名付き URL を受け取った場合、オブジェクトをアップロードすることができるのは、署名付き URL の作成者がそのオブジェクトをアップロードするのに必要な権限を持っている場合のみです。

デフォルトでは、すべてのオブジェクトおよびバケットはプライベートです。署名付き URL は、ユーザー/顧客が特定のオブジェクトをバケットにアップロードできるようにする必要があるが、AWS セキュリティ認証情報またはアクセス許可を持つことを求めない場合に有用です。

署名付き URL を作成するときは、セキュリティ認証情報を提供し、次にバケット名、オブジェクトキー、HTTP メソッド (オブジェクトのアップロードの PUT)、および有効期限の日時を指定する必要があります。署名付き URL は、指定した期間のみ有効です。つまり、有効期限日時の前にアクションを開始する必要があります。

マルチパートアップロードなど、アクションが複数のステップで構成されている場合、すべてのステップは有効期限が切れる前に開始する必要があります。そうしないと、Simple Storage Service (Amazon S3) が期限切れ URL でステップを開始しようとした場合に、エラーが発生します。

署名付き URL は、有効期限日時まで複数回使用できます。

署名付き URL へのアクセス

署名付き URL は、URL を持つすべてのユーザーに Amazon S3 バケットへのアクセスを許可するため、適切に保護することをお勧めします。署名付き URL の保護の詳細については、「署名付き URL 機能の制限」を参照してください。

有効なセキュリティ認証情報を持つすべてのユーザーが、署名付き URL を作成できます。ただし、オブジェクトを正常にアップロードするには、署名付き URL の基となるオペレーションを実行するアクセス許可を持つユーザーが、署名付き URL を作成する必要があります。詳細については、「署名付き URL を作成できるユーザー」を参照してください。

オブジェクトをアップロードするための署名付き URL の生成

事前署名付き URL は、AWS SDKs for .NET、Java、Ruby、JavaScript、PHP、Python を使用してプログラムで生成できます。

AWS SDK を使用して署名付き URL を生成し、その URL を別のユーザーに教えると、そのユーザーはその URL を使用して Amazon S3 にオブジェクトをアップロードできます。この URL を使用してオブジェクトをアップロードすると、Amazon S3 は指定したバケットにオブジェクトを作成します。署名付き URL で指定したのと同じキーを持つオブジェクトがバケット内に既存する場合、Amazon S3 は既存のオブジェクトをアップロードしたオブジェクトで置き換えます。

Microsoft Visual Studio を使用している場合は、AWS Toolkit for Visual Studio で AWS Explorer を使用して、コードを記述せずに署名付きオブジェクト URL を生成することができます。有効な署名付き URL を受け取ったすべてのユーザーは、オブジェクトをプログラムでアップロードすることができます。詳細については、「AWS Toolkit for Visual Studio ユーザーガイド」の「AWS Explorer から Amazon S3 を使用する」を参照してください。

AWS Explorer をインストールする方法については、「AWS SDK およびエクスプローラーを使用して Amazon S3 で開発する」を参照してください。

次の例では、署名付き URL を使用してオブジェクトをアップロードする方法を示します。

次のコード例は、Amazon S3 の署名付き URL を作成し、オブジェクトをアップロードする方法を示しています。

Go
SDK for Go V2
ヒント

この例を設定および実行する方法については、「GitHub」を参照してください。

// Get a presigned URL for the object. // In order to get a presigned URL for an object, you must // create a Presignclient fmt.Println("Create Presign client") presignClient := s3.NewPresignClient(&client) presignResult, err := presignClient.PresignGetObject(context.TODO(), &s3.GetObjectInput{ Bucket: aws.String(name), Key: aws.String("path/myfile.jpg"), }) if err != nil { panic("Couldn't get presigned URL for GetObject") } fmt.Printf("Presigned URL For object: %s\n", presignResult.URL)
Java
SDK for Java 2.x
ヒント

この例を設定および実行する方法については、「GitHub」を参照してください。

public static void signBucket(S3Presigner presigner, String bucketName, String keyName) { try { PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .contentType("text/plain") .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .putObjectRequest(objectRequest) .build(); PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest); String myURL = presignedRequest.url().toString(); System.out.println("Presigned URL to upload a file to: " +myURL); System.out.println("Which HTTP method needs to be used when uploading a file: " + presignedRequest.httpRequest().method()); // Upload content to the Amazon S3 bucket by using this URL. URL url = presignedRequest.url(); // Create the connection and use it to upload the new object by using the presigned URL. HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type","text/plain"); connection.setRequestMethod("PUT"); OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream()); out.write("This text was uploaded as an object by using a presigned URL."); out.close(); connection.getResponseCode(); System.out.println("HTTP response code is " + connection.getResponseCode()); } catch (S3Exception | IOException e) { e.getStackTrace(); } }
JavaScript
SDK for JavaScript V3
ヒント

この例を設定および実行する方法については、「GitHub」を参照してください。

クライアントを作成します。

// Create service client module using ES6 syntax. import { S3Client } from "@aws-sdk/client-s3"; // Set the AWS Region. const REGION = "REGION"; //e.g. "us-east-1" // Create an Amazon S3 service client object. const s3Client = new S3Client({ region: REGION }); export { s3Client };

署名付き URL を作成して、オブジェクトをバケットにアップロードします。

// Import the required AWS SDK clients and commands for Node.js import { CreateBucketCommand, DeleteObjectCommand, PutObjectCommand, DeleteBucketCommand } from "@aws-sdk/client-s3"; import { s3Client } from "./libs/s3Client.js"; // Helper function that creates an Amazon S3 service client module. import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import fetch from "node-fetch"; // Set parameters // Create a random name for the Amazon Simple Storage Service (Amazon S3) bucket and key export const bucketParams = { Bucket: `test-bucket-${Math.ceil(Math.random() * 10 ** 10)}`, Key: `test-object-${Math.ceil(Math.random() * 10 ** 10)}`, Body: "BODY" }; export const run = async () => { try { // Create an S3 bucket. console.log(`Creating bucket ${bucketParams.Bucket}`); await s3Client.send(new CreateBucketCommand({ Bucket: bucketParams.Bucket })); console.log(`Waiting for "${bucketParams.Bucket}" bucket creation...`); } catch (err) { console.log("Error creating bucket", err); } try { // Create a command to put the object in the S3 bucket. const command = new PutObjectCommand(bucketParams); // Create the presigned URL. const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600, }); console.log( `\nPutting "${bucketParams.Key}" using signedUrl with body "${bucketParams.Body}" in v3` ); console.log(signedUrl); const response = await fetch(signedUrl, {method: 'PUT', body: bucketParams.Body}); console.log( `\nResponse returned by signed URL: ${await response.text()}\n` ); } catch (err) { console.log("Error creating presigned URL", err); } try { // Delete the object. console.log(`\nDeleting object "${bucketParams.Key}"} from bucket`); await s3Client.send( new DeleteObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key }) ); } catch (err) { console.log("Error deleting object", err); } try { // Delete the S3 bucket. console.log(`\nDeleting bucket ${bucketParams.Bucket}`); await s3Client.send( new DeleteBucketCommand({ Bucket: bucketParams.Bucket }) ); } catch (err) { console.log("Error deleting bucket", err); } }; run();

署名付き URL を作成して、オブジェクトをバケットからダウンロードします。

// Import the required AWS SDK clients and commands for Node.js import { CreateBucketCommand, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, DeleteBucketCommand } from "@aws-sdk/client-s3"; import { s3Client } from "./libs/s3Client.js"; // Helper function that creates an Amazon S3 service client module. import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; const fetch = require("node-fetch"); // Set parameters // Create a random names for the S3 bucket and key. export const bucketParams = { Bucket: `test-bucket-${Math.ceil(Math.random() * 10 ** 10)}`, Key: `test-object-${Math.ceil(Math.random() * 10 ** 10)}`, Body: "BODY" }; export const run = async () => { // Create an S3 bucket. try { console.log(`Creating bucket ${bucketParams.Bucket}`); const data = await s3Client.send( new CreateBucketCommand({ Bucket: bucketParams.Bucket }) ); return data; // For unit tests. console.log(`Waiting for "${bucketParams.Bucket}" bucket creation...\n`); } catch (err) { console.log("Error creating bucket", err); } // Put the object in the S3 bucket. try { console.log(`Putting object "${bucketParams.Key}" in bucket`); const data = await s3Client.send( new PutObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key, Body: bucketParams.Body, }) ); return data; // For unit tests. } catch (err) { console.log("Error putting object", err); } // Create a presigned URL. try { // Create the command. const command = new GetObjectCommand(bucketParams); // Create the presigned URL. const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600, }); console.log( `\nGetting "${bucketParams.Key}" using signedUrl with body "${bucketParams.Body}" in v3` ); console.log(signedUrl); const response = await fetch(signedUrl); console.log( `\nResponse returned by signed URL: ${await response.text()}\n` ); } catch (err) { console.log("Error creating presigned URL", err); } // Delete the object. try { console.log(`\nDeleting object "${bucketParams.Key}"} from bucket`); const data = await s3Client.send( new DeleteObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key }) ); return data; // For unit tests. } catch (err) { console.log("Error deleting object", err); } // Delete the S3 bucket. try { console.log(`\nDeleting bucket ${bucketParams.Bucket}`); const data = await s3Client.send( new DeleteBucketCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key }) ); return data; // For unit tests. } catch (err) { console.log("Error deleting object", err); } }; run();
Python
SDK for Python (Boto3)
ヒント

この例を設定および実行する方法については、「GitHub」を参照してください。

Amazon S3 アクションを期間限定で実行できる署名付き URL を生成します。Requests パッケージを使用して、URL でリクエストを行います。

import argparse import logging import boto3 from botocore.exceptions import ClientError import requests logger = logging.getLogger(__name__) def generate_presigned_url(s3_client, client_method, method_parameters, expires_in): """ Generate a presigned Amazon S3 URL that can be used to perform an action. :param s3_client: A Boto3 Amazon S3 client. :param client_method: The name of the client method that the URL performs. :param method_parameters: The parameters of the specified client method. :param expires_in: The number of seconds the presigned URL is valid for. :return: The presigned URL. """ try: url = s3_client.generate_presigned_url( ClientMethod=client_method, Params=method_parameters, ExpiresIn=expires_in ) logger.info("Got presigned URL: %s", url) except ClientError: logger.exception( "Couldn't get a presigned URL for client method '%s'.", client_method) raise return url def usage_demo(): logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') print('-'*88) print("Welcome to the Amazon S3 presigned URL demo.") print('-'*88) parser = argparse.ArgumentParser() parser.add_argument('bucket', help="The name of the bucket.") parser.add_argument( 'key', help="For a GET operation, the key of the object in Amazon S3. For a " "PUT operation, the name of a file to upload.") parser.add_argument( 'action', choices=('get', 'put'), help="The action to perform.") args = parser.parse_args() s3_client = boto3.client('s3') client_action = 'get_object' if args.action == 'get' else 'put_object' url = generate_presigned_url( s3_client, client_action, {'Bucket': args.bucket, 'Key': args.key}, 1000) print("Using the Requests package to send a request to the URL.") response = None if args.action == 'get': response = requests.get(url) elif args.action == 'put': print("Putting data to the URL.") try: with open(args.key, 'r') as object_file: object_text = object_file.read() response = requests.put(url, data=object_text) except FileNotFoundError: print(f"Couldn't find {args.key}. For a PUT operation, the key must be the " f"name of a file that exists on your computer.") if response is not None: print("Got response:") print(f"Status: {response.status_code}") print(response.text) print('-'*88) if __name__ == '__main__': usage_demo()

署名付き POST リクエストを生成して、ファイルをアップロードします。

class BucketWrapper: def __init__(self, bucket): self.bucket = bucket self.name = bucket.name def generate_presigned_post(self, object_key, expires_in): """ Generate a presigned Amazon S3 POST request to upload a file. A presigned POST can be used for a limited time to let someone without an AWS account upload a file to a bucket. :param object_key: The object key to identify the uploaded object. :param expires_in: The number of seconds the presigned POST is valid. :return: A dictionary that contains the URL and form fields that contain required access data. """ try: response = self.bucket.meta.client.generate_presigned_post( Bucket=self.bucket.name, Key=object_key, ExpiresIn=expires_in) logger.info("Got presigned POST URL: %s", response['url']) except ClientError: logger.exception( "Couldn't get a presigned POST URL for bucket '%s' and object '%s'", self.bucket.name, object_key) raise return response
Ruby
SDK for Ruby
ヒント

この例を設定および実行する方法については、「GitHub」を参照してください。

require "aws-sdk-s3" require "net/http" # Creates a presigned URL that can be used to upload content to an object. # # @param bucket [Aws::S3::Bucket] An existing Amazon S3 bucket. # @param object_key [String] The key to give the uploaded object. # @return [URI, nil] The parsed URI if successful; otherwise nil. def get_presigned_url(bucket, object_key) url = bucket.object(object_key).presigned_url(:put) puts "Created presigned URL: #{url}." URI(url) rescue Aws::Errors::ServiceError => e puts "Couldn't create presigned URL for #{bucket.name}:#{object_key}. Here's why: #{e.message}" end def run_demo bucket_name = "doc-example-bucket" object_key = "my-file.txt" object_content = "This is the content of my-file.txt." bucket = Aws::S3::Bucket.new(bucket_name) presigned_url = get_presigned_url(bucket, object_key) return unless presigned_url response = Net::HTTP.start(presigned_url.host) do |http| http.send_request("PUT", presigned_url.request_uri, object_content, "content_type" => "") end case response when Net::HTTPSuccess puts "Content uploaded!" else puts response.value end end run_demo if $PROGRAM_NAME == __FILE__