You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS RDS数据库活动事件经Kinesis Data Stream传输至Lambda后的解密失败问题求助

AWS RDS数据库活动事件经Kinesis Data Stream传输至Lambda后的解密失败问题求助

问题概述

我正尝试解密从AWS RDS流到Kinesis再到Lambda函数的databaseActivityEvents数据,但无论怎么调整代码,解密操作始终返回InvalidCiphertextException: null错误,实在找不到问题所在,希望能得到大家的帮助。

背景与已完成操作

我已经完成了以下资源的配置,且整体数据流是通的:

  • 创建了新的Aurora数据库集群
  • 在KMS中创建了采用SYMMETRIC_DEFAULT类型的客户托管密钥
  • 使用上述KMS密钥创建了Kinesis数据流,并将其关联到Aurora集群,用于接收数据库活动事件
  • 创建了Lambda函数,由Kinesis数据流触发,目前能正常收到包含数据库事件(多为心跳)的JSON格式event数据

当前现象与代码尝试

1. 收到的Kinesis事件示例(脱敏处理后)

{
  "Records": [
    {
      "kinesis": {
        "kinesisSchemaVersion": "1.0",
        "partitionKey": "05841e02-874c-4628-b79e-1dcd5d73b256",
        "sequenceNumber": "49639037278219440985425171458121310232781924676881350674",
        "data": "eyJ0eXBlIjogIkRhdGFiYXNlQWN0aXZpdHlNb25pdG9yaW5nUmVjb3JkcyIsInZlcnNpb24iOiAiMS4yIiwiZGF0YWJhc2VBY3Rpdml0eUV2ZW50cyI6ICJBWUFEZUNiRTkzekFoU1ZXL2dBblRCSUdEeUFBWHdBQkFCVmhkM010WTNKNWNIUnZMWEIxWW14cFl5MXJaWGtBUkVGeVZta3lWMmxNT1ZSMVJtNXVlVlpMZURsb2MxWllMMWQyYjBwSFdWcDZjVEJOTjBSV1ptUnlRemNyV0dGTE5VWk5ia2wwYjNsT1dUQTRXbTUwTVhaUVFUMDlBQUVBQWtKREFCdEVZWFJoUzJWNUFBQUFnQUFBQUF6MHpuWU9FemV5VGczSWlkZ0FNUHlJTnVRbWJuQmpnMkRZNWt0TEx2WGM0cG5jejlqUkFTcTdZNldDVUxURHpnWkFRYnA2M0hlcmNYL1h1SzdZQkFJQUFBQUFEQUFFQUFBQUFBQUFBQUFBQUFBQUFBQkxubCsxWjZpaWVNTG1Pa21TSS80SC8vLy8vd0FBQUFFQUFBQUFBQUFBQUFBQUFBRUFBQUg2Qkx1czJ3ZEZxelk0cmpENWdaVDQwL21GNEQxbGxabTR3MkJxR2RMN3AwcVg3OXc0TStnVmNLU0FTNWRWb0N5OHFBVlpYRmx3YytKcVZjeWZ4bTdYOHhGL092Q1J5eE5sV2V5NGlKMjlpTU9JTlRLTWRreU84TWlsTm9NOHlmVk9Pb3FudkpBZ0U1Y1VUZjRyVm84WmRpdjBmQ0Q4NWdjUDZUMERRNTlycVNWQmYzQTdtbitHaUZ2LzQ0U1RzbGNwOERzKzFoS3BtYWx0YkxLTnkzN2dEd01IY2ZmbElkeE02S3Y5c1grMUNDdUthdVZ4R3VuM0t1T2MyQnFIQ0lnVGp0enhMMmR6OVpMLytpd1RaZk01cDZCaGlpTDZ0eExTbzBVRSt0NVNZa1pjZ2JRNThlSWozdktlenBnR0FYVXlSTkJDbzdXVkxObVpWQWRnQjJmdUdyaTIzL0phN3dOOEdQcnQ0bEpUdEVTdmJITGE5cUQ4em9JY0krVFcrS1pnMFl0MzVpWjZkaVNOcUdUQUVJcmkxdzVCSjFHaldoNnVHdHl0UGJteElPRkxOUHpLTXE2N2R0dXlLNlVTOFoxRXVzQ3dRQWpqQWVhQ0Nid2J1NDFkblRHMU1KYUI0R1I2Z3RGTDBURjMwdnpBMm1JVmwvZWVDRWdXOHEyQUJqNWV5VXB1UUNlRjRjUjNWUHR2REJnL2VyVjVyeFdVTUxCRGdFZTBkTlpBYWhjVkIzYStyLzBZUmhMVGZCZmoxcHQzcDg2L2JzTlg4a1VqRlBmY1ZLc3B0S2g3Z0twV3ZHZVZpNkxJUGpST1hjNjQ4cW5KYUh1UnV0L3lIY3lqN0VVN1IzdXNweTlhZzlLL1JlcHZXeTlxdGIyUmNLWk1HQjg3Q205eUJtZktyeEVKY25rbWpMTjJORjJ0QUdjd1pRSXhBS1VVbTJFeUExNUNPMzdTYTJpcHA2d3Nvc2xQcVNhRUZlMENRL3VjcnVaeUdIa3Y0c1VxWTRUdXhWa1puN0pUVEFJd1h6YmdYdE1YRldhMnh4U3ZBajhVUDFjVVBRZ2JUeWVTVzNCL244akNadXgwUnY0SWVrT0Y3V2htWnlzSjBISXkiLCJrZXkiIDogIkFRSURBSGhxV0dDdm45b2NQMVJ1a3pFS0xQald6T1ZMNkFzeTRSMllTbkZQNDdTT3l3RzNGMXd2VGhTUDJtTHk5RTBOS1VFcEFBQUFmakI4QmdrcWhraUc5dzBCQndhZ2J6QnRBZ0VBTUdnR0NTcUdTSWIzRFFFSEFUQWVCZ2xnaGtnQlpRTUVBUzR3RVFRTTJ6SWlEdUI5MWVpOUl6ekNBZ0VRZ0R1VDh5REhDWjB3THFjVjVQa25rYy9DZ0lvSmg5U1hxclBkeHBRRHhoMmYxVnJXeGRIdktsNDR0Zjg5QkJpMzlNWXVib1hJRDlzQTRGMkdWZz09In0=",
        "approximateArrivalTimestamp": 1679260829.009
      },
      "eventSource": "aws:kinesis",
      "eventVersion": "1.0",
      "eventID": "shardId-000000000001:49639037278219440985425171458121310232781924676881350674",
      "eventName": "aws:kinesis:record",
      "invokeIdentityArn": "arn:aws:iam::767437170311:role/lambda-admin",
      "awsRegion": "us-east-1",
      "eventSourceARN": "arn:aws:kinesis:us-east-1:767437170311:stream/aws-rds-das-cluster-6KXUII5RDIBDAE6U7EQLZST2YI"
    }
  ]
}

2. 解码Kinesis数据的代码

我先对Kinesis的data字段进行Base64解码并解析为JSON:

const raw = Buffer.from(record.kinesis.data, 'base64').toString('ascii')
const json = JSON.parse(raw)

解码后的JSON结构如下:

{
  type: 'DatabaseActivityMonitoringRecords',
  version: '1.2',
  databaseActivityEvents: 'AYADeCbE93zAhSVW/gAnTBIGDyAAXwABABVhd3MtY3J5cHRvLXB1YmxpYy1rZXkAREFyVmkyV2lMOVR1Rm5ueVZLeDloc1ZYL1d2b0pHWVp6cTBNN0RWZmRyQzcrWGFLNUZNbkl0b3lOWTA4Wm50MXZQQT09AAEAAkJDABtEYXRhS2V5AAAAgAAAAAz0znYOEzeyTg3IidgAMPyINuQmbnBjg2DY5ktLLvXc4pncz9jRASq7Y6WCULTDzgZAQbp63HercX/XuK7YBAIAAAAADAAEAAAAAAAAAAAAAAAAAABLnl+1Z6iieMLmOkmSI/4H/////wAAAAEAAAAAAAAAAAAAAAEAAAH6BLus2wdFqzY4rjD5gZT40/mF4D1llZm4w2BqGdL7p0qX79w4M+gVcKSAS5dVoCy8qAVZXFlwc+JqVcyfxm7X8xF/OvCRyxNlWey4iJ29iMOINTKMdkyO8MilNoM8yfVOOoqnvJAgE5cUTf4rVo8Zdiv0fCD85gcP6T0DQ59rqSVBf3A7mn+GiFv/44STslcp8Ds+1hKpmaltbLKNy37gDwMHcfflIdxM6Kv9sX+1CCuKauVxGun3KuOc2BqHCIgTjtzxL2dz9ZL/+iwTZfM5p6BhiiL6txLSo0UE+t5SYkZcgbQ58eIj3vKezpgGAXUyRNBCo7WVLNmZVAdgB2fuGri23/Ja7wN8GPrt4lJTtESvbHLa9qD8zoIcI+TW+KZg0Yt35iZ6diSNqGTAEIri1w5BJ1GjWh6uGtytPbmxIOFLNPzKMq67dtuyK6US8Z1EusCwQAjjAeaCCbwbu41dnTG1MJaB4GR6gtFL0TF30vzA2mIVl/eeCEgW8q2ABj5eyUpuQCeF4cR3VPtvDBg/erV5rxWUMLBDgEe0dNZAahcVB3a+r/0YRhLTfBfj1pt3p86/bsNX8kUjFPfcVKsptKh7gKpWvGeVi6LIPjROXc648qnJaHuRut/yHcyj7EU7R3uspy9ag9K/RepvWy9qtb2RcKZMGB87Cm9yBmfKrxEJcnkmjLN2NF2tAGcwZQIxAKUUm2EyA15CO37Sa2ipp6wsoslPqSaEFe0CQ/ucruZyGHkv4sUqY4TuxVkZn7JTTAIwXzbgXtMXFWa2xxSvAj8UP1cUPQgbTyeSW3B/n8jCZux0Rv4IekOF7WhmZysJ0HIy',
  key: 'AQIDAHhqWGCvn9ocP1RukzEKLPjWzOVL6Asy4R2YSnFP47SOywG3F1wvThSP2mLy9E0NKUEpAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM2zIiDuB91ei9IzzCAgEQgDuT8yDHCZ0wLqcV5Pknkc/CgIoJh9SXqrPdxpQDxh2f1VrWxdHvKl44tf89BBi39MYuboXID9sA4F2GVg=='
}

3. 解密尝试的代码(报错)

我尝试用以下代码解密databaseActivityEvents字段,但始终抛出InvalidCiphertextException:

const databaseActivityEvents = Buffer.from(json.databaseActivityEvents, 'base64')
const params = {
  KeyId: "c4d1dc19-ce04-4568-9863-d80ec0ff4c58",
  CiphertextBlob: databaseActivityEvents,
  EncryptionContext: {
    "aws:rds:dbc-id": "cluster-DFGNFSATIUGUYQA5DDCCJWTXCQ"
  }
}
const results = await kms.decrypt(params).promise()
console.log(results.Plaintext.toString('ascii'))

我试过包含或不包含EncryptionContext参数,结果都一样。

4. 正常运行的加密解密测试代码

为了验证KMS密钥和Lambda权限没问题,我写了一段测试代码,能正常完成加密和解密:

// 加密测试
let params = {
  KeyId: "c4d1dc19-ce04-4568-9863-d80ec0ff4c58",
  Plaintext: 'Test Ecrypt Me',
  EncryptionContext: {
    "Test": "EncryptionContext123"
  }
}
let results = await kms.encrypt(params).promise()
console.log(results.CiphertextBlob)

// 解密测试
params = {
  KeyId: "c4d1dc19-ce04-4568-9863-d80ec0ff4c58",
  CiphertextBlob: results.CiphertextBlob,
  EncryptionContext: {
    "Test": "EncryptionContext123"
  }
}
results = await kms.decrypt(params).promise()
console.log(results.Plaintext.toString('ascii'))

这段代码能正常输出加密后的Buffer和明文Test Ecrypt Me,说明KMS密钥本身和Lambda的KMS权限是正常的。

我的困惑

  • 我不知道Kinesis在传输数据时是否设置了EncryptionContext,也不清楚该如何查看它的具体值
  • 已经排查了密钥权限和基本的编码处理,还是找不到解密失败的原因

求助问题

请问我该如何正确解密databaseActivityEvents字段,以获取RDS实例的更新记录?


可能的解决方案

根据你的情况,我整理了几个可能的排查方向和解决方法:

  1. 确认EncryptionContext的正确值
    RDS在加密数据库活动流时,使用的EncryptionContext固定键为aws:rds:dbc-id,但值应该是数据库集群的资源ID,而不是你当前使用的集群名称。你可以通过以下方式获取:

    • AWS控制台:进入RDS集群详情页,查看“配置”标签下的“资源ID”
    • AWS CLI:执行aws rds describe-db-clusters --db-cluster-identifier <你的集群名称>,查看返回结果中的DbClusterResourceId字段
      把这个资源ID替换到EncryptionContext的值中再尝试解密。
  2. 移除解密参数中的KeyId
    解码后的JSON中的key字段是RDS用来加密数据的数据密钥(Data Key),KMS会自动通过这个数据密钥关联到对应的主密钥,所以解密时不需要手动指定KeyId参数,只需要传入CiphertextBlob和正确的EncryptionContext即可。

  3. 检查KMS密钥的密钥策略
    确保你的Lambda角色的ARN被添加到KMS密钥的密钥策略中,拥有kms:Decrypt权限。你可以在KMS控制台的密钥详情页“密钥策略”标签中查看和修改。

  4. 确认数据处理没有额外编码错误
    你当前对databaseActivityEvents的Base64解码是正确的,但可以再确认一下转换后的Buffer是否和原始密文一致,避免在解码过程

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 15:08:08