【Javascript】CloudFront 署名付きURLを生成

目次

Javascriptを使った、CloudFront署名付きURLの生成方法です。

前提

本件は、S3の前にCloudFrontを配置し、署名付きURLを介してS3オブジェクトをブラウザで表示してみるという構成を想定してコードを書きました。

また、CloudFrontディストリビューションがデプロイ済みであり、キーペア作成済み、パブリックキーがCloudFront側にアップロード済みであることが前提です。

以下の記事で触れてますのでよければどうぞ。

【Python】CloudFront 署名付きURLを生成

Javascript サンプルコード

共通部分

const fs = require('fs');

const cloudfrontDistributionDomain = "https://xxxxxx.cloudfront.net";
const s3ObjectKey = "icon.png";
const keyPairId = "パブリックキーID"; // キーグループのIDではない

var sigened_url;

/** 
 * プライベートキーを読み出す
 *
 * `options={encoding: "utf8"}` とすると、プレーンテキストで読み出せる
 */
function _read_private_key_contents(options = {}) {
  return fs.readFileSync("cloudfront_private_key.pem", options);
}

/**
 * 有効期限を生成する
 *
 * @param {number?} n 有効期間(単位 分)
 * @param {string?} format returnする型. stringの場合 `YYYY-MM-DD HH:ii:ss`、それ以外は timestamp(ms)
 */
function _get_after_n_minutes_datestring(n = 10, format = "string") {
  const afterNmin = (n * 60 + 1) * 1000; // 1秒未満切り上げのため +1 sec 、単位ms

  let dt = new Date();
  dt.setMilliseconds(dt.getMilliseconds() + afterNmin);

  if (format !== "string") {
    return dt.getMilliseconds();
  }

  // "YYYY-MM-DD HH:ii:ss" で出力する
  const year = String(dt.getFullYear());
  const month = String(dt.getMonth() + 1).padStart(2, '0');
  const date = String(dt.getDate()).padStart(2, '0');
  const hour = String(dt.getHours()).padStart(2, '0');
  const min = String(dt.getMinutes()).padStart(2, '0');

  return `${year}-${month}-${date} ${hour}:${min}:00`;
}

AWS SDK v3 の場合

追加のライブラリをインストールします。

npm install @aws-sdk/cloudfront-signer

サンプルコードです。

/** およそ10分間有効な署名付きURLを生成する v3 */
function generate_signed_url_v3(domain) {
  const {getSignedUrl} = require("@aws-sdk/cloudfront-signer");

  const url = `${domain}/${s3ObjectKey}`;
  const privateKey = _read_private_key_contents();
  const expire = _get_after_n_minutes_datestring();

  return getSignedUrl({
    url,
    keyPairId,
    dateLessThan: expire,
    privateKey,
  });
}

function sdkV3() {
  sigened_url = generate_signed_url_v3(cloudfrontDistributionDomain);
  console.log(sigened_url);

  // 代替ドメインを使用する場合
  const d2 = 'ここに代替ドメイン';
  sigened_url = generate_signed_url_v3(d2);
  console.log(sigened_url);
}

sdkV3();

AWS SDK v2 の場合

追加のライブラリをインストールします。

npm install aws-cloudfront-sign

サンプルコードです。

/** およそ10分間有効な署名付きURLを生成する v2 */
function generate_signed_url_v2(domain) {
  const cfsign = require('aws-cloudfront-sign');

  const url = `${domain}/${s3ObjectKey}`;
  const privateKey = _read_private_key_contents();
  const expire_ms = _get_after_n_minutes_datestring(format = "int") / 1000;
  const signingParams = {
    keypairId: keyPairId,
    privateKeyString: _read_private_key_contents(options = {encoding: "utf8"}),
    expireTime: expire_ms,
  };

  return cfsign.getSignedUrl(url, {
    keypairId: keyPairId,
    privateKeyString: _read_private_key_contents(options = {encoding: "utf8"}),
    expireTime: expire_ms,
  });
}

function awsCloudfrontSign() {
  sigened_url = generate_signed_url_v2(cloudfrontDistributionDomain);
  console.log(sigened_url);

  // 代替ドメインを使用する場合
  const d2 = 'https://代替ドメイン';
  sigened_url = generate_signed_url_v2(d2);
  console.log(sigened_url);
}

console.log("[S3/CloudFront] 署名付きURLを発行 V2");
awsCloudfrontSign();

参考ページ

v2で参考になった記事

Creating Amazon CloudFront Signed URLs in Node.js Class: AWS.CloudFront.Signer

v3で参考になった記事

AWS SDK for JavaScript v3 - @aws-sdk/cloudfront-signer Github - aws-sdk-js-v3