Referring to an existing resource in CF Template

Solution 1:

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.

Solution 2:

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}