New Vacant-Pastime

日記以外のエントリー系

【AWS】リアルタイム音声翻訳アプリケーションのセキュアな構築にちょっと苦労したお話

苦労したけど解決できたので、備忘録も兼ねて

 

やろうとしたこと

aws.amazon.com


こちらの構築を海外の関係者と会話するのに使えないか構築して試して欲しいとのことで、最初は別の人がやっていたのですが、アクセスできないとのことで、色々調べてみました。

環境は以下の通り

これ自体はCloudFormationを使ってほぼ自動的に構築するので、土台部分は簡単な訳です。最初に詰まっていた部分はS3にアップロードしたHTMLのARNからアクセスしようとしても繋がらなかったので、これはACLで明示的に拒否ってるかバケットポリシーが無記載だろうと思ったら後者で、これはすぐに解決しました。

 

しかし、何も弄っていない状況でこの環境を作るとセキュリティもガバガバだし、CloudFrontを利用してアクセスしているのにS3から直接アクセス出来てしまうのもイケてないと思い以下の提案をしました。

①:ブロックパブリックアクセスを有効にして、誰でもアクセス出来ないようにする
②:OAIを有効にしてWebサイトへのアクセスをCloudFrontからに絞る
③:バケットポリシーの許可をCloudFrontに付与する

 

②のOAIの部分は最近OAC(Origin Access Control)というが出来たとのことで、こっちを使用することに

dev.classmethod.jp

 

これらの設定をしてセキュアな環境が作れると思ってめでたしめでたしだと思っていました……


起こったこと

ブロックパブリックアクセスを有効にし

OACの設定も完了

CloudFront経由でWebサイトも立ち上がりOK!!!
しかし、待てど暮らせど録音した結果が日本語音声で帰ってきません

CloudWatchLogsを見るとLambda>S3の連携でアクセス拒否が出力されていました。
バケットポリシーの記載やLambdaやIAMの権限?と思い、あえてガバガバな権限にしましたが状況は改善せず。一旦途方に暮れます


解決


ブロックパブリックアクセスを一部有効にしたり無効にしたりすると、エラーが403や400と変わるので「もしかして、Lambda>S3の連携はインターネットを経由している?」と当たりが付きました。
さらに調べていくと

qiita.com

 

ブロックパブリックアクセス
S3には、アカウントレベルもしくはバケットレベルでバケットのパブリックアクセスを防止する「ブロックパブリックアクセス」という機能がある。
この機能を使うと、ACLバケットポリシーでのアクセス設定にかかわらず、最優先でパブリックアクセスを禁止したり、パブリックアクセスの許可を設定できないように制御できる。

あ……なるほどね。だからこれを有効にした状態でバケットポリシーの権限をめっちゃ緩くするとエラーになったのか……Access Denyしか出てないから原因が分からなかった……

さらに調べていくとこんな記事が

vlayusuke.com

 

どうも、同一アカウント内でS3バケットに対する操作を行う場合でも、Lambda関数とレイヤーからの操作を受け入れるためのassumed roleを明示的に書かないと、S3バケットに対する操作ができないようです。

今回の構成では、Amazon S3向けのVPC Endpointは実装していないので、Lambda関数からS3へのアクセスの通信が、一旦インターネットに出ていっているが故に、明示的にこういったポリシーの設定をしてあげないとダメなのかもしれません

 

そういうことかーーーー!!!
というわけで、CloudFrontとLambdaの内容を記載したバケットポリシーをこんな感じに

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::アカウントid:role/Lambda用実行ロール",
                    "arn:aws:sts::アカウントid:assumed-role/Lambda用実行ロール/Lambda実行関数"
                ]
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::S3バケット/*"
        },
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::S3バケット/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::アカウントid:CloudFrontID"
                }
            }
        }
    ]
}

この後実行したら無事翻訳の音声も流れて、かつCloudFrontからのみアクセスできるようになりましたとさ

バケットもフルオープンになっていないことを確認済。


終わってみて

S3関連のアクセス制限の優先順位等、権限周りの知識が曖昧だったなぁと痛感。バケットポリシーとかブロックパブリックアクセス等、用語や概要は知っていたけど、体系的な知識は身についていないと思った次第です。
もう少し体系的な知識をつけて、ベストプラクティスな提案をサッと出来るようになりたいところですね。

ではでは