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

CloudFormation中CloudWatch事件Input引用Secrets Manager密钥失败求助

Why the Secrets Manager Resolve Expression Isn't Working in CloudWatch Events Rule's Input

The issue here is that CloudFormation dynamic references (like {{resolve:secretsmanager:...}}) only work for top-level resource properties, not nested string values like the Input field inside the Targets array. When you use the resolve expression in the Name field (a top-level property), CloudFormation parses it during stack creation/update. But for nested string properties like Input, CloudFormation treats the entire string as literal text, so the resolve expression doesn't get evaluated.

Solutions to Pass Secrets to CloudWatch Event Body

This is the most secure and reliable approach. Instead of directly triggering your target resource from the CloudWatch Events Rule, have the rule invoke a Lambda function. The Lambda can fetch the secret from Secrets Manager, construct the required input payload, and then call your target service.

Here's a simplified adjustment to your CloudFormation template:

"dareMeXDevCloudwatchMissingPayoutsJob": {
  "Type": "AWS::Events::Rule",
  "DependsOn": [ "xxx" ],
  "Properties": {
    "Description": "xxxxx",
    "RoleArn": { "Fn::GetAtt": [ "xxxxx", "Arn" ] },
    "Name": "xxxxx",
    "ScheduleExpression": "cron(0 8 ? * 6 *)",
    "State": "ENABLED",
    "Targets": [ {
      "Arn": { "Fn::GetAtt": [ "YourLambdaFunction", "Arn" ] },
      "Id": "LambdaTarget",
      "Input": "{\"val1\":\"val1\"}"
    } ]
  }
}

And a sample Node.js Lambda implementation to handle the secret fetching:

const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();
const lambda = new AWS.Lambda();

exports.handler = async (event) => {
  // Fetch secret from Secrets Manager
  const secretResponse = await secretsManager.getSecretValue({
    SecretId: 'your-secret-arn-or-name'
  }).promise();
  const secretVal = JSON.parse(secretResponse.SecretString).yourSecretKey;

  // Build payload with the resolved secret
  const payload = {
    val1: event.val1,
    secretVal: secretVal
  };

  // Invoke your original target service
  await lambda.invoke({
    FunctionName: 'your-original-target-function',
    Payload: JSON.stringify(payload)
  }).promise();

  return { statusCode: 200 };
};

2. Use Fn::Sub with Dynamic Reference (Less Secure)

If you must pass the secret directly in the event input (note: this exposes the secret in CloudWatch Event logs), you can use Fn::Sub to embed the resolved secret value into the Input string. CloudFormation will evaluate the dynamic reference when processing the Fn::Sub function.

Adjust your Targets section like this:

"Targets": [ {
  "Arn": { "Fn::GetAtt": [ "xxxxxxx", "Arn" ] },
  "Id": "xxxx",
  "Input": {
    "Fn::Sub": "{\"val1\":\"val1\",\"secretVal\":\"${resolve:secretsmanager:arn-of-your-secret:SecretString}\"}"
  }
} ]

Critical Security Warning: The resolved secret will be visible in the CloudWatch Events console, event history, and any logs that capture the event payload. This is not recommended for sensitive secrets.

Key Takeaway

The top-level vs nested property limitation is a CloudFormation constraint. For sensitive data, always use a Lambda middle layer to avoid exposing secrets in event logs or stack outputs.

内容的提问来源于stack exchange,提问作者Piekarski D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:41:46