12

We have multiple CloudFormation scripts to create our stack.

Now, we want to write (automate) new scripts which will be used just to updated 1 specific resource (business requirement).

The thing which i am stuck at is how to refer to an existing resource in my update script? I know there is REF function but i believe this is used just to refer resources with in the same script. Is there something that AWS provide to refer to an existing resource?

I have read that we can use parameters but is there any other option?

Em Ae
  • 221
  • 1
  • 2
  • 3

4 Answers4

9

I recently had to do this for some layered deployments which referenced shared services. In addition to parameters, here are some other options:

  1. Named exports: this is a good option if you have some resources which were created by a separate CloudFormation stack and you just want to reference them (e.g. an infrastructure admin sets up the lower-level portion for the application team to deploy on top of).

  2. Substitution: in many cases you might simply need to reference a well-known name which is constant but the ARN varies depending on the AWS account ID. You can use Fn::Sub to expand a few “pseudo-parameters” such as the account ID or region:

    "TaskRoleArn": { "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:role/YourSharedServiceTaskRole" }

  3. SSM parameters: you can have a dynamic reference which retrieves an SSM property. This is handy for being completely abstracted from the source of that value – it could be created by CloudFormation but could literally also be someone running a one-off command line script and it supports secure storage of passwords and other secrets which can be configured to prevent retrieval by anyone other than the target service (e.g. an EC2 / ECS IAM instance role) — for example, I used this to store SES credentials:

    aws ssm put-parameter --type String --name "/project/mail/EmailHost" --value email-smtp.us-east-1.amazonaws.com aws ssm put-parameter --type String --name "/project/mail/EmailUser" --value <SES_ACCESS_KEY> aws ssm put-parameter --type SecureString --key-id alias/your-well-known-iam-kms-alias --name "/project/mail/EmailPassword" --value <SES PASSWORD>`

  4. Macros: this was recently announced and is a very powerful mechanism where you can have a Lambda function which returns arbitrary JSON for inclusion in the template. That could do almost anything from provisioning extra resources which the CloudFormation stack creator doesn't have direct permission to create to looking up values in a database and returning a template configured with, for example, VPC CIDR allocations out of a larger reservation pool which is managed by the parent organization.

Chris Adams
  • 309
  • 2
  • 6
1

If you know names of your resource, you can build resource ARN by variables and names like this:

Queue: !Sub arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:alarms-queue-${Environment}
0

AWS uses ARNs (AWS Resource Name) to reference resources. Here is the general formatting:

arn:partition:service:region:account-id:resource arn:partition:service:region:account-id:resourcetype/resource arn:partition:service:region:account-id:resourcetype:resource

You can lookup more info http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html

Also you can lookup the specific ARN used by the resources you want to reference in their service documentation pages

Zero Subnet
  • 699
  • 2
  • 10
  • 29
  • 2
    Can you give an example in a CloudFormation definition? This is true in general, but If I have ```DomainName: { 'Fn::GetAtt': [ 'WebsiteBucket', 'DomainName' ] }``` and want to replace "WebsiteBucket" with an arn? – shaunc Jun 15 '18 at 07:39
  • 2
    This comment doesn't really attempt to address the question. Rather than explaining what an ARN is, it should have explained how to look them up in CloudFormation. – Chris Adams Sep 13 '18 at 13:32
  • This answer helped me to find the way: just build ARN from what you know like this: `Queue: !Sub arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:alarms-queue-${Environment}` – Jarda Pavlíček Dec 05 '20 at 10:47
0

Amazons CDK (currently in the stage of developer preview as of writing) offers a way import existing resources:

If you need to reference a resource, such as an Amazon S3 bucket or VPC, that's defined outside of your CDK app, you can use the Xxxx.import(...) static methods that are available on AWS constructs. For example, you can use the Bucket.import() method to obtain a BucketRef object, which can be used in most places where a bucket is required. This pattern enables treating resources defined outside of your app as if they are part of your app.

Source: https://docs.aws.amazon.com/CDK/latest/userguide/aws_construct_lib.html

It also allows to import existing CloudFormation templates: https://docs.aws.amazon.com/CDK/latest/userguide/use_cfn_template.html

I hope this helps.

karfau
  • 101
  • 2