Search code examples
amazon-web-servicesaws-cloudformationamazon-cloudwatchaws-secrets-manager

Referencing Secrets Manager secret in cloudFormation template


i have piece of cloudFormation code

"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": [
                "xxxxxxx",
                "Arn"
              ]
            },
            "Id": "xxxx",
            "Input": "{\"val1\":\"val1\",\"secretVal\":\"??????????????????\"}"
          }
        ]
      }
    }

the thing I want to accomplish, is passing Secrets Manager value to variable secretVal I tried to do this by setting secretVal value to {{resolve:secretsmanager:{arn of secret}:SecretString}}, but then on cloudWatch event I have optput like {"val1": "val1", "secretVal": "{{resolve:secretsmanager:{arn of secret}:SecretString}}"}

When I tried to set for example Name to {{resolve:secretsmanager:{arn of secret}:SecretString}}, then everything worked as it should, but with Input it just doesn't works. Do I do something wrong? Or maybe there is some other way of passing secret values to cloudWatch event body? Thanks from advance!


Solution

  • @RobS this wouldn't work in my use case anyways. the goal was to make normal api lambda for handling users requests also available to:

    -be invoked periodically based on fixed cron expression

    -be invoked by itself, but at some future point of time

    this key was just a protection from end users. as I get response from AWS, this is possible by making child CloudFormation stack

    Parent stack snippet

    "Resources": {
    
        "MySecretB": {
          "Type": "AWS::SecretsManager::Secret",
          "Properties": {
            "Name": "MySecretForAppA",
            "Description": "This secret has a hardcoded password in SecretString (use GenerateSecretString instead)",
            "SecretString": "{\"username\":\"MasterUsername\",\"password\":\"secret-password\"}"
          }
        },
        "Test": {
          "DependsOn" : "MySecretB",
          "Type": "AWS::CloudFormation::Stack",
          "Properties": {
            "Parameters": {
              "Key": {
                "Fn::Sub": ["${value1}", {
                  "value1": "{{resolve:secretsmanager:MySecretForAppA:SecretString:username}}"
                }]
              }
    
            },
            "TemplateURL" : "https://s3.amazonaws.com/mybucketname/childstack.json "
          }
        }
      }
    

    Child stack snippet

      "Parameters": {
            "Key":{
              "Type":"String"
            }
          },
          "Resources": {
            "ScheduledRule": {
                "Type": "AWS::Events::Rule",
                "Properties": {
                    "ScheduleExpression": "rate(1 minute)",
                    "Description": "ScheduledRule",
                    "Targets": [
                        {
                            "Arn": "arn:aws:lambda:us-east-1:380574440275:function:LambdaFunction",
                            "Id": "TargetFunctionV1",
                            "Input": {"Fn::Sub": "{\"Input\": \"${Key}\"}"}
                        }
                    ]
                }
            }
        }
    

    Like you told, passing a secret into a CW event is probably not a good idea, so I just made another lambda function, which is unavailable to end users. it's possible to invoke it only from cloudWatch events