Node.jsでCloudFront+S3の署名付きURLを発行する
吉川@広島です。4連休は自宅で過ごします。
案件においてCloudFrontで署名付きURLを発行したい、というシチュエーションは結構ありそうですが、実は自分はこの設定を経験したことがありません。
- CloudFront+S3で署名付きURLでプライベートコンテンツを配信する | DevelopersIO
- 【初心者向け】CloudFrontで署名付きURLを発行する【やってみた】 | DevelopersIO
いずれ来るであろう機会に備えて素振りしてみることにしました。
S3バケットを作成+サンプルファイルをアップロード
まずはバケットを作成します。
バケット名だけ決めて、後はデフォルト値で作成します。
バケットを作成したら、動作確認用の画像をアップロードします。今回は下記のサイトから150×150.pngというファイルをダウンロードして使用しています。
CloudFront Distributionを作成
CloudFrontのCreate Distributionから作成していきます。
Origin Domainで先程作成したS3バケットを選びましょう。
S3 bucket accessはYes use OAIを選択し、Create new OAIから新しいOAIを作成します。
任意の名前を入力します。
Bucket PolicyはYes, update...を選択します。
Viewer protcol policyをRedirect HTTP to HTTPSに設定します。
この設定でDistributionを作成します。完了まで少し待ちましょう。
作成が完了したら、一旦動作確認してみます。
// CloudFront https://{SUB_DOMAIN}.cloudfront.net/150x150.png
CloudFront URLにアクセスするとアップロードした画像ファイルが表示されました。
// S3 https://{BUCKET_NAME}.s3.ap-northeast-1.amazonaws.com/150x150.png
S3のURLから見ようとすると下記のようにエラーになるのが期待値です。
CloudFront用のPublicKey PrivateKeyを作成
CloudFront用のキー作成にあたって採る方法ですが、
今後は信頼されたキーグループを推奨
ということでこちらの方法を採用していきます。
手元の端末(自分はMacです)で下記のコマンドを実行します。
openssl genrsa -out private_key.pem 2048 openssl rsa -pubout -in private_key.pem -out public_key.pem
すると下記の2つのキーが作成されます。
- private_key.pem
- public_key.pem
こちらのPublicKeyの方をAWSにアップロードします。
CloudFrontの左メニューから、Public keysを選択します。そしてCreate Public Keyから作成していきます。
- Name: 任意
- Key: 先程作成したPublicKeyの内容をペースト
で作成しましょう。
続いてまた左メニューを確認し、Key groupsを選択します。そしてCreate key groupから作成します。
Public keysは上で作成したpublic keyを紐付けます。
CloudFront Behaviorを編集
ここからは今作成したpublic keyとDistributionを紐付けていきます。
作成済のCloudFront Distributionを編集します。Distributionを選択し、さらにBehaviorを選択します。この状態でEditを押下します。
Restrict viewer accessをYesにして、Trusted key groupsを選択します。そして、先程作成したkey groupを追加します。
以上でWebコンソールの設定は完了です。
Node.jsで署名付きURLを発行する
aws-sdk v3を使う方法 (現状厳しい)
現時点のaws-sdk v3では、v2のAWS.CloudFront.Signerクラスに相当する機能が用意されていないようです。
Create CloudFront signed URL · Issue #1822 · aws/aws-sdk-js-v3
そのため、sdk v3で実現するのは厳しいと感じました。
aws-sdk v2を使う方法
sdk v2はSignerクラスがあるので実装可能です。
サンプルコードはこちらの記事が参考になりそうでした。
Node.jsでAmazon CloudFrontの署名付きURLを生成する - Qiita
aws-cloudfront-signを使う方法 (一番手軽)
最後にaws-cloudfront-signというパッケージを使う方法です。
Creating Amazon CloudFront Signed URLs in Node.js | AWS Developer Tools Blog
jasonsims/aws-cloudfront-sign: Utility module for AWS CloudFront
紹介した方法の中で一番記述量が少なく手軽だったため、今回はこちらを採用しました。
ただ注意点として、TypeScriptの型定義がないため、anyを許容するか、自分で型定義を書くしかなさそうです。
環境
- Node.js 15.11.0
- typescript 4.3.5
- aws-cloudfront-sign 2.2.0
コード
// main.ts // @ts-ignore import { getSignedUrl } from 'aws-cloudfront-sign' const main = async () => { const signedUrl = getSignedUrl( 'https://{SUB_DOMAIN}.cloudfront.net/150x150.png', { keypairId: '{PUBLIC_KEY_ID}', privateKeyPath: '/path/to/private_key.pem', } ) as string console.log(signedUrl) } main()
keyPairId
はpublic keysのIDを入力しましょう。画面でいうと下記になります。
以下の出力が得られればOKです。
https://{SUB_DOMAIN}.cloudfront.net/150x150.png?Expires=1627019755&Policy=... ✨ Done in 0.78s.
実際アクセスして画像が表示されることも確認できました。
参考
- CloudFront+S3で署名付きURLでプライベートコンテンツを配信する | DevelopersIO
- 【初心者向け】CloudFrontで署名付きURLを発行する【やってみた】 | DevelopersIO
- [アップデート] root ユーザー作業が不要に!Amazon CloudFront で署名付き URL/Cookie 向け公開鍵を IAM ユーザー権限で管理できるようになりました。 | DevelopersIO
- Node.jsでAmazon CloudFrontの署名付きURLを生成する - Qiita
- Create CloudFront signed URL · Issue #1822 · aws/aws-sdk-js-v3
- Creating Amazon CloudFront Signed URLs in Node.js | AWS Developer Tools Blog