'Create role only if FindInMap value is present? / What to do if Mapping doesn't have values for some keys?
I have a role that I want to create only if there are entries for the given keys in the Mapping. The confusion comes when I have no values to put in for certain key / values (in this case, some regions don't have a value for "XClientPrincipals", so I get an error.
Example: The map:
alpha: ...
beta:
Region1:
YClientPrincipals:
- 'arn:aws:iam::#########:root'
Region3:
XClientPrincipals:
- 'arn:aws:iam::#########:root'
YClientPrincipals:
- 'arn:aws:iam::#########:root'
prod:
Region1:
YClientPrincipals:
- 'arn:aws:iam::#########:root'
Region2:
XClientPrincipals:
- 'arn:aws:iam::#########:root'
- 'arn:aws:iam::#########:root'
YClientPrincipals:
- 'arn:aws:iam::#########:root'
Region3:
XClientPrincipals:
- 'arn:aws:iam::#########:root'
- 'arn:aws:iam::#########:root'
YClientPrincipals:
- 'arn:aws:iam::#########:root'
The role:
# Role definition for LMSortPlanningWorkflow - https://issues.amazon.com/LMCP-3533
XClientRole:
Type: AWS::IAM::Role
Condition: IsBetaOrProd # Don't create external client roles in Alpha
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: 'sts:AssumeRole'
Effect: Allow
Principal:
AWS:
'Fn::FindInMap': [ { Ref: 'Domain' }, { Ref: 'Region' }, 'XClientPrincipals' ]
RoleName: { 'Fn::Sub': 'XClientRole' }
ManagedPolicyArns:
- Ref: SomeApiCallPolicy
The issue is that XClientPrincipals only applies to some Regions, and we only need to create the roles in those regions (and they're different between beta and prod). If I don't provide something in the map for every possible combination of domain and region we have, it will error when deploying for that domain + region because it can't find anything in the map. But if I specify an empty array for that domain + region, that's also an error because the principal needs a value. Is there a way to create a condition for only creating the role if it can find the value in the map first?
I'm pretty sure I could create a condition to only create the role and spell out acceptable domain and region values (1st and 2nd key) that should evaluate to true, but the actual mapping is a little more complicated than this, so it would be great to be able to just do a condition like:
RunLambdaInVPC:
Fn::Not: [ {Ref: FindInMap .... }, null]
but I don't think I've seen any examples of this or figured out a way to get something like this to work.
Solution 1:[1]
Yes, you can conditionally create resources based on the value of a certain mapping.
Here's an example that shows how the value of a region map can be used in a Condition, that can then be used to determine whether a resource should be created or not:
AWSTemplateFormatVersion: "2010-09-09"
Mappings:
RegionMap:
us-east-1:
"HVM64": "ami-0ff8a91507f77f867"
us-west-1:
"HVM64": "ami-0bdb828fd58c52235"
IsProdMapping:
us-east-1:
"prod": "True"
us-west-1:
"prod": "False"
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", HVM64]
InstanceType: t3.nano
SubnetId: !Ref Subnet
RootRole:
Type: 'AWS::IAM::Role'
Condition: CreateIAMRole
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: root
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: '*'
Resource: '*'
Conditions:
CreateIAMRole: !Equals
- !FindInMap [IsProdMapping, !Ref "AWS::Region", "prod"]
- "True"
Parameters:
VPC:
Type: AWS::EC2::VPC::Id
Description: The VPC where you want to deploy
Subnet:
Type: AWS::EC2::Subnet::Id
Description: The subnet where you want to deploy
If I deploy this template in us-east-1, RootRole is created.
If I deploy this template in us-west-1, RootRole is not created.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
