ブロックパブリックアクセスを有効にする前に問題ないか確認したい

2020.03.10

大阪オフィスのちゃだいん(@chazuke4649)です。

ブロックパブリックアクセスしてますか?(誰かのマネ

   

S3のブロックパブリックアクセス(Block Public Access 以降BPA)は、パブリック公開防止の安全装置としてとても便利な機能ですが、たまに少し悩むことがあります。

「BPAを有効にしたいけど、アプリケーションやシステムに影響ないだろうか?」

既存S3バケットで念のため有効にしたい場合、事前調査できると不安解消できますよね。
今回は、1つ方法を考えましたのでご紹介します。

そもそもBPAについては下記エントリをどうぞ。

前提

今回の調査はBPA有効化前に必須の作業ではありません。
むしろ大半が不要かと思いますが、一部下記のような状況が起きる場合があります。

  • S3上のファイルのACLが変更されている可能性がある
  • ACL操作権限をS3クライアントに付与している
  • ACLのパブリック公開設定で、S3ファイル利用しているシステムが存在する可能性がある など

こういった時に今回の調査は役に立つかもしれません。

条件

今回の調査方法は、全てのケースで有効な訳ではありません。
以下のような条件を想定しています。

  • アクセスポリシーから判断する
  • ステータスを「公開可能」から「非公開」に変更したいケースを対象とする
  • BPAのIgnorePublicAcls RestrictPublicBucktsの影響を調査する
     

逆に、以下は例外となります。

  • アクセスログから判断する
  • ステータスを「パブリック」から「非公開」に変更したいケースを対象とする
  • BPAの4つ全ての影響を調査する

順番に各条件の意味合いを説明します。

1.アクセスポリシーから判断する

まず1つ目、今回はアクセスポリシーから判断します。

ここでいうアクセスポリシーとは、S3のリソースベースのポリシー(バケットポリシー・バケットACL・オブジェクトACL)を指します。

つまり、S3側にパブリックアクセスが有効なアクセスポリシーがない → 実質アクセスできない → BPA有効にしても問題ないよねっていうことです。

例外としてはアクセスログから判断することですが、ここから判断するのは難しく骨の折れる作業になると考えられます。理由としては、パブリックの定義および複雑な判定のため厳密な抽出が難しいためです。

なので、今回は効率の良いアクセスポリシーをチェックする方法をとります。

2.「公開可能」から「非公開」にしたいケースを対象

アクセスステータス

バケットのアクセスステータスを、正確には「オブジェクトは公開可能」から「バケットとオブジェクトは非公開」に変更したいケースを対象とします。

基本的にはパブリックな使い方をしていないバケットを念のためBPAを有効化して、絶対公開されないようにしたいといったものです。

すでに「パブリック」で使用しているバケットにBPAを有効化すれば、おそらく影響が出るので、今回の「事前に影響の有無を調べる」ことはあまり意味を成さないからです。

3.IgnorePublicAcls RestrictPublicBucktsの影響を調査する

BPAでは、4つの設定をそれぞれ有効にすることができます。
内容は平たくいうと以下の通りです。

  • BlockPublicAcls:未来にパブリックなACLに変更することを阻止する
  • IgnorePublicAcls:現在のパブリックなACLを無効化する
  • BlockPublicPolicy:未来にパブリックなポリシーに変更することを阻止する
  • RestrictPublicBuckts:現在のパブリックなポリシーを無効化する  

Amazon S3 ブロックパブリックアクセスの使用

今回影響を調査するのは、IgnorePublicAcls RestrictPublicBucktsの2つです。
理由としては、

  • 現在のアクセスポリシーから判断するので、未来にポリシーが変更されるかどうかは判断できない
  • バケットレベルの権限をアプリケーションがころころ変更するのは考えにくい(よろしくない)
  • オブジェクトレベルの権限を使ってるなら、現在のオブジェクトACLをみることである程度判断できる

と考えるためです。

なので、影響調査としては2つだが、調査で問題なければ多くの場合4つとも影響がない可能性が高いです。

ちなみに、BlockPublicAclsの影響調査は、下記エントリが参考になります。

今回の調査方法

ごめんなさい、やっと本題です。
シンプルですが下記2点を実施します。

  • バケットレベルのパブリック設定有無を、S3アクセスアナライザーで調査する(念のため)
  • オブジェクトレベルのパブリック設定有無を、自前スクリプトで調査する

ポイントとして、s3アクセスアナライザー(Access Analyzer for S3)はバケットレベルをチェックしてくれますが、オブジェクトレベルには対応してません。なので、自前のスクリプトでオブジェクトACLで調査する流れになっています。

S3アクセスアナライザーについては下記エントリをどうぞ。

1.バケットレベルの念のため調査

S3アクセスアナライザーの調査するのは、バケットポリシーとバケットACLの2つです。

やたらと「念のため」としている理由は、バケットのステータスが「オブジェクトは公開可能」となっている場合、基本的にS3アクセスアナライザーでパブリック検知はされていないはずです。

  • 下図のように対象のバケットが「パブリックアクセスのバケット」に表示されていなければOK

2.オブジェクトレベルの調査

ざっくり言うと、test-bucket-nameを対象のバケット名に変更して、Boto3で下記スクリプトを実行すればOKです。

obj-acl-checker.py

import boto3  
  
  
# あるバケットのオブジェクトを全部取得して
# それぞれオブジェクトについて パブリックACLが付いていないか調べる
# パブリックACLが付いているオブジェクト情報を出力する
bucket_name = "test-bucket-name"
print("--- {}".format(bucket_name))  
  
# Bucketのオブジェクト一覧を取得できるようにする
client = boto3.client('s3')
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)   
  
#オブジェクトの総数を表示する
obj_list = []
for obj in bucket.objects.all():
    obj_list.append(obj)
print("number of objects: {}".format(len(obj_list)))

for obj in obj_list:
    # obj の ACL情報を取得する  
    acl = client.get_object_acl(
        Bucket=bucket_name,
        Key=obj.key
    )
    # PublicなACLだけ表示する
    grants = acl['Grants']
    all_user = "http://acs.amazonaws.com/groups/global/AllUsers"
    auth_user = "http://acs.amazonaws.com/groups/global/AuthenticatedUsers"
    for g in grants:
        uri = g['Grantee'].get('URI')
        if uri == all_user or uri == auth_user:
            print("object:{}\tacl_uri:{}".format(obj.key, uri))

少し説明をすると以下処理を行っています。

  • 対象のバケットに格納されているオブジェクトの総数を表示する
  • 各オブジェクトのオブジェクトACLを参照する
  • そのうち、ALLUsersorAuthenticatedUsersを含むオブジェクトのみ表示する

ACL Amazon S3 は、定義済みの AllUsers または AuthenticatedUsers グループのメンバーにアクセス許可を付与した場合、バケットまたはオブジェクト ACL はパブリックであると見なします。

パブリックの意味より引用

オブジェクトの調査をやってみた

まず、S3バケットオブジェクトACLの異なるいくつかのオブジェクトを設置します。

権限周りが問題なければ、あとは先ほどのスクリプトを実行するだけです。
以下が実行結果です。

% python obj-acl-checker.py
--- test-chadain-20200304
number of objects: 4
object:testdoc.txt	acl_uri:http://acs.amazonaws.com/groups/global/AuthenticatedUsers
object:testdoc2.txt	acl_uri:http://acs.amazonaws.com/groups/global/AllUsers

パブリックなオブジェクトACLを持つオブジェクトが2つ見つかりました。
もしBPAを有効にしたら、この権限を使用したリクエストはブロックされます。

もちろん、何もヒットしなければパブリックなACLは存在しないということです。

パブリックなACLが発見されたらどうすべき?

いくつか見つかった場合は、対応の検討が必要です。

  • パブリックなオブジェクトACLをPut、Getする箇所の特定および修正
  • 実施しない場合、第三者にGetされる可能性があるという理解

公開が意図しない設定であるならば、BPAを有効化にすることで、パブリック公開を阻止し安全な状態を保つことができます。

終わりに

以上2つの方法でアクセスポリシーを確かめることによって、BPAによる影響を事前調査することができます。

これさえやれば完璧かというとそうではないのですが、ある程度不安を解消することには使えるのかなぁと思われます。

このブログが少しでお役に立てば幸いです。
大阪オフィスのちゃだいん(@chazuke4649)でした。