CloudFrontの署名付きURLでS3にアクセスする方法

# 概要

![スクリーンショット 2020-02-10 16 02 45](https://user-images.githubusercontent.com/17561411/74127747-d38a2f80-4c1e-11ea-8cc2-1ae3f1bdd0c1.png)

今回はCloudFrontの署名付きURLでS3にアクセスする方法に関する内容を書いてみました。


手順は下記のようになります。
・S3作成
・CloudFront作成
・CloudFrontの署名付きURL発行
・CloudFrontの署名付きURLでS3にアクセス


## S3作成

![スクリーンショット 2020-02-10 16 10 25](https://user-images.githubusercontent.com/17561411/74128363-5cee3180-4c20-11ea-99a9-935a66fb13cc.png)

BucketNameを入れて、② > ③(Block all public access全部チェック) > ④を進んでS3を作成してください。　

その後、簡単なindex.htmlファイルをS3にアップロードしてください。

## CloudFront作成


![スクリーンショット 2020-02-10 16 18 47](https://user-images.githubusercontent.com/17561411/74128766-44cae200-4c21-11ea-908c-5fdb0070bfde.png)

CloudFrontに移動して「Create Distribution」をクリックします。



![スクリーンショット 2020-02-10 16 18 08](https://user-images.githubusercontent.com/17561411/74128807-688e2800-4c21-11ea-9465-0a7f075f2890.png)

Delivery Methodは**Web**を選択します。
RTMPは Streaming serviceです。

![スクリーンショット 2020-02-10 16 24 25](https://user-images.githubusercontent.com/17561411/74129003-e0f4e900-4c21-11ea-88b5-f5fea77c13bc.png)

- **Origin Domain Name:** S3のリストの中で、最初作成したS3を選択します。
- **Origin Path:**S3 SubBucketFolderですが、今回作成していないので、空欄でOKです。
- **Origin ID:**Origin Domain Name選択すると、勝手に表示されます。
- **Restrict Bucket Access:**S3にCloudFrontのみアクセス可能にする設定なので、「Yes」を選択します。
- **Origin Access Identity:**初めて作成する場合、「Create a New Identity」を選択します。
- **Grant Read Permissions on Bucket:**Block all public accessしているので、CloudFrontからS3にアクセスするために権限を与えます。

![スクリーンショット 2020-02-10 16 37 44](https://user-images.githubusercontent.com/17561411/74129761-b86dee80-4c23-11ea-99e4-14b116c5f391.png)

- **Viewer Protocol Policy:**今回は証明書なしに行うので、「Http and Https」を選択します。
- **Restrict Viewer Access:**署名付きURLのみアクセスを許可するために、「Yes」を選択します。

そして、「Create Distribution」をクリックしてCloudFrontを作成してください。
おそらく、StatusがDeployedまで15分くらいかかると思います。。

Deployedが表示されたら、S3 Policy確認と、Domain Nameでアクセスしましょう。
まず、S3 Policyは**Grant Read Permissions on Bucket**によって更新されていると思います。
![スクリーンショット 2020-02-10 17 24 03](https://user-images.githubusercontent.com/17561411/74303806-62718600-4d9e-11ea-8eed-1112a3cf8429.png)


そして、Domain Nameでアクセスすると、
![スクリーンショット 2020-02-10 16 46 59](https://user-images.githubusercontent.com/17561411/74130311-1ea74100-4c25-11ea-9e32-c084c8a4acc4.png)
MissingKeyだと言われます。先ほど**Restrict Viewer Access**を「Yes」にしたので、
別途に署名付きURLを発行しないと、アクセスできません。

では、CloudFrontの署名付きURLを発行しましょう。

ちなみに、index.htmlのように、特定のObjectではないURLをRequestする場合、下記の設定を行ってください。
Distribution Settings > Edit > Default Root Objectにindex.htmlを入力 > Yes, Editをクリックして、15分待ち。。

## CloudFrontの署名付きURL発行

![スクリーンショット 2020-02-10 17 00 54](https://user-images.githubusercontent.com/17561411/74131126-00424500-4c27-11ea-9f9d-01523febdc21.png)

**Root User**で 「My Security Credentials」に移動します。

![スクリーンショット 2020-02-10 17 03 21](https://user-images.githubusercontent.com/17561411/74131270-53b49300-4c27-11ea-88ca-b4add3661f42.png)

CloudFront key pairs > 「Create New Key Pair」をクリックして、PrivateキーとPublicキーをダウンロードしてください。

## CloudFrontの署名付きURLでS3にアクセス

これで、S3にアクセスする準備ができたと思います。
筆者はLaravelでCloudFrontの署名付きURLを発行してみます。

```php

AWS_ACCESS_KEY_ID= // AWS Access Key
AWS_SECRET_ACCESS_KEY= // AWS Secret Access Key
AWS_DEFAULT_REGION= // AWS region
AWS_BUCKET= // S3 bucket name
CLOUDFRONT_DOMAIN_NAME= //cloudfront Domain Name
RESOURCE_KEY=index.html
CLOUDFRONT_EXPIRES=60 //1分
CLOUDFRONT_PRIVATE_KEY= // Security Credentials private key path
CLOUDFRONT_KEY_PAIR_ID= // Security Credentials CloudFront key pairs Access Key ID
```

```php

       $sdk = new Sdk([
            'region'  => env('AWS_DEFAULT_REGION'),
            'version' => 'latest',
            'credentials' => [
                'key'    => env('AWS_ACCESS_KEY_ID'),
                'secret' => env('AWS_SECRET_ACCESS_KEY')
            ]
        ]);

        $client = $sdk->createCloudFront();
        $expires = time() + env('CLOUDFRONT_EXPIRES');

        $cloudFrontUrl = $client->getSignedUrl([
            'url'         => env('CLOUDFRONT_DOMAIN_NAME') . '/' . env('RESOURCE_KEY'),
            'expires'     => $expires,
            'private_key' => storage_path('app') . '/' . env('CLOUDFRONT_PRIVATE_KEY'),
            'key_pair_id' => env('CLOUDFRONT_KEY_PAIR_ID')
        ]);

        dump($cloudFrontUrl);
        exit;
```
![スクリーンショット 2020-02-10 17 14 38](https://user-images.githubusercontent.com/17561411/74131983-e99ced80-4c28-11ea-812a-79a61baeb7af.png)

発行したURLでアクセスすると、S3にアップロードしたindex.htmlが表示されます。

![スクリーンショット 2020-02-10 17 20 45](https://user-images.githubusercontent.com/17561411/74132384-ce7ead80-4c29-11ea-9af0-e02a4b8941a2.png)
そして、1分経ってアクセスすると、Access Deniedが表示され、アクセスできなくなります。

# 参考

[Authorization@Edge using cookies: Protect your Amazon CloudFront content from being downloaded by unauthenticated users](https://aws.amazon.com/ko/blogs/networking-and-content-delivery/authorizationedge-using-cookies-protect-your-amazon-cloudfront-content-from-being-downloaded-by-unauthenticated-users/)
[[CloudFront + S3]特定バケットに特定ディストリビューションのみからアクセスできるよう設定する](https://dev.classmethod.jp/cloud/aws/cloudfront-s3-origin-access-identity/)