aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 54 forks source link

SSM Dynamic Reference latest version #75

Closed Ricapar closed 3 years ago

Ricapar commented 5 years ago

1. AWS::CloudFormation::Stack-SSM Dynamic Referecnes

2. Scope of request

As documented here, CloudFormation supports resolving values out of SSM using the {{resolve:ssm:MyParamNameHere:1}} notation.

It is also documented that "You cannot currently specify that AWS CloudFormation use the latest version of a parameter."

I am requesting that we be able to support using the latest version of a parameter.

3. Expected behavior

This currently does not work:

{{resolve:ssm:MyParamNameHere:latest}}

Expected behavior: When something similar to the sample above is used within CloudFormation, it is able to resolve and use the latest value.

4. Suggest specific test cases

5. Helpful Links to speed up research and evaluation

AWS Documentation on Dynamic References: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html

6. Category

rahulgarg05 commented 3 years ago

The What's New post for this launch is available here - https://aws.amazon.com/about-aws/whats-new/2021/04/now-reference-latest-aws-systems-manager-parameter-values-in-aws-cloudformation-templates-without-specifying-parameter-versions/

craigataws commented 3 years ago

Feature has launched 🚀 ! Closing issue

whoDoneItAgain commented 3 years ago

Feature has launched 🚀 ! Closing issue

I think the feature may be bugged.

I've created many CFTs with a resource property value like:

BeginTime: !Sub '{{resolve:ssm:/${Region}/${BusinessUnit}/${Environment}/${AppName}/parameters/schedules/${SchBusinessUnit}/${SchRegion}/${SchEnvironment}/${SchAppName}/schedule-1/begin-time}}'

It resolves correctly on the initial deployment.

When I subsequently update the parameter in the parameter store and update the stack, it fails to update and gives the no update to be done error. I've tried with and without the !Sub by specifying the literal name of the parameter to resolve.

The documentation says under the SSM parameter section:

version An integer that specifies the version of the parameter to use. If you do not specify the exact version, CloudFormation uses the latest version of the parameter whenever you create or update the stack. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm

The announcement says:

If you choose not to specify the parameter versions in the template, CloudFormation will automatically fetch the latest parameter values from Parameter Store. https://aws.amazon.com/about-aws/whats-new/2021/04/now-reference-latest-aws-systems-manager-parameter-values-in-aws-cloudformation-templates-without-specifying-parameter-versions/

mikerochip commented 3 years ago

I think the feature may be bugged.

Not bugged, just counterintuitive. That's unfortunately how dynamic secret resolution has been working as well despite not having the version requirement for much longer than ssm. This was discussed earlier in the thread, but the TLDR is that because you're not changing anything about the template itself, it's not going to pick up your new value.

I already put in a feature request to provide an option to make secrets NOT work this way. You could upvote that if you want #369, you could create a new feature request for this case, or you could start specifying the version. None of the options are great, but that's all we have I'm afraid, unless you want to go with one of the many suggested work arounds that showed up in this thread over the last couple of years.

zdot commented 3 years ago

I was very excited, then immediately very disappointed, by this feature release. If I can't re-resolve dynamic references on subsequent stack updates, what's the point of being able to specify "latest" at all? If the reference won't ever update following the initial deployment, it's as good as pinned and might as well specify the version number.

We've been looking for a generic solution to passing variables between CloudFormation stacks for a number of years now, something along the lines of what @Ricapar laid out above. If stack B needs variables from stack A, it doesn't make sense to pass the values as parameters, because 1. we clutter the user interface, and 2. keeping the values in sync requires manual intervention or an extra layer of automation external to CloudFormation. Neither is ideal. So far we've explored:

  1. Stack Exports
  2. SSM Parameter Types
  3. SSM Resolve
  4. SecretsManager Resolve
  5. SSM / Secrets Manager + Custom Resource

Stack Exports

Stack exports allow you to publish variables from one stack and consume them in another. However, you can't update the exporting stack without deleting / decoupling the consumer stacks first (as @clayvan pointed out above). Our infrastructure needs updates, so this isn't going to work.

SSM Parameter Types

CloudFormation parameters with a AWS::SSM::Parameter::Value<Type> type do re-resolve the latest parameter values on subsequent updates, but suffer from a few problems: 1. It's not possible to resolve the value conditionally. This may not seem like a big deal, but it's fairly common for us to toggle infrastructure components based on configuration. If the component happens to need an SSM value, that value has to always exist, regardless of whether the template needs it or not. 2. the interface is cluttered with parameters that don't need to be visible to the end user, probably shouldn't be changed, and count towards the parameter limit.

Secrets Manager Resolve

Maybe we can use {{resolve:secretsmanager:MyVar}}? This already defaults to the latest version, same as {{resolve:ssm:MyVar}} does now. However, it suffers from the exact same problem; the value isn't re-resolved on subsequent updates. Additionally, it only resolves in certain contexts (to prevent plaintext data leaks), and doesn't support types (number, etc.), so it can't be used as a generic interface for passing template variables.

SSM / Secrets Manager + Custom Resource

In the end we often end up falling back to a generic custom resource that we use to retrieve and resolve SSM or Secrets Manager values inside of a template. This mostly works, but requires us to build and bundle extra code with the template, and of course the custom resource won't run unless I update the value of a RunMePlease attribute or change the logical ID.

So we've tried five different things, none of which do exactly what we want. I think this problem is the result of a natural progression for people who rely on CloudFormation for IaC and attempt to refactor their growing infrastructure in sane ways, and it makes sense to address it. I want to:

  1. Create both variables and secrets inside of template A
  2. Reference those variables and secrets inside of template B
  3. Re-resolve references on subsequent updates if unpinned
  4. Handle types, e.g. not explode if a resource attribute requires a number instead of a string
  5. Support conditional resolution, e.g. If("MyCondition", "resolve-this-only-if-true", "otherwise-default-value")
  6. Have the reference limit be separate from the parameter limit

It feels like all of the components needed to accomplish this are there.

skysb commented 3 years ago

Has this really been resolved as the official documentation still states that the version is required for secure string parameters? image

3r1co commented 2 years ago

Hello, just confirming that the documentation hasn't been updated, but the SSM resolution without version specification resolves to the latest version of the parameter in my Cloud Formation templates. This is indeed a very useful feature, but having the documentation up date would be very helpful.

rachfop commented 2 years ago

Docs are updated. Thanks!

3r1co commented 2 years ago

Hi Rachfop, thanks for the update. Could you please also update the according regular expression on top of the page? This one here should work: '{{resolve:ssm:[a-zA-Z0-9_.\-/]+(:\d+)?}}'

tavin commented 2 years ago

It seems the fix for this is incomplete. For example:

$ aws cloudformation deploy ...

An error occurred (ValidationError) when calling the CreateChangeSet operation: Template error: parameter AppHostImageId should not contain ssm versionless resolver

This comes from the following snippet in the Parameters:

AppHostImageId:
  Type: String
  Default: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'

I would expect (and I need) the "versionless" resolution to work for a parameter default the same as elsewhere in a template.

Should this be reopened? Is there perhaps another open issue tracking this behavior?

Thanks.

NaveenTanguduTR commented 1 year ago

How to dynamically resolve the SSM parameters which are different for environment and regions I tried like this. !Sub '{{resolve:ssm:${SearchWritePassword}}}' and !Ref {{resolve:ssm-secure:${SearchWritePassword}}} , '{{resolve:ssm-secure:${SearchWritePassword}}}' .

StanForever commented 6 months ago

I'm facing similar issue what @tavin is facing. Any update on this or are we tracking this somewhere else?