Skip to content

Instantly share code, notes, and snippets.

@guss77
Last active February 18, 2022 15:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save guss77/2471e8789a644cac96992c4102936fb3 to your computer and use it in GitHub Desktop.
Save guss77/2471e8789a644cac96992c4102936fb3 to your computer and use it in GitHub Desktop.
Computed variables for CloudFormation using an identity function, as by @claude on StackOverflow (https://serverfault.com/a/812040/6438)
##
#
# Custom resource setup to provide an identity function that can be used to
# implement "custom variables".
# See: https://serverfault.com/a/812040/6438
#
# Usage:
#
# After deploying the below code to your stack, you can define computed
# variables thus:
# ```
# GlobalStackName:
# Type: Custom::Variable
# Properties:
# ServiceToken: !GetAtt [ IdentityFunc, Arn ]
# Value: !Join [ "-", [ { Ref: "AWS::StackName" }, { Ref: "AWS::Region" } ]]
# ```
# And use it like this:
#
# ```
# !GetAtt [ GlobalStackName, Value ]
# ```
# Any attribute name can be used instead of `Value` in the definition and fetched
# with the `GetAtt`. It may be useful to define all computed values in a single
# variable, each with its own attribute name.
#
# Its also possible to use such custom variables to resolve conditions to values, in which case
# pay attention to put the `Fn::If` as the top entry under `Properties`:
# ```
# ResolveConditionToValue:
# Type: Custom::Variable
# Properties:
# "Fn::If":
# - ConditionName
# - ServiceToken: { "Fn::GetAtt": [ IdentityFunc, Arn ] }
# Value: !Ref SomeParam
# - ServiceToken: { "Fn::GetAtt": [ IdentityFunc, Arn ] }
# Value: !Ref SomeOtherParam
# ```
# It may seem redundant, but if you do anything else, the `Fn::If` and its content will be sent as the value
# to the function instead of being resolved.
#
# Articles used in the construction of this snippet:
# * https://serverfault.com/a/812040/6438
# * https://github.com/arjenderijke/aws-cloud-examples/blob/master/cloudformation/python-custom-resource.template
# * https://blog.jayway.com/2015/07/04/extending-cloudformation-with-lambda-backed-custom-resources/
# * http://2ndwatch.com/blog/a-step-by-step-guide-on-using-aws-lambda-backed-custom-resources-with-amazon-cfts/
Resources:
IdentityFunc:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: >
var r = require('cfn-response');
exports.handler = function(ev, ctx) {
r.send(ev, ctx, r.SUCCESS, ev.ResourceProperties);
};
Handler: index.handler
Runtime: nodejs6.10
Timeout: 30
Role: !GetAtt [ IdentityFunctionExecutionRole, Arn ]
IdentityFunctionExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal: { Service: [ lambda.amazonaws.com ] }
Action: sts:AssumeRole
Policies:
- PolicyName:
Fn::Join: [ '-', [ identity-custom-res, { Ref: 'AWS::StackName' }, { Ref: 'AWS::Region' } ] ]
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "arn:aws:logs:*:*:*"
- Effect: Allow
Action: cloudformation:DescribeStacks
Resource: "arn:aws:cloudformation:*:*:*"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment