🌤️
【AWS】Elastic Beanstalk環境のLaravelでCloudFrontの署名付きURLを発行する
English ver.
概要
CloudFrontの署名付きURL経由 で、S3のオブジェクトにアクセスさせる手順をまとめました。
- ローカルで動かしました!
- S3用の署名付きURL発行しました!
のような例はよく見かけたのですが、Elastic Beanstalk環境から、CloudFrontの署名付きURLの実装例があまり見当たらなかったのでメモ程度にまとめています。
間違い等ももしかしたらあるかもなので、こっそり指摘していただけると嬉しいです!
前提
- AWS Elastic Beanstalk環境
- PHP (8.0.6)
- Laravel (8.49.2)
手順
1. aws-sdk-php-laravel をインストール
composer require aws/aws-sdk-php-laravel
config/app.php
'providers' => [
...
+ Aws\Laravel\AwsServiceProvider::class,
]
'aliases' => [
...
+ 'AWS' => Aws\Laravel\AwsFacade::class,
]
2. キーペアを作成する
こちらの手順(Create a key pair for a trusted key group (recommended))に従って、キーペアを作成する。手順を以下に示す。
キーペア作成 (例: private_key.pem)
openssl genrsa -out private_key.pem 2048
Public Key作成 (例: public_key.pem)
openssl rsa -pubout -in private_key.pem -out public_key.pem
3. CloudFrontにPublic Keyを追加
- Name: 名称
- Description(任意): 説明
- Key: 以下の出力を貼り付ける
cat public_key.pem
4. Key GroupにPublic Keyを追加する
-
Name
- 名称 -
Description
- 説明(任意) -
Public Keys
- 先程追加したKeyを選択
5. ファイル格納用のS3のバケットを作成する
- 特に何も設定を変更せずに作成する
6. CloudFrontのDistributionを作成する
-
Origin Domain
- 5.で作成したバケットのドメインを選択 -
Restrict viewer access
- Yes -
Trusted authorization type
- Trusted key groups (recommended)- 先程のKey Groupを選択
- 作成したDistributionのOriginを編集
-
S3 bucket access
- Yes use OAI (bucket can restrict access to only CloudFront) -
Bucket policy
- Yes, update the bucket policy
こうすることでS3のバケットポリシーが上書きされます。
7. 署名付きURLを発行する記述を追加
※以下に出てくる$post->url
は、既にstoreAs()
等で保存した際のpathを使用しています。
.env
AWS_URL=https://xxxxxxxxxxx.cloudfront.net # ファイル格納用S3がOriginのDistributionのドメイン名
AWS_CLOUDFRONT_KEY_PAIR_ID=<CloudFrontに追加したPublic KeyのID>
PRIVATE_KEY_PATH=<Private Keyを配置するPATH> # 例では /etc/pki/tls/certs/配下
config/app.php
/*
|--------------------------------------------------------------------------
| Other variables
|--------------------------------------------------------------------------
|
| Define other variables here.
*/
'key_pair_id' => env('AWS_CLOUDFRONT_KEY_PAIR_ID', ''),
'private_key_path' => env('PRIVATE_KEY_PATH', ''),
$pathはあくまで例で、実際のコードとは若干異なります。S3に保存した際のpathをそのまま、署名付きURL発行に使用しています。
URLを発行する.php
use Aws\Laravel\AwsFacade as AWS;
// S3にファイルを保存(省略)
$path = $request->file('foo')->storeAs('some_path', 'fileName');
// 省略
$client = AWS::createClient('cloudfront');
$signedUrl = $client->getSignedUrl([
'url' => config('filesystems.disks.s3.url') . '/' . $path,
'expires' => time() + 30, // 30秒で期限切れ
'private_key' => realpath(config('app.private_key_path')),
'key_pair_id' => config('app.key_pair_id'),
]);
// 省略
8. Private KeyをS3にアップロードする
- 生成したprivate keyを
Elastic Beanstalk環境が生成した
S3のバケットにアップロードします。今回はバケット直下にひみつかぎ.pem(仮称)
をアップロードします。
例)elasticbeanstalk-ap-northeast-1-xxxxxxxxxxx
-
aws-elasticbeanstalk-ec2-role
で鍵ファイルを取得できるようにバケットポリシーを更新
(自前でec2のロールを付与している場合は、そのロールを指定してください )
バケットポリシー
{
"Version": "2008-10-17",
"Statement": [
...
{
"Sid": "xx-xxxxxxxxx-xxxx-xx-xxxx-xxxxxxx",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::xxxxxxxxxxxx:role/aws-elasticbeanstalk-ec2-role"
]
},
"Action": [
+ "s3:GetObject",
],
"Resource": [
+ "arn:aws:s3:::elasticbeanstalk-ap-northeast-1-xxxxxxxxxx/ひみつかぎ.pem",
]
}
]
.ebextensions
配下に設定ファイルを追加する
9. -
.ebextentions.privatekey.config
というファイルを作成
例
privatekey.config
Resources:
AWSEBAutoScalingGroup:
Metadata:
AWS::CloudFormation::Authentication:
S3Auth:
type: "s3"
buckets: ["elasticbeanstalk-ap-northeast-1-xxxxxxxxxxx"] # Beanstalkのバケット
roleName:
"Fn::GetOptionSetting":
Namespace: "aws:autoscaling:launchconfiguration"
OptionName: "IamInstanceProfile"
DefaultValue: "aws-elasticbeanstalk-ec2-role" # 他のRoleを紐付けている場合はそちらを指定できます
files:
# Private key
"/etc/pki/tls/certs/ひみつかぎ.key":
mode: "000400"
owner: root # 必要に応じて適切なuserに変更してください
group: root # 必要に応じて適切なgroupに変更してください
authentication: "S3Auth" # S3Authを指定する場合、上記Resourcesの記述も必須
source: https://elasticbeanstalk-ap-northeast-1-xxxxxxxxxx.s3.ap-northeast-1.amazonaws.com/ひみつかぎ.key
※ハマったところ
-
.ebextentions
以外のフォルダにconfigファイルを作っても読み込まれません。
最初気づかずに、何回デプロイしても毎度、鍵が見当たらないよ系のエラーがでてきて、時間を溶かしました。 -
Resources:
は必須です。files:
でS3Auth
を指定する場合、これがないことでエラーになります
10. Elastic Beanstalk環境で動作確認
きちんとURLが生成できていることを確認。
期限切れの場合は見れないことも確認。
まとめ
無事にElastic Beanstalk環境のLaravelから、CloudFrontの署名付きURL経由でS3オブジェクトにアクセスすることができました🎉
鍵の扱いが本当にこれでよかったのかが少し気になっているので、もっといい方法知っているよという方がいましたらぜひ教えてください!
今回は単一環境のみでのセットアップだったので、複数環境で使用する場合のメモも今後まとめてみようと思います。
参考
Discussion