あめがえるのITブログ

頑張りすぎない。ほどほどに頑張るブログ。

AWS KMSのデフォルトのキーポリシーにrootの権限がついている件


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設定が生きるロジックが不明だったが理解できた!