Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one escape policy variables in AWS CloudFormation YAML templates

I have been trying to write a number of my AWS CloudFormation templates in the YAML format.

I have been having issues with CloudFormation trying to parse IAM policy variables, such as ${aws:username}, in conjunction with substitutions. An example is the following:

CommonUserGroup:
  Type: AWS::IAM::Group
  Properties:
    GroupName: Common
    Path: /project/
    Policies:
      - PolicyName: ClusterPolicy
        PolicyDocument:
          Version: 2012-10-17
          Statement:
            - Effect: Allow
              Action: "iam:GetAccountPasswordPolicy"
              Resource: "*"
            - Effect: Allow
              Action: "iam:ChangePassword"
              Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:user/${aws:username}'

When the CloudFormation template is used to try and create a stack the following error is returned:

Template validation error: Template format error: Unresolved resource dependencies [aws:username] in the Resources block of the template

If I manually specify the username, rather than using a policy variable, like:

'arn:aws:iam::${AWS::AccountId}:user/bob'

Then the error goes away.

Is there a way that one can escape policy variables such that CloudFormation doesn't try and parse them as part of the template?

like image 443
PicoutputCls Avatar asked Apr 06 '18 09:04

PicoutputCls


1 Answers

After a bit of searching I came across the following Reddit post which mentions the same problem: Creating No MFA No Access policy via YAML template - substitution issues

A reply to this thread referenced the following AWS CloudFormation documentation: Filter View: Fn::Sub, which states:

To write a dollar sign and curly braces (${}) literally, add an exclamation point (!) after the open curly brace, such as ${!Literal}. AWS CloudFormation resolves this text as ${Literal}.

This can be used to escape policy variables.

So in the example in my question, ${aws:username} can be escaped in the YAML as ${!aws:username}.

like image 97
PicoutputCls Avatar answered Oct 09 '22 00:10

PicoutputCls