优化 AWS KMS 解密费用以提升数据库活动流的效能
关键要点
合规行业如医疗和金融对数据库活动审计要求严格,需要确保用户操作的记录,保障合规性和安全性。AWS 提供的数据库活动流Database Activity Streams,DAS能有效审计数据库活动,但频繁的解密调用可能导致不可预测的成本。本文介绍了一种优化 AWS KMS 解密成本的方法,通过实施缓存策略来减少 KMS 调用次数。通过采用此解决方案,企业能够在确保安全的同时,降低 AWS KMS 的使用费用。在医疗和金融等受监管行业,审计数据库活动至关重要。公司需要记录数据库用户和管理员执行的操作,以维护合规性和安全性。
AWS 提供了强大的数据库审计功能,通过数据库活动流DAS实现。此功能与Amazon关系数据库服务Amazon RDS和Amazon Aurora集成,可以详细记录所有对数据库的操作,包括 SQL 命令、连接信息和数据库模式的更改有关更多信息,请参考监控数据库活动流。DAS 与AWS 密钥管理服务AWS KMS集成,使得在活动流中对数据的加密和解密成为可能。然而,随着数据库工作负载的增长和审计量的增加,频繁的解密调用可能会带来不可预测的费用。
在本文中,我们将介绍一种潜在的解决方案,帮助优化与 AWS 管理的数据库审计功能相关的费用。该策略能够减少解密活动日志所需的 AWS KMS 调用次数,并通过实施加密密钥的缓存策略,降低超出调用速率限制的风险。
解决方案概述
下图展示了该解决方案的高层架构。
该解决方案使用的 AWS 服务和功能包括:
飞鱼加速器手机版Amazon Aurora 数据库活动流 用于监控和审计用户操作AWS 身份与访问管理IAM 能够进行程序性访问,允许各个组件相互交互AWS 密钥管理服务AWS KMS 由 Aurora 用于在将数据插入数据库活动流之前对其进行加密Amazon Kinesis 数据流 用于将审计数据通过 Kinesis 数据流提供AWS Lambda 作为数据处理器,用于从 Kinesis 数据流读取活动负载并缓存 AWS KMS 数据密钥本文介绍的解决方案实现了缓存用于解密 DAS 负载的数据加密密钥的逻辑。通过缓存数据密钥,可以减少对 AWS KMS 的 API 调用次数。
安全性考虑
缓存加密密钥可以显著降低成本并优化部署,然而,保持稳健的安全态势对于防止未授权访问敏感数据至关重要。以下是需要考虑的主要安全最佳实践:
确保 Lambda 函数的 IAM 策略权限范围应较窄。有关更多信息,请参阅Security in AWS Lambda。作为数据处理器的 Lambda 函数将日志记录到 Amazon CloudWatch。具有访问 CloudWatch 日志权限的用户可以查看解密的有效负载及相应的敏感数据,确保在 CloudWatch 日志组中应用最小权限原则。有关更多信息,请参考Identity and access management for Amazon CloudWatch Logs 和 Data protection in Amazon CloudWatch Logs。工作流包括三个阶段:审计、缓存和验证。步骤如下:
用户在数据库上进行更改。数据库集群或实例将加密的活动负载审计日志发送到 Kinesis 数据流。Lambda 函数充当记录处理器。它调用 kmsDecrypt API 解密在流启动时创建的数据加密密钥DEK。然后,使用 AWS 加密 SDK,AWS Lambda 将使用之前解密的 DEK 解密活动负载。Lambda 函数随后缓存数据密钥,以供后续解密,直到达到函数超时或缓存限制。 有关更多信息,请参阅 数据密钥。负载解密后,Lambda 函数可以将日志导出到进一步分析,例如 Amazon S3、Amazon OpenSearch 和第三方监控工具。安全和运营团队可以使用 CloudWatch Logs 和 AWS CloudTrail 验证解决方案的效果:CloudWatch 显示 Lambda 函数的日志,包括调用时间和运行时事件。CloudTrail 记录 AWS KMS 调用的次数。先决条件
DAS 在与 Amazon Aurora PostgreSQL 兼容版本 实施时有以下要求和限制。
创建用于数据库活动流的 KMS 密钥
数据库活动流需要一个 KMS 密钥来加密和解密记录的数据库活动。有关更多信息,请参见创建密钥。请按照以下步骤创建 KMS 密钥:
在 AWS KMS 控制台上,选择导航窗格中的 客户管理密钥。选择 创建密钥。对于 密钥类型,选择 对称。有关对称加密的更多信息,请参阅 对称加密 KMS 密钥。对于 密钥用途,选择 加密和解密。选择 下一步。对于 别名,输入密钥名称为 PostgreSQLDAS。您可以根据数据库引擎适当修改别名。对于 描述,输入可选描述,如 Amazon Aurora PostgreSQL 数据库活动流DAS的密钥。选择 下一步。在 定义密钥管理权限 下,选择允许管理该密钥的 IAM 用户和角色。选择 下一步。审核/创建密钥策略,并选择 完成。创建 KMS 密钥时,可以为新 KMS 密钥指定密钥策略。如果不提供,AWS KMS 会为您创建一个。默认密钥策略 的内容取决于您是在 AWS KMS 控制台中创建密钥还是使用 AWS KMS API。
请参照服务的密钥策略权限。
启动数据库活动流
DAS 提供了您的数据库集群活动的近实时流。有关更多信息,请参见数据库活动流如何工作。
要在 Amazon Aurora PostgreSQL 启动数据库活动流,请按照以下步骤操作:
在 Amazon RDS 控制台的导航窗格中,选择 数据库。选择您要启动活动流的 Aurora 集群。在 操作 菜单中,选择 启动数据库活动流。对于 AWS KMS 密钥,输入您之前创建的 KMS 密钥。对于 数据库活动流模式,您可以根据要求选择流的模式为同步或异步。在 调度 部分,选择 立即。选择 启动数据库活动流。
在 Kinesis 数据流控制台,等待数据流的状态显示为活动。
创建 Lambda 执行角色
该函数的目的是作为记录处理器,从 Kinesis 数据流中读取数据。它缓存数据密钥,直到达到缓存阈值和设置的 Lambda 运行时。
在启动 Lambda 函数之前,您需要创建一个具有读取 Kinesis 数据流记录权限、将函数日志写入 CloudWatch 以及使用 AWS KMS Decrypt API 解密数据密钥的 Lambda 执行角色。
按照以下步骤进行操作:
在 IAM 控制台上,创建一个新角色,并将其命名为 dasdataprocessorexecutionrole。如果没有使用默认策略,则需要将该角色添加为 KMS 策略的主体。请参考服务的权限在密钥策略中。添加所需的权限。以下 JSON 策略可作为示例。IAM 策略基于您的设置和安全要求而有所不同。请参考应用最小权限原则以获取最佳实践。
json{ Version 20121017 Statement [ { Effect Allow Action [ kmsDecrypt ] Resource arnawskmsYOURREGIONYOURACCOUNTIDkey/YOURKEYID } { Effect Allow Action [ kinesisDescribeStream kinesisGetRecords kinesisGetShardIterator ] Resource arnawskinesisYOURREGIONYOURACCOUNTIDstream/awsrdsdasclusterXXXXXXXXXXXXXXXXXXXXXXXXXXXXXI } { Effect Allow Action [ logsCreateLogGroup logsCreateLogStream logsPutLogEvents ] Resource arnawslogsYOURREGIONYOURACCOUNTID } ]}
根据前面部分创建的不同服务相应地更改 ARNs。
创建 Lambda 函数
以下是使用 AWS SDK for Python (Boto3) 的示例 Lambda 函数。请按照以下步骤创建 Lambda 函数:
在 Lambda 控制台的导航窗格中,选择 函数。选择 创建函数。选择 使用蓝图 并选择 处理发送到 Kinesis 流的记录。对于 函数名称,输入 dasdataprocessor。对于 现有角色,选择您在前面部分创建的角色。选择 创建函数。从代码源部分更新 Lambda 代码并部署新版本。有关更多详情,请参考 Lambda 控制台。根据您的具体需求设置函数超时、内存分配和其他参数。有关更多信息,请参见 AWS Lambda 定价 和 配置函数超时控制台。您可以在 AWS Samples GitHub repo 中找到函数代码。
在代码中,根据您的具体设置更改以下值。在使用 Lambda 时,请遵循最佳实践以使用变量。有关更多信息,请参阅保护环境变量。
pythonREGIONNAME = useast1 # 您的区域RESOURCEID = clusterXXXXXXXXXXXXXXXYYYYYYYZZZZ # 您的 Aurora 集群 IDSTREAMNAME = KINESISSTREAMNAME # 您的 Kinesis 数据流名称
在代码中,以下类管理缓存。特别是,getDecrypted 方法在调用 AWS KMS 解密 API 之前,会检查缓存中是否存在密钥。
pythonclass KMSDataKeyCache() def init(self session) # 初始化 KMS 客户端和一个简单的字典以缓存密钥 selfkmsclient = sessionclient(kms regionname=REGIONNAME) selfkeycache = {}
def getDecrypted(self datakeydecoded) # 尝试从缓存中获取解密密钥,或使用 KMS 解密它 if datakeydecoded in selfkeycache return selfkeycache[datakeydecoded] else # 使用 KMS 解密密钥并存储在缓存中 datakeydecryptresult = selfkmsclientdecrypt( CiphertextBlob=datakeydecoded EncryptionContext={awsrdsdbcid RESOURCEID}) selfkeycache[datakeydecoded] = datakeydecryptresult[Plaintext] return datakeydecryptresult[Plaintext]在实施缓存时,尽管可以节省成本并提升性能,但请确保分析安全权衡。缓存的明文数据密钥在内存中可能被拥有运行时访问的任何人访问。考虑添加额外逻辑设置缓存密钥的超
发表评论