Node.js
AWS
S3
aws-cli
CloudFront

{AWS(CloudFront+S3)+Node.js} 署名付きURLを使用したプライベートコンテンツの配信

はじめに

短期間のみ有効な署名付き URL を使用してプライベートコンテンツを配信するにあたり、Node.js環境下での情報が公式にはのっていなかったので、その対応方法をメモとして残します。

公式ガイド
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html

環境準備

  1. プライベートコンテンツを格納するS3のバケットを作成する
  2. 上記バケットを非公開とする
  3. CloudFrontのディストリビューションを作成する
    • CloudFront経由に限り上記S3バケットにアクセス出来る用に設定する
  4. 署名付きURL生成のためにCloudFront のキーペアを作成する
    • この処理だけはAWSアカウント(ルートアカウント)が必要

〇参考URL
https://dev.classmethod.jp/cloud/aws/cf-s3-deliveries-use-signurl/
http://blog.mekachan.net/?p=105

コード実装

現在JavaScriptのaws-sdkライブラリではCloudfrontの署名付きURL生成がサポートされていないため、「aws-cloudfront-sign」ライブラリを活用して対応する

aws-cloudfront-sign

https://www.npmjs.com/package/aws-cloudfront-sign

サンプルコード

// 30分だけ有効な署名付きURLを生成するコード
var cf = require('aws-cloudfront-sign')
var options = {
  keypairId: 'XXXXXX',
  privateKeyPath: 'XXXX/XXXXXX-private-pk-XXXXX.pem',
  expireTime: (new Date().getTime() + 30 * 60 * 1000)
}
// CloudFrontの「Domain Name」を指定する
// https://${Domain Name}/${Origin path(S3バケット内のパス)}
var signedUrl = cf.getSignedUrl('https://dXXX.cloudfront.net/example.mp4', options);
console.log('Signed URL: ' + signedUrl);

options(オプション)の説明

項目 内容
expireTime 有効期限(任意設定:省略時は30秒)指定する際はミリ秒で指定する
keypairId 作成したクラウドフロントキーペアのアクセスキー ID
privateKeyString
または
privateKeyPath
作成したクラウドフロントキーペアの秘密鍵ファイルパス

参考 S3上で署名付きURLを利用するの場合

このケースではクラウドフロントを介しません。
S3上で生成した署名付きURL経由で非公開バケット中のリソースへアクセスする方式です。
特別なライブラリは不要でaws-sdkで対応可能です。

const AWS = require('aws-sdk')

AWS.config.update({
  accessKeyId: 'XXXXXX',
  secretAccessKey: 'XXXXXX'
  // ,
  // region: 'ap-northeast-1'
})
const s3 = new AWS.S3()

const url = s3.getSignedUrl('getObject', {
    Bucket: 'private-bucket',
    Key: 'example.mp4',
    Expires: 60 // 単位は秒
})

console.log(url)

参考(AWS-CLI)の場合

aws cloudfront sign
 --url http://dXXX.cloudfront.net/example.mp4
 --key-pair-id XXXXXX
 --private-key file://C:/XXX-private-pk-XXXXX.pem
 --date-less-than YYYY-mm-dd