特定のIPとVPCに制限したS3バケットでS3レプリケーションを設定してみた

特定のIPアドレスとVPCに制限したS3バケット間でオブジェクトのレプリケーションを設定してみました。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Bonjour、AWS事業本部のニシヤマです。

S3バケットへのアクセスを特定のIPとVPCに制限する

先日、上記のブログを参考にして特定のIPアドレスとVPCに制限したS3バケットを2つの環境で、S3オブジェクトのレプリケーションを実施してみたのでご紹介します。

事前準備

設定作業は省略しますが、前述のブログに沿って特定のIPアドレスとVPCに制限したS3バケットを2つ準備します。 今回は以下の2つのS3バケットで試してみます。

  • testrepl-source-bucket:レプリケーション元のS3バケット
  • testrepl-destination-bucket:レプリケーション先のS3バケット
  • 各S3バケットへ以下の様なバケットポリシーで特定のIPアドレスとVPCにアクセスを制限します。

    {
        "Version": "2012-10-17",
        "Id": "PolicyDemo",
        "Statement": [
            {
                "Sid": "Allow-from-specific-IP-and-VPC-only",
                "Effect": "Deny",
                "Principal": "*",
                "Action": "s3:*",
                "Resource": [
                    "arn:aws:s3:::<S3バケット名>",
                    "arn:aws:s3:::<S3バケット名>/*"
                ],
                "Condition": {
                    "NotIpAddress": {
                        "aws:SourceIp": [
                            "XX.XX.XX.XX/32",
                            "YY.YY.YY.YY/32",
                            "ZZ.ZZ.ZZ.ZZ/32"
                        ]
                    },
                    "StringNotEquals": {
                        "aws:sourceVpc": "vpc-054a436355a30c4b9"
                    }
                }
            }
        ]
    }

    注意点

    IPアドレスとVPCに制限をするバケットポリシーで設定時の注意点ですが、明示的なDenyを利用してポリシーに記載されたVPC ID、IPアドレス以外からは拒否するため、実在するIPアドレスなどを利用しないとバケットポリシー設定直後に操作できなくなってしまうので注意してください。 念のため、自身のAWSアカウントで発行したElastic IPなども登録しておくと何かあった場合にも安心です。

    この状態だと、Conditionに記載されたIPアドレスや、VPC ID以外からawsコマンド利用した場合も以下の様なエラーが発生します。

    $ aws s3 ls s3://testrepl-source-bucket/
    
    An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

    それではこちらの設定は完了した状態で進みます。

    レプリケーション設定

    それではレプリケーション設定を実施してみます。以下のブログを参考に同一リージョンでのS3バケットのレプリケーションを設定していきます。

    [アップデート] 同一リージョン内でS3バケットのレプリケーションが出来るようになりました!

    上記ブログにもある通り、レプリケーションを利用する際両方のS3バケットでバージョニングの有効化が必要なので設定します。必要であればライフサイクルルールで旧バージョンの削除設定なども追加してください。その他注意点に関しては上記ブログを参照して下さい。

    レプリケーション元のS3バケットのバージョニング設定

    レプリケーション先のS3バケットのバージョニング設定

    それでは、testrepl-source-bucketからtestrepl-destination-bucketへのレプリケーション設定を実施します。 管理タブのレプリケーションルールを作成をクリックします。

    レプリケーションルールを作成画面では、適当なレプリケーションルール名を入力します。 今回はルールスコープはバケット内のすべてのオブジェクトに適用を選択し、送信先にtestrepl-destination-bucketを入力します。 IAM ロールでは新しいロールの作成を選択し他はデフォルトのままで保存をクリックします。

    これでルールが作成されました。

    ファイルをアップロード

    それではS3バケットにファイルをアップロードしてみます。

    アップロードに成功しました。レプリケーションのステータスはオブジェクトの詳細画面で確認可能な為実行されるまで暫し待ちます。

    以下のURLにある通りS3のレプリケーションにはほとんどが15分以内に完了しますが、数時間以上かかる場合もあるとのことですのでのんびり待ちましょう。

    https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-object-replication-time/

    ほとんどのオブジェクトは 15 分以内にレプリケートされますが、レプリケーションには数時間以上かかることがあります。レプリケーションは非同期プロセスで、オブジェクトは最終的にレプリケートされます。

    暫くするとレプリケーションステータスがFAILEDになって失敗してしまいました。レプリケーション先のS3バケットにもオブジェクトはありません。

    解決方法

    こちら検証したところIPアドレスとVPCに制限した際に設定したバケットポリシーによりエラーが発生している様です。そのため、S3バケットのレプリケーションの設定の際に作成したIAMロールをバケットポリシーで許可する必要があります。 また、許可する際の書き方は以下URLの例に記載されています。

    https://aws.amazon.com/jp/premiumsupport/knowledge-center/block-s3-traffic-vpc-ip/

    (同じ AWS アカウント内の) 特定のユーザーにバケットへのアクセスを許可する必要がある場合は、[Condition] (条件) ブロック内に次のステートメントを含めます。
    
    AROAEXAMPLEID は許可する IAM ロールのロール ID です。
    AIDAEXAMPLEID は許可する IAM ユーザーのユーザー ID です。
    111111111111 はバケットの AWS アカウント ID で、AWS アカウントのルートユーザーの認証情報を表します
    
    例:
    
    "StringNotLike": {
    "aws:userId": [
    "AROAEXAMPLEID:*",
    "AIDAEXAMPLEID",
    "111111111111"
    ]
    }

    IAMロールのID確認

    S3レプリケーションルールの設定からレプリケーションに利用しているIAMロールを確認します。

    s3crr_role_for_testrepl-source-bucketというIAMロールを利用していることが確認できましたので、AWS CLIで上記のIAMロールのIDを確認します。

    $ aws iam get-role --role-name s3crr_role_for_testrepl-source-bucket
    {
        "Role": {
            "Path": "/service-role/",
            "RoleName": "s3crr_role_for_testrepl-source-bucket",
            "RoleId": "XXXXXXXXXXYYYYYYYYYY",
            "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/service-role/s3crr_role_for_testrepl-source-bucket",
            "CreateDate": "2021-04-26T14:07:05+00:00",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "s3.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            },
            "MaxSessionDuration": 3600,
            "RoleLastUsed": {}
        }
    }

    RoleIdの確認ができました。

    S3バケットポリシーの修正

    それではS3バケットポリシーを修正します。

    先ほどの参考URLの例に、RoleIdの値を入れてバケットポリシーを作成し、以下の様なポリシーになりました。この際、IAMロールの後ろに:*が必要になるので注意して下さい。

    {
        "Version": "2012-10-17",
        "Id": "PolicyDemo",
        "Statement": [
            {
                "Sid": "Allow-from-specific-IP-and-VPC-only",
                "Effect": "Deny",
                "Principal": "*",
                "Action": "s3:*",
                "Resource": [
                    "arn:aws:s3:::<S3バケット名>",
                    "arn:aws:s3:::<S3バケット名>/*"
                ],
                "Condition": {
                    "StringNotLike": {
                        "aws:userId": [
                            "XXXXXXXXXXYYYYYYYYYY:*"
                        ]
                    },
                    "NotIpAddress": {
                        "aws:SourceIp": [
                            "XX.XX.XX.XX/32",
                            "YY.YY.YY.YY/32",
                            "ZZ.ZZ.ZZ.ZZ/32"
                        ]
                    },
                    "StringNotEquals": {
                        "aws:sourceVpc": "vpc-054a436355a30c4b9"
                    }
                }
            }
        ]
    }

    再びファイルをアップロード

    こちらのバケットポリシーをレプリケーション元、レプリケーション先両方のS3バケットに設定して再度ファイルをアップロードします。 暫くすると、レプリケーションステータスがCOMPLETEDになりました。

    レプリケーション先のS3バケットにもちゃんとオブジェクトが作成されていました。

    以上です。

    おわりに

    S3バケットを特定の場所からのみアクセスさせたいという要件はよくあるかと思いますが、それに加えレプリケーション機能を利用することでオブジェクトのバックアップやバケットの集約することができました。この記事がどなたかのお役に立てば幸いです。