

# S3 on Outposts バケットにオブジェクトをアップロードするための署名付き URL の生成
<a name="S3OutpostsPresignedUrlUploadObject"></a>

バケットポリシーを更新せずに、Outpost にローカルに保存されているオブジェクトへの時間制限付きのアクセス許可を付与するには、事前署名付きの URL を使用します。署名付き URL を使用すると、バケット所有者は仮想プライベートクラウド (VPC) 内の個人とオブジェクトを共有したり、オブジェクトをアップロードまたは削除する権限を、これらのユーザーに付与したりできます。

AWS SDK または AWS Command Line Interface(AWS CLI) を使用して署名付き URL を作成する際には、その URL に対し特定のアクションを関連付けます。また、1 秒から 7 日まで指定可能なカスタム有効期限を選択して、署名付き URL に対し期間制限付きのアクセス許可を付与できます。署名付き URL を共有すると、VPC 内のユーザーは署名元のユーザーと同じように、URL に埋め込まれたアクションを実行できるようになります。この URL は有効期限が切れると失効し、以後は機能しなくなります。

署名付き URL を作成する場合には、ご自身のセキュリティ認証情報を設定し、さらに次の情報を指定する必要があります。
+ Outposts バケット上の Amazon S3 アクセスポイントの Amazon リソースネーム (ARN)
+ オブジェクトキー
+ HTTP メソッド (オブジェクトをアップロードするための `PUT`)
+ 有効期限の終了日時

署名付き URL は、指定した期間内でのみ有効です。つまり、有効期限が切れる日時の前に、URL で許可されているアクションを開始する必要があります。有効期限が切れる日時までは、署名付き URL を複数回使用できます。一時トークンを使用して署名付き URL を作成した場合、トークンが有効期限切れになると、URL の有効期限より前であってもその URL は失効します。

マルチパートアップロードなど、複数のステップで構成されているアクションでは、すべてのステップを有効期限が切れる前に開始する必要があります。有効期限が切れた URL を使用して、S3 on Outposts がステップの開始を試みた場合は、エラーが発生します。

署名付き URL へのアクセス権を持つ仮想プライベートクラウド (VPC) 内のユーザーは、オブジェクトをアップロードすることが可能です。例えば、署名付き URL にアクセスできる VPC 内のユーザーは、お客様のバケットへのオブジェクトのアップロードが可能です。署名付き URL は、その URL を保有するすべてのユーザーに対し、S3 on Outposts バケットへのアクセスを許可するため、これらの URL には適切な保護を行うことをお勧めします。署名付き URL の保護の詳細については、[署名付き URL 機能の制限](S3OutpostsPresignedURL.md#S3OutpostsPresignedUrlUploadObjectLimitCapabilities) を参照してください。

有効なセキュリティ認証情報を持つすべてのユーザーが、署名付き URL を作成できます。ただし、署名付き URL の基となるオペレーションを実行するアクセス許可を持つユーザーが、その署名付き URL を作成する必要があります。詳細については、「[署名付き URL を作成できるユーザー](S3OutpostsPresignedURL.md#S3Outpostswho-presigned-url)」を参照してください。

## AWS SDK を使用した S3 on Outposts オブジェクトオペレーションへの署名付き URL の生成
<a name="s3-outposts-presigned-urls-upload-examples"></a>

------
#### [ Java ]

**SDK for Java 2.x**  
この例では、限られた時間内に S3 on Outposts バケットにオブジェクトをアップロードするために使用できる、署名付き URL を生成する方法を説明します。詳細については、「[S3 on Outposts での署名付き URL の使用](S3OutpostsPresignedURL.md)」を参照してください。  

```
    public static void signBucket(S3Presigner presigner, String outpostAccessPointArn, String keyName) {

        try {
            PutObjectRequest objectRequest = PutObjectRequest.builder()
                    .bucket(accessPointArn)
                    .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 must be used when uploading a file: " +
                    presignedRequest.httpRequest().method());

            // Upload content to the S3 on Outposts 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 e) {
            e.getStackTrace();
        } catch (IOException e) {
            e.getStackTrace();
        }
    }
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
S3 on Outposts アクションを期間限定で実行できる署名付き URL の生成方法を示します。詳細については、「[S3 on Outposts での署名付き URL の使用](S3OutpostsPresignedURL.md)」を参照してください。この URL でリクエストを行うには、`Requests` パッケージを使用します。  

```
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 S3 on Outposts 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 that 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 on Outposts presigned URL demo.")
    print('-'*88)

    parser = argparse.ArgumentParser()
    parser.add_argument('accessPointArn', help="The name of the S3 on Outposts access point ARN.")
    parser.add_argument(
        'key', help="For a GET operation, the key of the object in S3 on Outposts. 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.accessPointArn, '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()
```

------