AWS KMSのデフォルトのキーポリシーにrootの権限がついている件について調べてみた。
理由
rootがあることでIAMポリシーからキーポリシーへアクセスるできるようになる模様。
KMSキーが管理不要になるリスクを回避するためにデフォルトでrootアカウントに権限を振っている模様。
docs.aws.amazon.com
調査
rootなしのキーポリシーを作成しIAMポリシーの権限でKMSキーにアクセスできないことを確認する。
その後rootを付与しIAMポリシーの権限でアクセスできることを確認する。
やること
CloudFormationでKMSで暗号化されているS3バケットと、S3へ接続するためのLambdaを作成し、キーポリシーを操作して接続有無を確認する。
実践!
1.環境構築
1-1.下記CloudFormationを実行
※キーポリシー内のユーザとログインしているユーザを合わせること。
※今回は[testuser]を作成し、そのユーザでAWSコンソールにログインしてCloudFormationを実行する。
AWSTemplateFormatVersion: '2010-09-09' Resources: # KMSキーの作成 MyKMSKey: Type: "AWS::KMS::Key" Properties: Description: "KMS Key for S3 encryption" KeyPolicy: Version: "2012-10-17" Id: "key-default-1" Statement: - Sid: "Enable IAM User Permissions" Effect: "Allow" Principal: AWS: - !Sub "arn:aws:iam::${AWS::AccountId}:user/testuser" Action: "kms:*" Resource: "*" # IAMロールの作成 MyLambdaExecutionRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" Policies: - PolicyName: "LambdaS3KMSEncryptionPolicy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "s3:GetObject" - "s3:PutObject" Resource: - !Sub "arn:aws:s3:::${MyS3Bucket}/*" - Effect: "Allow" Action: - "kms:Decrypt" - "kms:Encrypt" - "kms:GenerateDataKey" Resource: - !Sub "arn:aws:kms:${AWS::Region}:${AWS::AccountId}:key/${MyKMSKey}" # S3バケットの作成 MyS3Bucket: Type: "AWS::S3::Bucket" Properties: BucketName: !Sub "${AWS::StackName}-mybucket" BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: "aws:kms" KMSMasterKeyID: !Ref MyKMSKey # Lambda関数の作成 MyLambdaFunction: Type: "AWS::Lambda::Function" Properties: FunctionName: !Sub "${AWS::StackName}-MyLambdaFunction" Handler: "index.handler" Role: !GetAtt MyLambdaExecutionRole.Arn Code: ZipFile: | import json import boto3 s3 = boto3.client('s3') def handler(event, context): bucket = event['bucket'] key = event['key'] response = s3.get_object(Bucket=bucket, Key=key) data = response['Body'].read().decode('utf-8') return { 'statusCode': 200, 'body': json.dumps(data) } Runtime: "python3.9" Environment: Variables: BUCKET_NAME: !Ref MyS3Bucket
2.S3バケットにサンプルファイルをアップロード
2-1.AWS - [S3] - 作成したS3バケットを選択
2-2.サンプルファイルをアップロード
※今回は[test.txt]というファイルをアップロードする。
3.Lambda実行(失敗パターン)
3-1.AWS - [Lambda] - 作成した関数を選択
3-2.[Test]
3-3.下記を入力
イベント名:イベント名
イベントJSON:下記を入力
{ "key": "test.txt", "bucekt": "test-stack01-mybucket" }
3-4.[保存]
3-5.[Test]
3-6.S3への接続に失敗すること
4.Lambda実行(成功パターン)
4-1.AWS - [KMS] - [カスタマー管理型のキー] - 作成したKMSキーを選択
4-2.キーポリシーの[編集]
4-3.下記に変更
{ "Version": "2012-10-17", "Id": "key-default-1", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::xxxxxxxxxxxx:user/testuser" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::xxxxxxxxxxxx:root" }, "Action": "kms:*", "Resource": "*" } ] }
4-4.[変更の保存]
4-5.AWS - [Lambda] - 作成した関数を選択
4-6.[Test]
4-7.200OKが返ってきて、S3にアップロードしたファイルの中身が表示されること
※キーポリシーにrootが追加されることでIAMに付与しているKMSポリシーが生き、接続できるようになる。
感想
KMSポリシーにIAMを設定しなくてもIAMポリシーのKMS設定が生きるロジックが不明だったが理解できた!