【CloudFront + S3】署名付きURLでのコンテンツアクセス

## はじめに

AWS認定のSA Proを学習していて、署名付きURLという機能を知りました。
CloudFrontの学習も兼ねて、今回は、署名付きURL実装方法について、具体的な手順を記述していきたいと思います。



## この記事でわかること

- 署名付きURLとはなんなのか、がわかります。

- 具体的な手順はなんなのか、がわかります。

  

## 目次

- [署名付きURLとは](#署名付きurlとは)
- [仕組み](#仕組み)
- [実際にやってみた](#実際にやってみた)
  - [1.EC2で、キーペアを作成](#1ec2でキーペアを作成)
  - [2.S3バケットの作成](#2s3バケットの作成)
  - [3.CloudFrontに、パブリックキーを登録](#3cloudfrontにパブリックキーを登録)
  - [4.CloudFrontに、キーグループを作成](#4cloudfrontにキーグループを作成)
  - [5.CloudFrontに、OAC(オリジンアクセスコントロール)を設定](#5cloudfrontにoacオリジンアクセスコントロールを設定)
  - [6.CloudFrontで、ディストリビューションを作成](#6cloudfrontでディストリビューションを作成)
  - [7.S3バケットポリシーを設定](#7s3バケットポリシーを設定)
  - [8.署名付きURLを検証](#8署名付きurlを検証)
- [参考にした記事](#参考にした記事)

## 署名付きURLとは

アクセス期限が設けられたURLのことです。
特定のユーザーに対して、一時的にコンテンツへのアクセス許可を与えたいケースで利用します。



## 仕組み

以下の構成図を使って、署名付きURLの仕組みを説明します。

![230207-ページ2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/ebc11b99-64db-5987-ab1a-99bc3c3c5667.png)


#### ① 署名付きURLを要求

クライアントPCが、署名付きURLを発行するEC2に対し、署名付きURLを要求します。

#### ② 秘密鍵によって署名された、署名付きURLを発行

EC2が、署名付きURLを発行し、署名付きURL要求元のクライアントPCに送付します。URLは、EC2が所有している秘密鍵によって署名されており、公開鍵認証が利用されています。

#### ③署名付きURLでアクセス

クライアントPCが、署名付きURLで静的コンテンツへアクセスします。上記構成図では、CloudFrontのエッジロケーションを利用したアクセスを例としています。CloudFrontは、事前に、EC2で所有している秘密鍵の対となる公開鍵を登録しています。

#### ④公開鍵で、署名付きURLの妥当性を検証

CloudFrontは、アクセスされた署名付きURLに対し、公開鍵で署名の妥当性を検証し、問題がなければ、オリジンとして設定しているS3へ、コンテンツリクエストを行います。

#### ⑤オリジン(S3)へ、コンテンツリクエスト

S3は、CloudFrontからコンテンツリクエストを受け取り、CloudFrontに対しコンテンツを返します。



## 実際にやってみた

さっそく、署名付きURLで、静的コンテンツへアクセスするまでをやってみます。
今回は、前項で紹介した以下構成と同様のもので試します。

![230207-ページ2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/8a28da5e-52e3-bacd-106d-6e15456dcf0d.png)


### 1.EC2で、キーペアを作成

まずは、秘密鍵を作成します。opensslコマンドで、pem形式のキーファイルを作成します。

````
user1@websrv02:~$ openssl genrsa -out urltest.private.pem 2048
````

次に、公開鍵を作成します。

```
user1@websrv02:~$ openssl rsa -pubout -in urltest.private.pem -out urltest.pub.pem
```

秘密鍵と公開鍵が作成されたことを確認します。(※キーファイルのパスは、途中で変更しました。)

```
user1@websrv02:~/urltest_230225$ ll url*
-rw------- 1 user1 user1 1704 Feb 25 14:36 urltest.private.pem
-rw-rw-r-- 1 user1 user1  451 Feb 25 14:37 urltest.pub.pem
```

### 2.S3バケットの作成

以下の設定でS3バケット「urltest-230225」を作成します。
今回の手順では、ブロックパブリックアクセスは設定しません。※ブロックパブリックアクセスを設定しても、署名付きURLでのアクセスのみ受け付けることは可能です。

![urltest-230225_-_S3_bucket-7853972.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/dd65a2f9-78e7-0357-61e2-f71db9c1e742.png)


バケットには、以下の画像をアップロードしておきます。この画像が、最終的に、署名付きURLでブラウザに表示される画像です。

![undou_taiiku_dengurigaeshi_boy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/cb1e512a-8360-cea8-ba4d-dbb6704ed0cc.png)


### 3.CloudFrontに、パブリックキーを登録

CloudFrontのサービス画面の左ペインにある、パブリックキー押下し、項番１にて、EC2で作成した公開鍵（`urltest.pub.pem`）を登録します。以下の作成ウィザードにて、`urltest.pub.pem`の内容を登録します。
![CloudFront-7335938.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/eb6d8a18-00ba-334f-19d4-40d010cd6d0f.png)


### 4.CloudFrontに、キーグループを作成

キーグループを作成します。キーグループには、項番3で登録したパブリックキーを登録します。
![CloudFront-7336045.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/d7cbb38d-38a3-59ea-9640-8a30ce53271a.png)




### 5.CloudFrontに、OAC(オリジンアクセスコントロール)を設定

OACを設定します。以下の作成画面にて、赤枠の部分の設定を変更します。
※OACを作成してるのに、従来機能のOAIを混入させてしまいました。ご了承ください。

![CloudFront-7751068.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/1e92bc8e-4b0e-c9b0-084a-e7c20029d6e9.png)


__■ OACとは__

オリジンS3に設定した時、S3へのリクエストをCloudFrontに限定する(CloudFrontを経由しないリクエストは受け付けない)ための機能のことです。
従来まで、OAI(オリジンアクセスアイデンティティ)という機能で提供されていましたが、S3へのアップロードにおける柔軟性と、セキュリティ面での強化されて、2022/5にアップデートされたものとなります。
OAIと比べると・・・

- SSE-KMS で暗号化されている、 S3 オブジェクトの、ダウンロードとアップロードをサポートしている。
- `署名リクエスト `オプションを利用することで、CloudFrontとS3間で、クライアントからのリクエストごとに認証処理を施し、よりセキュアな通信を実現している。
  ※OACの署名リクエストに関しては、後日別の記事で解説しようと思います。

などといった機能が実装されています。



### 6.CloudFrontで、ディストリビューションを作成

ディストリビューションを作成します。ディストリビューションとは、CloudFrontにおける、コンテンツの供給元です。
以下の赤枠部分を設定します。
**S3バケットアクセス**には`Origin access control settings(recommended)`を選択し、前項の手順で作成したOACを設定します。

![CloudFront-7751249.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/0932a5c7-6e78-102d-f5f5-d05fe937208a.png)




オリジンシールドを設定します。

![CloudFront-7751497.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/7c2cd428-f0f0-381d-30f9-23dd7017002e.png)

__■オリジンシールドとは__

オリジンとなるS3の前段に、コンテンツをキャッシュするコンポーネントを配置す機能です。オリジンシールドを有効化することで、キャッシュヒット率を向上させることができます。
オリジンシールドリージョンには、クライアントとロケーションが近いリージョンを選択することで、レイテンシーを低減させることができます。



**キーグループ**には、項番4で作成したキーグループを指定しています。

![CloudFront-7752847.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/07fa24b7-1f2a-008c-88ae-ef0453eb3ec1.png)




**カスタムSSL証明書**では、ACMで作成したSSL証明書を設定し、HTTPS通信でのアクセスを可能にしています。

![CloudFront-7752982-7886893.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/b36952a8-1607-bd0f-5c67-3e41012200ac.png)




### 7.S3バケットポリシーを設定

指定したCloudFrontのディストリビューションからのみ、S3でリクエストを受け付けるため、
以下のようにバケットポリシーを設定します。
![urltest-230225_-_S3_bucket-7753985.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/ce737601-c5d6-2dc7-e311-1f5e6e7e4a65.png)


OACで、SSE-KMSを有効化したい場合などは、記述内容が異なりますので、以下を参照ください。
https://aws.amazon.com/jp/blogs/news/amazon-cloudfront-introduces-origin-access-control-oac/



### 8.署名付きURLを検証

最後に、署名付きURLを検証してみます。
まず、AWSCLIを使って、署名付きURLを生成します。必要なコマンドはこちらです。

```
user1@websrv02:~$ aws cloudfront sign \
--url https://d3cXXXXXXXX.cloudfront.net/undou_taiiku_dengurigaeshi_boy.png\
--key-pair-id KXXXXXX \
--private-key file://./urltest.private.pem \
--date-less-than $((`date "+%s"` + 86400))
```

特に、`--key-pair-id`はCloudFrontのキーグループから、`--url`は、CloudFrontのディストリビューション画面から、ディストリビューションドメイン名を指定し、S3のパスを指定します。`--date-less-than`には、署名付きURLへのアクセス期限を指定します。指定した期限を過ぎると、該当のURLにアクセスできなくなります。



そして、こちらが、出力された署名付きURLをつかってアクセスした結果です。
![undou_taiiku_dengurigaeshi_boy_png__500×388_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/fe599aa0-0a1a-c7b6-e18b-35490f397e55.png)

問題なくアクセスできることが確認できます。



以下が、通常のURLでアクセスした結果です。

![https___d3crjw5xkciefh_cloudfront_net_undou_taiiku_dengurigaeshi_boy_png-7888191.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100138/cbfa7ed8-d857-8eeb-65bd-920245fcb9cf.png)


アクセスできないことが確認できました。



以上が、署名付きURLの実装方法でした。



## 参考にした記事


https://www.aws-room.com/entry/presigned-cloudfront


https://aws.amazon.com/jp/blogs/news/amazon-cloudfront-introduces-origin-access-control-oac/