环境准备

下载文件: https://pingfan.s3.amazonaws.com/files/kms-large-scale.zip

解压后有四个yaml,分别将其部署到CloudFormation。部署完成后如下:

image-20240622111450934

我们通过CloudFormation创建以下资源:

  • 符合和不符合最佳实践的 KMS 密钥和 KMS 密钥策略
  • 用于存储聚合数据的 S3 存储桶
  • 一个 Lambda 函数, 用于识别 KMS 密钥及其关联的策略
  • 所有必需的 IAM 策略和角色

KMS key

通过CloudFormation创建了11个CMK,例如其中一个的定义:

    Type: AWS::KMS::Key
    Properties:
      Description: An example symmetric encryption KMS key
      EnableKeyRotation: true
      PendingWindowInDays: 20
      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}:root"
            Action: 'kms:*'
            Resource: '*'
          - Sid: Allow administration of the key
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:user/Alice"
            Action:
              - 'kms:Create*'
              - 'kms:Describe*'
              - 'kms:Enable*'
              - 'kms:List*'
              - 'kms:Put*'
              - 'kms:Update*'
              - 'kms:Revoke*'
              - 'kms:Disable*'
              - 'kms:Get*'
              - 'kms:Delete*'
              - 'kms:ScheduleKeyDeletion'
              - 'kms:CancelKeyDeletion'
            Resource: '*'
          - Sid: Allow use of the key
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:user/Bob"
            Action:
              - 'kms:DescribeKey'
              - 'kms:Encrypt'
              - 'kms:Decrypt'
              - 'kms:ReEncrypt*'
              - 'kms:GenerateDataKey'
              - 'kms:GenerateDataKeyWithoutPlaintext'
            Resource: '*'

image-20240622112048491

lambda

DynamoDB 表为 Lambda 函数提供 AWS 帐户信息。这在我们构建多帐户功能时变得很重要。

Lambda中相关代码如下:

# 从dynamodb表里加载出来所有account
def get_accounts(
    dynamo_accountID: str,
    dynamodb_role: str = "dynamodb_role",
    dynamodb_table: str = "accounts",
    region: str = "us-east-1",
):
    # Get assumed role credentials for dynamodb read
    try:
        session = getAssumedRoleSession(dynamo_accountID, dynamodb_role)
        logger.info(f"Account Number: {getAccountNumber(session, region)}")

        # Who am I?
        logger.debug(f"Who Am I? [{whoami(session, region)}]")

        dynamodb = session.resource("dynamodb", region_name=region)
        table = dynamodb.Table(dynamodb_table)

        accounts = table.scan(ProjectionExpression="accountId, accountName")
        print(f"Accounts: {accounts['Items']}")

        return accounts["Items"]

    except Exception as e:
        logger.error("Issue assuming the XA role: " + str(e))

其他扫描Key,以及生成文件到S3代码逻辑也在lambda代码中可以找到。

image-20240622113203785