[ CloudFormation ] WaitCondition for race conditions in IAM templates

0

Hi,
I'm working on a template that allows to create a user, add it to any groups if need, tag it, add managed policies and in-line policies:

## =================== VERSION ===================  
AWSTemplateFormatVersion: '2010-09-09'  
  
## =================== DESCRIPTION ===================  
Description: >-  
  Creates an IAM User if none is present, optionally manage to which IAM group(s) the user belongs to  
  Optionally embed AWS managed policies, customer managed policies and inline policies in the user  
  
## =================== METADATA ===================  
Metadata:   
  AWS::CloudFormation::Interface:   
    ParameterGroups:   
      -  
        Label:  
          default: Set a one-time password   
        Parameters:  
          - paramOneTimePassword  
    ParameterLabels:  
      paramOneTimePassword:  
        default: ' '  
  
## =================== PARAMETERS ===================  
Parameters:  
  paramOneTimePassword:  
    Description: The user will have to pick a new password upon first sign in  
    Type: String      
    NoEcho: 'true' # mask the parameter value as asterisks (*****) to prevent it from being displayed in the console, CLI, or API  
    ConstraintDescription: Password must be between 8 and 32 characters, start with lowercase or uppercase letter, and can be alphanumeric with the following special characters !@#$%&  
  
## =================== MAPPINGS ===================  
Mappings:  
  mapUserData:  
    UserName:  
      AWS: testuser  
      Real: 'Test User'  
    Groups:  
      Group: BackendDev  
    Tags:  
      product: testProduct  
  mapManagedPolicies:  
    CustomerManagedPolicies:   
      ARN: None  
  
## =================== CONDITIONS ===================  
Conditions:  
  hasManagedPolicy:  
    !Not \[!Equals \[!FindInMap \[mapManagedPolicies, CustomerManagedPolicies, ARN], 'None'] ]  
   
## =================== RESOURCES ===================  
Resources:  
  myInlinePolicyForChangeOwnPassword:  
    Type: 'AWS::IAM::Policy'  
    Properties:  
      PolicyName: IAM-ChangeOwnPassword  
      PolicyDocument:  
        Version: '2012-10-17'  
        Statement:  
          - Effect: Allow  
            Sid: ViewAccountPasswordRequirements  
            Action: 'iam:GetAccountPasswordPolicy'  
            Resource: "*"  
          - Effect: Allow  
            Sid: ChangeOwnPassword  
            Action:  
              - 'iam:GetUser'  
              - 'iam:ChangePassword'  
            Resource: !Join \['', \[arn:aws:iam::*:user/,!FindInMap \[mapUserData, UserName, AWS]]]  
      Users:  
        - !FindInMap \[mapUserData, UserName, AWS]  
  myUser:  
    Type: 'AWS::IAM::User'  
    Properties:  
      UserName: !FindInMap \[mapUserData, UserName, AWS]  
      LoginProfile:  
        Password: !Ref paramOneTimePassword   
        PasswordResetRequired: true   
      Groups:  
        - !FindInMap \[mapUserData, Groups, Group]  
      ManagedPolicyArns: # list of ARNs of IAM managed policies that you want to attach to the user  
        - !If \[ hasManagedPolicy, !FindInMap \[mapManagedPolicies, CustomerManagedPolicies, ARN], !Ref "AWS::NoValue" ]  
      Tags:  
        - Key: name  
          Value: !FindInMap \[mapUserData, UserName, Real]  
        - Key: product  
          Value: !FindInMap \[mapUserData, Tags, product]  
  WaitCondition:  
    Type: AWS::CloudFormation::WaitCondition  
    DependsOn: myUser  
    Properties:  
      # Handle: !Ref WaitHandle  
      Timeout: 120  
      Count: 1  
  
## =================== OUTPUT ===================  
Outputs:  
  outputArn:  
    Description: User ARN  
    Value: !GetAtt myUser.Arn  
  outputName:  
    Description: User name  
    Value: !Ref myUser  

The problem tho is that there's a race condition when sometimes the user is quickly created, so the in-line policy can be correctly attached, but other times it pops.
I've read about the WaitCondition resource (and WaitConditionHandle), but I can't really find a way to make CF wait and evaluate the AWS::IAM::User resource before going ahead and trying to attach the inline policy.

I'm running out of ideas here, thoughts?

cig0
asked a year ago80 views
1 Answer
0

Solved! Please check here the answer if you're interested in learning how to add both managed and inline policies to a user at the moment of user creation (I'm pointing to an external resource since these forums don't do well with code formatting): https://devops.stackexchange.com/questions/14344/how-to-add-a-wait-condition-when-creating-iam-entities/14345#14345

cig0
answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions