Node.jsでAmazon CloudFrontの署名付きURLを生成する
Node.jsでAmazon CloudFrontの署名付きURLを生成する:
環境整備が面倒くさかったので手順を整理しておきます。
この記事では 署名付きURL の作成方法について取り上げます。Webアプリケーションの構築については範囲外です
画像ファイルを格納するS3のバケットを作成します。
今回は
テストのために
CloudFrontを迂回してアクセスできないように設定します。
Step 2: Create distribution の画面で以下の設定を行います。
コンソールの CloudFront Distributions にて status が
ゆっくりコーヒーを飲む時間くらいはかかるので、余裕を見て作業しましょう。
Route 53 で先程作成した CloudFront Distribution へのaliasを作成します。
まず、CloudFrontのコンソールで Domain Name をコピーしておきます。
つづいて、Route53で Aレコード を追加します。
ふたたび CloudFrontのコンソールに戻り、Alternate Domain Names (CNAMEs) を更新します。
リストから作成したDistributionを選択し、
Alternate Domain Names (CNAMEs) にRoute53で登録したAレコードのNameを入力します。
また
SSL Certificate で
AWS Certificate Manager で証明書を作成し登録します。
AWS Certificate Managerが開きます。このときリージョンが バージニア北部 となっていることを確認してください。(そうでなければ変更する)
ドメイン名は
今回、ドメインの管理もRoute53で行っているのでCNAMEの登録による確認で証明書が発行されます。
ここでも検証が完了するまで少し時間がかかりますが、状況 が 発行済み になるまで何度かリロードしてください。
(私の環境では、以降のCloudFrontのコンソールでなかなか証明書が一覧に表示されず、しばらく悩みました。
経験上、AWSコンソールでの作業はひとつづつ確実にこなすのが良いです。)
CloudFrontのコンソールに戻り、SSL Certificate で
(私の環境では一旦Editをキャンセルし、ブラウザのリロードを行い、再度Edit画面に戻ると選択可能になっていました。)
Custom SSL Certificate (example.com): のテキストボックスにフォーカスを合わせると、AWS Certificate Managerで発行した証明書が表示されますので、選択してください。
署名付きURLを生成するための公開鍵、秘密鍵、アクセスキーIDを取得します。
AWSコンソールのヘッダー右上、ユーザー名の部分をクリックして セキュリティ認証情報 を選択します。
ダイアログが表示される場合は
CloudFrontのキーペア にて
また、CloudFrontのキーペア に
やっと本題。
今回は署名付きURLを生成する機能だけを実装します。
適当にNode.jsのプロジェクトフォルダを作成し、AWS-SDKとその他のパッケージをインストールします。
(その他のパッケージは署名付きURLの生成に直接関与するものではありません。AWS-SDKだけが必須です。)
以下のように、コンソールに生成したURLを出力するコードを作成します。
秘密鍵の保存場所とアクセスキーIDを
実行すると以下のような結果が返ります。
返されたURLにブラウザからアクセスし、画像が表示されることを確認してください。
また、QueryString部分をカットして
やりたいこと
- 認証が必要なWebアプリケーションをAWS上に構築する
-
Amazon S3で画像ファイルを管理する - 画像ファイルには認証済みユーザーのみがアクセス可能
- 独自URLで公開する
- 当然SSL化する
-
環境整備が面倒くさかったので手順を整理しておきます。
この記事では 署名付きURL の作成方法について取り上げます。Webアプリケーションの構築については範囲外です
手順
リソース管理用のS3バケットを準備する
画像ファイルを格納するS3のバケットを作成します。今回は
cloudfront-private-content
という名前にしました。テストのために
cat.jpg
と dog.jpg
をバケットにアップロードします。
CloudFrontでS3バケットを公開設定する
CloudFrontを迂回してアクセスできないように設定します。Step 2: Create distribution の画面で以下の設定を行います。
Origin Settings
項目 | 設定値 |
---|---|
Origin Domain Name | 作成したS3バケットを指定 |
Restrict Bucket Access | Yes |
Origin Access Identity | Create a New Identity |
Grant Read Permissions on Bucket | Yes, Update Bucket Policy |
Default Cache Behavior Settings
項目 | 設定値 |
---|---|
Viewer Protocol Policy | Redirect HTTP to HTTPS |
In Progress
から Deployed
に変わるまで結構時間がかかります。ゆっくりコーヒーを飲む時間くらいはかかるので、余裕を見て作業しましょう。
CloudFrontへ独自ドメインでアクセスする
Route 53 で先程作成した CloudFront Distribution へのaliasを作成します。まず、CloudFrontのコンソールで Domain Name をコピーしておきます。
xxxxxxxxxxxxx.cloudfront.net
つづいて、Route53で Aレコード を追加します。
項目 | 設定値 |
---|---|
Name | private-content .example.com |
Type | A - IPv4 address |
Alias | Yes |
Alias Target | xxxxxxxxxxxxx.cloudfront.net |
リストから作成したDistributionを選択し、
Distribution Settings
ボタンをクリックします。General
タブのEdit
ボタンをクリックします。Alternate Domain Names (CNAMEs) にRoute53で登録したAレコードのNameを入力します。
Yes, Edit
ボタンをクリックし、変更を保存します。
独自ドメインをSSL化する
また Distribution Settings
> General
> Edit
ボタンをクリックします。SSL Certificate で
Custom SSL Certificate (example.com):
を選択したいところですが、まだアクティブになっていないと思います。(選択可能な証明書があればアクティブになる)AWS Certificate Manager で証明書を作成し登録します。
Request or Import a Certificate with ACM
ボタンをクリックします。AWS Certificate Managerが開きます。このときリージョンが バージニア北部 となっていることを確認してください。(そうでなければ変更する)
ドメイン名は
*.example.com
として続行します。今回、ドメインの管理もRoute53で行っているのでCNAMEの登録による確認で証明書が発行されます。
ここでも検証が完了するまで少し時間がかかりますが、状況 が 発行済み になるまで何度かリロードしてください。
(私の環境では、以降のCloudFrontのコンソールでなかなか証明書が一覧に表示されず、しばらく悩みました。
経験上、AWSコンソールでの作業はひとつづつ確実にこなすのが良いです。)
CloudFrontのコンソールに戻り、SSL Certificate で
Custom SSL Certificate (example.com):
が選択可能であればチェックしてください。(私の環境では一旦Editをキャンセルし、ブラウザのリロードを行い、再度Edit画面に戻ると選択可能になっていました。)
Custom SSL Certificate (example.com): のテキストボックスにフォーカスを合わせると、AWS Certificate Managerで発行した証明書が表示されますので、選択してください。
Yes, Edit
ボタンをクリックし、変更を保存します。
キーペアの作成
署名付きURLを生成するための公開鍵、秘密鍵、アクセスキーIDを取得します。AWSコンソールのヘッダー右上、ユーザー名の部分をクリックして セキュリティ認証情報 を選択します。
ダイアログが表示される場合は
Continue to Security Credentials
ボタンをクリックして続行します。CloudFrontのキーペア にて
新しいキーペアの作成
をクリックし、公開鍵と秘密鍵をダウンロードします。 また、CloudFrontのキーペア に
アクセスキーID
が表示されるので、これもコピーしておきます。
Node.jsでAmazon CloudFrontの署名付きURLを生成する
やっと本題。今回は署名付きURLを生成する機能だけを実装します。
適当にNode.jsのプロジェクトフォルダを作成し、AWS-SDKとその他のパッケージをインストールします。
(その他のパッケージは署名付きURLの生成に直接関与するものではありません。AWS-SDKだけが必須です。)
$ mkdir cloudfront-secret-content $ cd cloudfront-secret-content $ npm init -y $ npm install --save aws-sdk dotenv fs-extra moment
index.js
require('dotenv').config(); const AWS = require('aws-sdk'); const fs = require('fs-extra'); const moment = require('moment'); // 対象となるリソースのURL const target = 'https://private-content.example.com/cat.jpg'; /** * AWS.CloudFront.Signer.getSignedUrlを呼び出す。 * * Class: AWS.CloudFront.Signer — AWS SDK for JavaScript * https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CloudFront/Signer.html * @param {String} keypairId * @param {String} privateKey * @param {Object} options */ function getSignedUrlAsync(keypairId, privateKey, options) { return new Promise((resolve, reject) => { // Signerインスタンスを生成 const signer = new AWS.CloudFront.Signer(keypairId, privateKey); // URL生成 signer.getSignedUrl(options, (err, url) => { if (err) { reject(err); } resolve(url); }); }); } async function main() { // private keyを読み込む const privateKey = await fs.readFile(process.env.PRIVATE_KEY_FILE, { encoding: 'utf-8' }); // 期限を設定 // 現在日時から1日後まで有効とする const expires = moment.utc().add(1, 'days').unix(); // URL生成 const url = await getSignedUrlAsync( // キーペアのID // AWSコンソールの以下の場所で確認可能 // セキュリティ認証情報 > CloudFront のキーペア > アクセスキーID process.env.KEYPAIR_ID, // 秘密鍵を渡す privateKey, { // 対象となるCloudFrontのURL url: target, // 生成されるURLの期限 (UTCのunixtime) expires } ); console.log(url); } main().then(() => { console.log('done.'); }).catch((err) => { console.error(err); });
.env
ファイルに記述します。.env
KEYPAIR_ID=xxxxxxxxxxxxxxxxxxxx PRIVATE_KEY_FILE=./secret/pk-xxxxxxxxxxxxxxxxxxxx.pem
$ node index.js https://private-content.example.com/cat.jpg?Expires=1540535260&Key-Pair-Id=XXXXXXXXXXXXXXXXXXXX&Signature=..... done.
また、QueryString部分をカットして
403
が返されること、cat.jpg
をdog.jpg
に変更してもアクセスできないことを確認します。
コメント
コメントを投稿