SCP を利用して S3 署名付き URL の利用を HTTPS のみに制限してみた
こんにちは、大前です。
詳細は以下ブログを参照したいただければと思いますが、S3 署名付き URL は、生成された URL を利用してアップロードやダウンロードを行う際に、権限に関する評価が行われます。
上記の仕様をもとに、SCP を利用して S3 署名付き URL の利用に対する制限を行えるのかを試してみました。具体的には、S3 署名付き URL を利用する際には HTTPS のみに限定する様なポリシーを SCP で適用してみたいと思います。
やってみた
SCP なしでの S3 署名付き URL 利用
まずは SCP の設定なしで S3 署名付き URL を利用し、コンテンツのアップロードとダウンロードを試してみます。
前提として、AWS 上で操作を行なっているユーザは Administrator 相当の権限を持ち、今回利用する S3 バケットはパブリックアクセス禁止かつバケットポリシーは無しの状態となっています。
S3 署名付き URL を利用したダウンロード
S3 にアップロード済みの sample_file
というファイルを S3 署名付き URL を利用してダウンロードします。ダウンロード用の署名付き URL はコンソールから生成します。
取得した URL を利用すると、コンテンツのダウンロードができます。("THIS IS SAMPLE FILE" は sample_file 内に記載されたテキストです)
curl -X GET "https://<ダウンロード元バケット>.s3.ap-northeast-1.amazonaws.com/sample_file THIS IS SAMPLE FILE
ちなみに、取得した URL を http に変更しても変わらずコンテンツが取得できます。後ほど、SCP を利用して https のみの利用に制限できるか試してみます。
curl -X GET "http://<ダウンロード元バケット>.s3.ap-northeast-1.amazonaws.com/sample_file THIS IS SAMPLE FILE
S3 署名付き URL を利用したアップロード
続いて、アップロードです。S3 署名付き URL を利用したアップロードを試すにあたり、具体的な方法については以下ブログを参考にしました。ブログ内の記載に従えば、Lambda を利用してアップロード用の S3 署名付き URL を生成できます。
生成された URL を利用し、sample_file_2
というファイルをアップロードします。
curl -X PUT --upload-file sample_file_2 "https://<アップロード先バケット>.s3.amazonaws.com/sample_file_2
S3 にアップロードできました。
ダウンロードと同様に、払い出された URL を http に変更しても問題なくアップロードできます。これについてもダウンロードと同じく、後ほど SCP を利用して http でのアップロードを制限できるか試してみます。
curl -X PUT --upload-file sample_file_2 "http://<アップロード先バケット>.s3.amazonaws.com/sample_file_2
SCP で https のみ利用可能なポリシーを追加
制限がない状態だと http/https ともに S3 署名付き URL の利用が可能であることがわかったため、SCP にポリシーを追加し、意図した通りに制限がかけられるか確認してみます。
S3 が存在する AWS アカウント(もしくはアカウントが所属する OU)に対して、以下の SCP を適用します。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Statement1", "Effect": "Deny", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::*", "Condition": { "Bool": { "aws:SecureTransport": "false" } } } ] }
S3 署名付き URL のアップロード/ダウンロードに対応するアクションは GetObject/PutObject であるため、アクションとしてはこの 2つを指定しています。また、Condition 句で aws:SecureTransport
に関する条件を追加することで、HTTP リクエストを許可しない形にしています。Resource は全ての S3 バケットが対象になっていますが、特定の S3 バケットのみを指定しても良いと思います。
参考 : s3-bucket-ssl-requests-only の S3 バケットポリシーを作成する
SCP を追加したので、再度 S3 署名付き URL を利用した際の動作を確認してみます。
S3 署名付き URL を利用したダウンロード(SCP 制限あり)
先ほどと同様に、sample_file に対して S3 署名付き URL を生成し、ダウンロードを試みてみます。
# HTTPS curl -X GET "https://<ダウンロード元バケット>.s3.ap-northeast-1.amazonaws.com/sample_file THIS IS SAMPLE FILE
# HTTP curl -X GET "http://<ダウンロード元バケット>.s3.ap-northeast-1.amazonaws.com/sample_file <?xml version="1.0" encoding="UTF-8"?> <Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>xxxx</RequestId><HostId>xxxx</HostId></Error>
HTTP のリクエストのみ AccessDenied となったため、SCP が効いていることがわかります。
S3 署名付き URL を利用したアップロード(SCP 制限あり)
同様に、アップロードについても確認します。
# HTTPS curl -X PUT --upload-file sample_file_2 "https://<アップロード先バケット>.s3.amazonaws.com/sample_file_2
# HTTPS curl -X PUT --upload-file sample_file_2 "https://<アップロード先バケット>.s3.amazonaws.com/sample_file_2 <?xml version="1.0" encoding="UTF-8"?> <Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>xxxx</RequestId><HostId>xxxx</HostId></Error>
アップロードについても、HTTP のリクエストが弾かれました。
(その他) S3 署名付き URL を使わないパブリックアクセス
SCP を適用した状態で、S3 バケットのアクセス許可を変更し、パブリックにコンテンツにアクセスできる様にしてみました。
この状態で、署名付き URL を利用せずにコンテンツをダウンロードしてみます。
# HTTPS curl -X GET https://<ダウンロード元バケット>.s3.ap-northeast-1.amazonaws.com/sample_file THIS IS SAMPLE FILE
# HTTP curl -X GET https://<ダウンロード元バケット>.s3.ap-northeast-1.amazonaws.com/sample_file THIS IS SAMPLE FILE
S3 署名付き URL を利用しないパブリックアクセスの場合は HTTP でもアクセスできており、SCP が影響していないことがわかります。SCP が影響する範囲は IAM ユーザーとロールのみであるため、IAM エンティティを利用しないパブリックアクセスに対して制限をかけたい場合はリソースベースのポリシー(バケットポリシー)を利用する必要があります。
参考 : サービスコントロールポリシー (SCPs) - AWS Organizations
おわりに
SCP を利用し、S3 署名付き URL の利用に関する制限をかけてみました。
多分制限かけられるよな・・・?とは思いつつも、自信がなかったので実際に試して動作を確認することができてよかったです。
Organizations によるマルチアカウント環境などでは、個々の S3 バケットにポリシーをアタッチするのではなく、SCP といった中央集約可能な制御方法を利用したい場合もあるかと思います。そういった場合に、SCP で何をどこまで縛れるのか知っておくと役に立つかと思います。
以上、AWS 事業本部の大前でした。