NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    AWS KMS CMKを用いたS3オブジェクトのアクセス制限

    本記事はNRIネットコム Advent Calendar 2021 14日目の記事です。
    🧦 13日目 ▶▶ 本記事 ▶▶ 15日目 🎁

    初めまして、NRIネットコム新入社員の西本です。 今回、アドベントカレンダー14日目の記事を書かせていただきました。AWS APN Ambassadorでもある上野さんの後というのは荷が重いですね(笑)私は、今年4月に新卒入社し、研修を経て7月からクラウドに関するお仕事をさせていただいています。入社当時はクラウドとは?AWSって何?っていうところからのスタートでした。入社してまだ間もないですが、業務で扱った一部を紹介したいと思います。

    今回のテーマについて

    本題ですが、上述したようにAWSのお話です。テーマは、「AWS Key Management ServiceのキーポリシーによるAmazon S3 オブジェクトのアクセス制限」についてです(以降、KMS, S3とする)。さっそくですが、今回のユースケースについて説明します。

    ユースケースについて

    今回、環境を構築するうえで、S3に対する操作は運用担当者である私たちが行うが、アップロードされる機密文書を参照することはNGといった要件がありました。

    参照権限(get) その他権限
    運用担当者 ×
    お客様

    このユースケースを満たすには以下のような手段があるかと思います。
    ・ IAMロールでの制御
    ・ バケットポリシーでの制御
    ・ S3 AccessPointでの制御
    ・ KMS CMKでの制御

    今回の記事ではKMS CMKを使用する方法について紹介します。作成したCMKのキーポリシーにprincipalでIAMロールを指定することで、今回の要件を満たすように設計します。運用担当者・お客様はそれぞれのロールを使用します。 構成は以下の通りです。

    KMS CMKでのアクセス制御については下記の記事が参考になります。
    参考記事:
    AWS KMS CMK(Customer Master Key)のキーポリシーとIAMポリシーの組み合わせのアクセス制御と、キーポリシーのみのアクセス制御を試して設定の違いをみてみた | DevelopersIO

    KMSのキーポリシーを利用したアクセス制御を採用した理由

    KMSによるアクセス制御には、制御の容易さ二重防止策になるといったメリットがあると考えています。例えば、複数のバケットに対してバケットポリシーのみで今回の要件を満たすように制御しようとすると、バケット数分の細かい設定が必要になります。その際、設定ミスや誤った設定をしたまま更新をかけてしまったことが原因で、意図しないアクセス元からオブジェクトにアクセスできてしまうといったこともゼロとは言いきれないかと思います。今回の検証では、バケット作成時にあらかじめ作成しておいたCMKでデフォルト暗号化を実施することで、以下の 2点が達成できます。

    ・許可すべきユーザーのみがオブジェクトの参照・ダウンロードを可能にする(IAMポリシー、バケットポリシーによる設定は別途必要です)
    ・バケットポリシーの設定不備により、意図しないアクセス元からオブジェクトにアクセスできたとしても暗号化されたデータを復号できず、データの中身を保護できる

    KMSを利用した場合コストが発生します。一方で上述したIAMロールやバケットポリシーでのアクセス制御の場合、コストは発生しません。その点を考慮して設計していく必要があるでしょう。

    今回の検証の流れ

    検証は以下の手順で進めました。

    1. 運用担当者用ロールとお客様用ロールの作成
    2. カスタマー管理CMKの作成
    3. 2で作成したCMKを使ってデフォルト暗号化したS3バケットの作成
    4. S3バケットにオブジェクトをアップロードし、マネジメントコンソール上から運用担当者用・お客様用ロールそれぞれでオブジェクトにアクセスした際の挙動を確認

    1. 各ロールの作成

    今回は運用担当者用とお客様用の2つのロールを準備しました。どちらのロールにもS3に対する全操作ができる権限を付与しています。

    2. カスタマー管理CMKの作成

    特定のIAMロールでのみ復号可能とするため、キーポリシーを以下のように設定しました。後述しますが、キーポリシーの設定は注意が必要です。

    {
        "Version": "2012-10-17",
        "Id": "key-xxxx",
        "Statement": [
            {
                "Sid": "XXXX",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:role/xxxxxxxx" //運用担当者用ロール
                },
                "Action": [
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:TagResource",
                    "kms:UntagResource",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                    "kms:GenerateDataKey"
                ],
                "Resource": "*"
            },
            {
                "Sid": "XXXX",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:role/xxxxxxxx" //お客様用ロール
                },
                "Action": "kms:Decrypt",
                "Resource": "*"
            }
        ]
    }
    

    運用担当者用ロールにはDecryptの権限を与えず、キーの削除といった操作権限を付与しました。お客様用ロールにはDecrypt権限のみを付与することで今回の要件を満たすように設定しています。

    キーポリシー設定時の注意点

    権限については最小権限にすることがベストプラクティスです。一方で、必要なアクション権限を付与せず更新してしまうとキーの削除やキーポリシーの変更ができなくなってしまいます。バケットポリシーの設定でよく耳にするのではないでしょうか。
    また、バケットポリシーではrootユーザーを使用することで対処できますが、キーポリシーでは暗黙的にrootユーザーに対して権限が与えられていません。そのため、rootユーザーに操作権限を与えておきたい場合は明示的に設定しておく必要があります(今回の検証では必要ないのでrootユーザーに対して権限を与えず進めます)。実は、一度キーポリシーの設定を失敗してしまいマネジメントコンソール上から全く操作ができなくなってしまいました。今回は幸いにもPut権限を与えていたことでAWS CLIでキーポリシーをリカバリーすることができました。

    キーポリシーの設定に失敗し、対処できなくなってしまった場合にはAWSサポートに問い合わせが必要になります。
    参考記事:「In this scenario」で検索かけると該当箇所にたどり着けます。
    Default key policy - AWS Key Management Service

    3. S3バケットの作成

    作成したカスタマー管理CMKでデフォルト暗号化したS3バケットを作成します。 バケットポリシーは以下のように設定し、運用担当者用ロール及びお客様用ロールのみが使用できるように制限しました。 特定のIAMロールに対して制限したい場合には、ConditionでRoleIdを設定することになります。詳細についてはこちらの記事が参考になりました。
    参考記事:
    特定の IAM ロールのみアクセスできる S3 バケットを実装する際に検討したあれこれ | DevelopersIO

    RoleIdはCLIにて以下のコマンドで確認できます。

    $ aws iam get-role  --role-name ロール名 

    今回設定したバケットポリシーはこちらになります。※RoleIdの後に:*をつけるのをお忘れないように。

    {
        "Version": "2008-10-17",
        "Statement": [
            {
                "Sid": "BaseDeny",
                "Effect": "Deny",
                "Principal": "*",
                "Action": "s3:*",
                "Resource": [
                    "arn:aws:s3:::bucket-name/*",
                    "arn:aws:s3:::bucket-name"
                ],
                "Condition": {
                    "StringNotLike": {
                        "aws:userid": [
                            "XXXXXXXXXXXXXXXXXXXXXX:*",  //運用担当者用RoleId
                            "XXXXXXXXXXXXXXXXXXXXXX:*" //お客様用RoleId
                        ]
                    }
                }
            },
            {
                "Sid": "BaseAllow",
                "Effect": "Allow",
                "Principal": "*",
                "Action": "s3:*",
                "Resource": [
                    "arn:aws:s3:::bucket-name/*",
                    "arn:aws:s3:::bucket-name"
                ],
                "Condition": {
                    "StringLike": {
                        "aws:userid": [
                            "XXXXXXXXXXXXXXXXXXXXXX:*",  //運用担当者用RoleId
                            "XXXXXXXXXXXXXXXXXXXXXX:*" //お客様用RoleId
                        ]
                    }
                }
            }
        ]
    }
    

    本来はBaseAllowの部分の設定のみでも要件を満たしますが、許可されたロール以外からの操作を完全に遮断するため、BaseDenyの設定を加えています。バケットポリシーでは、明示的なDenyの効力が最も強くなります。

    4. オブジェクトアクセス時の挙動確認

    作成したS3バケットにオブジェクト(test.txt)をアップロードします。 その後、アップロードしたオブジェクトに対してマネジメントコンソールから「開く」や「ダウンロード」操作をした際の挙動について見ていきます。

    運用担当者用ロール

    暗号化されたオブジェクトを復号するための権限がキーポリシーで付与されていないため、Access deniedとなり下のように失敗します。

    お客様用ロール

    運用担当者用ロールとは違い、復号するための権限が与えられているためオブジェクトに対して「開く」や「ダウンロード」操作が可能です。

    以上で、KMS CMKを利用し、S3バケットのオブジェクトに対して参照可能とするユーザーを制限することができました。

    まとめ

    S3バケットのオブジェクトに対して、CMKを利用したアクセス制御について考えてみました。制御の方法も様々で、要件に応じて最も適している手段はどれなのかをしっかり検討した上で設計する必要があると感じました。今回の要件を満たすためにどういう設定が必要かを考えることで各サービスについての理解も深まりました。また、慎重に各ポリシーの設定は行っていたたものの、失敗してしまったこともあり、その設定をすることによってどういう挙動になるのかを考えた上で作成・更新をしていくように努めたいと思います。
    ここまで書きましたが、人に伝えるための文章を書くのは難しいなと改めて感じました。今後は、認定資格を中心にAWSに関する知識を増やし、文章力強化のためにもブログの執筆に取り組んでいきたいと思います。

    NRIネットコム Advent Calendar 2021
    🧦 13日目 ▶▶ 本記事 ▶▶ 15日目 🎁