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 に変更してもアクセスできないことを確認します。
コメント
コメントを投稿