πŸš€ Exciting Day 3 of My AWS DevOps Engineer Professional Journey! πŸš€

Nirav RaychuraNirav Raychura
16 min read

Welcome back to the next chapter of my AWS DevOps certification adventure! Day 3 was a deep dive into the powerful world of AWS CloudFormation, and I'm thrilled to share the wealth of knowledge acquired.

πŸ“š Course Progress - Day 3: AWS CloudFormation Deep Dive! πŸ’»πŸŒ

Continuing my AWS DevOps certification journey with the invaluable guidance of StΓ©phane Maarek's Udemy course, Day 3 marked an in-depth exploration into the powerful realm of AWS CloudFormation.

πŸ’‘ AWS CloudFormation Overview:

  • Unveiled the fundamental concepts behind AWS CloudFormation, understanding its role in orchestrating and managing AWS resources.

AWS CloudFormation is a service that helps you model and set up your Amazon Web Services resources so that you can spend less time managing those resources and more time focusing on your applications that run in AWS. You create a template that describes all the AWS resources that you want, and AWS CloudFormation takes care of provisioning and configuring those resources for you. You don’t need to individually create and configure AWS resources and figure out what’s dependent on what; AWS CloudFormation handles all of that for you.

πŸ› οΈ Creating CloudFormation Stack:

  • Explored the step-by-step process of creating a CloudFormation stack, laying the foundation for automated resource provisioning.

To create a stack, you run the aws cloudformation create-stack command. You must provide the stack name, the location of a valid template, and any input parameters. Parameters are separated with a space and the key names are case sensitive. If you mistype a parameter key name when you run aws cloudformation create-stack, AWS CloudFormation doesn’t create the stack and reports that the template doesn’t contain that parameter. You can use your own bucket and manage its permissions by manually uploading templates to either Amazon S3 or AWS Systems Manager. Then whenever you create or update a stack, specify the Amazon S3 or AWS Systems Manager of a template file. By default, aws cloudformation describe-stacks returns parameter values. To prevent sensitive parameter values such as passwords from being returned, include a NoEcho property set to TRUE in your AWS CloudFormation template.

🚫 Deleting and Updating Stacks:

  • Learned the intricacies of deleting and updating CloudFormation stacks, ensuring a smooth management process.

To delete a stack, you run the aws cloudformation delete-stack command. You must provide the stack name. To update a stack, you run the aws cloudformation update-stack command. You must provide the stack name, the location of a valid template, and any input parameters. Parameters are separated with a space and the key names are case sensitive.

Note: You can also Create, Update & Delete Stacks via AWS Management Console.

πŸ“ YAML Crash Course:

  • Provided a YAML crash course with sample files, empowering readers to grasp the essentials of writing YAML for CloudFormation templates.

YAML is a human-readable data serialization format. It is often used for configuration files and data exchange between languages that are not natively compatible. Here is a sample YAML file that you can use to learn how to write YAML:

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  MyBucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: my-bucket-name
      AccessControl: PublicRead

🧱 CloudFormation Resources:

  • Explored the concept of resources in CloudFormation, understanding how they represent the building blocks of your infrastructure.

In AWS CloudFormation, a resource is an AWS entity that you can create, modify, or delete as a single unit in a CloudFormation stack. AWS CloudFormation provides a number of built-in resource types, such as Amazon EC2 instances, Amazon RDS database instances, and Amazon S3 buckets. You can also create custom resources.

Here is an example YAML file for learning CloudFormation Resources.

Parameters:
  S3BucketName:
    Type: String
    Description: "S3 bucket to create"
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9_-]*"

Resources:
  SampleS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref S3BucketName
    DeletionPolicy: Delete

  S3CustomResource:
    Type: Custom::S3CustomResource
    Properties:
      ServiceToken: !GetAtt AWSLambdaFunction.Arn
      bucket_name: !Ref SampleS3Bucket    ## Additional parameter here

  AWSLambdaFunction:
     Type: AWS::Lambda::Function
     Properties:
       Description: "Empty an S3 bucket!"
       FunctionName: !Sub '${AWS::StackName}-${AWS::Region}-lambda'
       Handler: index.handler
       Role: !GetAtt AWSLambdaExecutionRole.Arn
       Timeout: 360
       Runtime: python3.8
       Code:
         ZipFile: |
          import boto3
          import cfnresponse
          ### cfnresponse module help in sending responses to CloudFormation
          ### instead of writing your own code

          def handler(event, context):
              # Get request type
              the_event = event['RequestType']        
              print("The event is: ", str(the_event))

              response_data = {}
              s3 = boto3.client('s3')

              # Retrieve parameters (bucket name)
              bucket_name = event['ResourceProperties']['bucket_name']

              try:
                  if the_event == 'Delete':
                      print("Deleting S3 content...")
                      b_operator = boto3.resource('s3')
                      b_operator.Bucket(str(bucket_name)).objects.all().delete()

                  # Everything OK... send the signal back
                  print("Execution succesfull!")
                  cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
              except Exception as e:
                  print("Execution failed...")
                  print(str(e))
                  response_data['Data'] = str(e)
                  cfnresponse.send(event, context, cfnresponse.FAILED, response_data)

  AWSLambdaExecutionRole:
     Type: AWS::IAM::Role
     Properties:
       AssumeRolePolicyDocument:
         Statement:
         - Action:
           - sts:AssumeRole
           Effect: Allow
           Principal:
             Service:
             - lambda.amazonaws.com
         Version: '2012-10-17'
       Path: "/"
       Policies:
       - PolicyDocument:
           Statement:
           - Action:
             - logs:CreateLogGroup
             - logs:CreateLogStream
             - logs:PutLogEvents
             Effect: Allow
             Resource: arn:aws:logs:*:*:*
           Version: '2012-10-17'
         PolicyName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambda-CW
       - PolicyDocument:
           Statement:
           - Action:
             - s3:PutObject
             - s3:DeleteObject
             - s3:List*
             Effect: Allow
             Resource:
             - !Sub arn:aws:s3:::${SampleS3Bucket}
             - !Sub arn:aws:s3:::${SampleS3Bucket}/*
           Version: '2012-10-17'
         PolicyName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambda-S3
       RoleName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambdaExecutionRole

πŸ”„ CloudFormation Parameters:

  • Dived into CloudFormation parameters, allowing for dynamic input and customization during stack creation.

AWS CloudFormation parameters enable you to pass values into your AWS CloudFormation stack at runtime. You can use parameters to customize your stack and make it more reusable.

πŸ—ΊοΈ CloudFormation Mappings:

  • Unpacked CloudFormation mappings, facilitating the association of key-value pairs based on input parameters.

AWS CloudFormation mappings enable you to create a lookup table of keys and associated values that you can use to specify conditional parameter values, resource property values, and output values.

πŸ’Ό CloudFormation Outputs:

  • Explored CloudFormation outputs, understanding their significance in exposing information from the stack.

AWS CloudFormation outputs enable you to export information about the resources in your stack to other stacks or to view them in the AWS Management Console.

πŸ” CloudFormation Conditions:

  • Delved into CloudFormation conditions, enabling the creation of conditional resources based on specific criteria.

AWS CloudFormation conditions enable you to control whether certain resources are created or whether certain resource properties are assigned a value during stack creation or update.

πŸ”„ CloudFormation Intrinsic Functions:

  • Explored CloudFormation intrinsic functions, offering dynamic and flexible options within templates.

AWS CloudFormation intrinsic functions enable you to assign values to properties that are not available until runtime, such as the Amazon EC2 instance ID or the Amazon S3 bucket name.

↩️ CloudFormation Rollback:

  • Understood CloudFormation rollback mechanisms, ensuring reliable and controlled deployments.

AWS CloudFormation rollback enables you to automatically roll back to a previous version of your stack if the update fails.

πŸ”„ CloudFormation Drift:

  • Examined CloudFormation drift detection, allowing for the identification of resource configuration changes.

AWS CloudFormation drift detection enables you to detect whether the actual configuration of a stack differs, or has drifted, from its expected configuration.

πŸ“œ CloudFormation Stack Policies:

  • Unveiled CloudFormation stack policies, providing granular control over updates to stack resources.

AWS CloudFormation stack policies enable you to prevent updates to specific resources in a stack.

πŸ”„ Nested Stacks:

  • Explored the concept of nested stacks, facilitating the modularization of complex infrastructure.

AWS CloudFormation nested stacks enable you to create stacks within stacks

πŸ”„ CloudFormation Change Sets:

  • Dived into CloudFormation change sets, enabling preview and execution of proposed changes before implementation.

AWS CloudFormation change sets enable you to preview the changes to your stack before you apply them.

🚫 Deletion Policy:

  • Learned about CloudFormation deletion policies, managing resources during stack deletion.

AWS CloudFormation deletion policy enables you to specify how AWS CloudFormation handles the deletion of resources.

πŸ›‘οΈ Termination Protection:

  • Explored CloudFormation termination protection, preventing accidental deletion of critical stacks.

AWS CloudFormation termination protection enables you to prevent a stack from being accidentally deleted.

πŸ–₯️ EC2 UserData in CloudFormation:

  • Delved into EC2 UserData in CloudFormation, allowing for the customization of instances during launch.

AWS CloudFormation EC2 user data enables you to run scripts or commands on an Amazon EC2 instance during launch.

πŸ“œ Overview of CloudFormation CNF-init:

  • Explored CloudFormation CNF-init, understanding its role in initializing and configuring instances.

You can use the cfn-init command to read template metadata from the AWS::CloudFormation::Init key and act accordingly to fetch and parse metadata from CloudFormation, install packages, write files to disk, enable/disable, and start/stop services. You can also use cfn-init to update an existing file, create a backup copy of the original file in the same directory with a .bak extension, and produce two files: the original file’s contents and the updated contents.

To check if all the stages of user data are completed or not, you can use the cfn-signal command. This command sends a signal to AWS CloudFormation that indicates whether the instance has been successfully configured. If the instance is successfully configured, the cfn-signal command returns a success signal. If the instance is not successfully configured, the cfn-signal command returns a failure signal.

Here are the four stages of AWS CloudFormation CNF-init:

  • cfn-init: This command reads template metadata from the AWS::CloudFormation::Init key and acts accordingly to fetch and parse metadata from CloudFormation, install packages, write files to disk, enable/disable, and start/stop services. You can use CNF-init to run scripts or commands on an Amazon EC2 instance during launch.

  • cfn-signal: This command sends a signal to AWS CloudFormation that indicates whether the instance has been successfully configured . If the instance is successfully configured, the cfn-signal command returns a success signal. If the instance is not successfully configured, the cfn-signal command returns a failure signal.

  • cfn-hup: This command is used to detect changes to the metadata on an Amazon EC2 instance and to trigger actions based on those changes. You can use cfn-hup to monitor changes to the metadata and to perform actions such as updating configuration files or restarting services.

  • cfn-get-metadata: A wrapper script making it easy to retrieve either all metadata defined for a resource or path to a specific key or subtree of resource metadata.

Here is an example YAML file for learning how it works.

AWSTemplateFormatVersion: '2010-09-09'
Description: AWS CloudFormation Sample Template for CFN Init
Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instances
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.

  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.

  MyS3BucketName:
    Description: Name of an existing bucket to download files from
    Type: String

  ImageId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

Resources:
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80 and SSH access via port 22
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: !Ref SSHLocation

  WebServerHost:
    Type: AWS::EC2::Instance
    Metadata:
      Comment: Install a simple PHP application
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
              php: []
          groups:
            apache: {}
          users:
            "apache":
              groups:
                - "apache"
          sources:
            "/home/ec2-user/aws-cli": "https://github.com/aws/aws-cli/tarball/master"
          files:
            "/tmp/cwlogs/apacheaccess.conf":
              content: !Sub |
                [general]
                state_file= /var/awslogs/agent-state
                [/var/log/httpd/access_log]
                file = /var/log/httpd/access_log
                log_group_name = ${AWS::StackName}
                log_stream_name = {instance_id}/apache.log
                datetime_format = %d/%b/%Y:%H:%M:%S
              mode: '000400'
              owner: apache
              group: apache
            "/var/www/html/index.php":
              content: !Sub |
                <?php
                echo '<h1>AWS CloudFormation sample PHP application for ${AWS::StackName}</h1>';
                ?>
              mode: '000644'
              owner: apache
              group: apache
            "/etc/cfn/cfn-hup.conf":
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
              mode: "000400"
              owner: "root"
              group: "root"
            "/etc/cfn/hooks.d/cfn-auto-reloader.conf":
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.WebServerHost.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerHost --region ${AWS::Region}
              mode: "000400"
              owner: "root"
              group: "root"
            # Fetch a webpage from a private S3 bucket
            "/var/www/html/webpage.html":
              source: !Sub "https://${MyS3BucketName}.s3.${AWS::Region}.amazonaws.com/webpage.html"
              mode: '000644'
              owner: apache
              group: apache
              authentication: S3AccessCreds
          commands:
            test:
              command: "echo \"$MAGIC\" > test.txt"
              env:
                MAGIC: "I come from the environment!"
              cwd: "~"
          services:
            sysvinit:
              httpd:
                enabled: 'true'
                ensureRunning: 'true'
              postfix:
                enabled: 'false'
                ensureRunning: 'false'
              cfn-hup:
                enable: 'true'
                ensureRunning: 'true'
                files:
                  - "/etc/cfn/cfn-hup.conf"
                  - "/etc/cfn/hooks.d/cfn-auto-reloader.conf"
      AWS::CloudFormation::Authentication:
        # Define S3 access credentials
        S3AccessCreds:
          type: S3
          buckets:
            - !Sub ${MyS3BucketName}
          roleName: !Ref InstanceRole
    CreationPolicy:
      ResourceSignal:
        Timeout: PT15M

    Properties:
      ImageId: !Ref ImageId
      KeyName: !Ref KeyName
      InstanceType: t2.micro
      IamInstanceProfile: !Ref InstanceProfile # Reference Instance Profile
      SecurityGroups:
      - !Ref WebServerSecurityGroup
      UserData:
        Fn::Base64:
          !Sub |
            #!/bin/bash -xe

            # Get the latest CloudFormation helper scripts
            yum install -y aws-cfn-bootstrap

            # Start cfn-init
            /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerHost --region ${AWS::Region}

            # cfn-init completed so signal success or not
            /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerHost --region ${AWS::Region}


  InstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: 'sts:AssumeRole'
            Principal:
              Service: ec2.amazonaws.com
            Effect: Allow
            Sid: ''
      Policies:
        - PolicyName: AuthenticatedS3GetObjects
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - 's3:GetObject'
                Resource: !Sub 'arn:aws:s3:::${MyS3BucketName}/*'
                Effect: Allow

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref InstanceRole

Outputs:
  InstanceId:
    Description: The instance ID of the web server
    Value:
      !Ref WebServerHost
  WebsiteURL:
    Value:
      !Sub 'http://${WebServerHost.PublicDnsName}'
    Description: URL for newly created LAMP stack
  PublicIP:
    Description: Public IP address of the web server
    Value:
      !GetAtt WebServerHost.PublicIp

πŸ”„ Continue Rollingback and Update:

  • Understood the continuation of rollback and update processes in CloudFormation.

AWS CloudFormation continue rollback and update enables you to continue rolling back or updating a stack even if one or more resources in the stack fail to create or update. This feature enables you to recover from failed stack updates more easily and reduces the risk of downtime.

πŸ”„ Custom Resources in CloudFormation:

  • Explored the creation and utilization of custom resources, enhancing template flexibility.

AWS CloudFormation custom resources enable you to write custom provisioning logic in AWS Lambda functions and use them in your CloudFormation templates. You can use custom resources to create, modify, or delete resources that are not available as CloudFormation resource types.

πŸ§‘β€πŸ”§ CloudFormation Service Role:

  • Gained insights into CloudFormation service roles, defining the permissions required for stack operations.

AWS CloudFormation service role is an AWS Identity and Access Management (IAM) role that AWS CloudFormation assumes when it creates or updates resources in your stack. The service role enables AWS CloudFormation to perform actions on your behalf, such as creating or deleting Amazon S3 buckets or launching Amazon EC2 instances.

πŸ” CloudFormation SSM Parameters:

  • Understood the integration of AWS Systems Manager (SSM) parameters within CloudFormation.

AWS CloudFormation SSM parameters enable you to store and manage configuration data for your applications and services. You can use SSM parameters to store secrets, such as database passwords, and other configuration data, such as the IP addresses of your Amazon EC2 instances.

Here is an example YAML file to learn SSM Perameters.

Parameters:
  InstanceType:
    Description: WebServer EC2 instance type
    Type: AWS::SSM::Parameter::Value<String>
    Default: /dev/ec2/instanceType

  ImageId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

Resources:
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref InstanceType
      ImageId: !Ref ImageId

πŸ”„ CloudFormation Dynamic Reference:

  • Delved into CloudFormation dynamic references, enabling dynamic retrieval of parameter values.

AWS CloudFormation dynamic references enable you to reference values that are not available until runtime, such as the Amazon EC2 instance ID or the Amazon S3 bucket name.

Here is an example of how to use Dynamic Reference.

Parameters:
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instances
  ImageId: # Public SSM Paramater
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

Resources:
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      KeyName: !Ref KeyName
      # ssm dynamic reference
      InstanceType: '{{resolve:ssm:/ec2/instanceType:1}}'

  MyIAMUser:
    Type: AWS::IAM::User
    Properties:
      UserName: 'sample-user'
      LoginProfile:
        # ssm-secure dynamic reference (latest version)
        Password: '{{resolve:ssm-secure:/iam/userPassword}}'

  MyDBInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      DBInstanceClass: db.t2.micro
      Engine: mysql
      AllocatedStorage: "20"
      VPCSecurityGroups:
      - !GetAtt [DBEC2SecurityGroup, GroupId]
      # secretsmanager dynamic reference
      MasterUsername: '{{resolve:secretsmanager:MyRDSSecret:SecretString:username}}'
      MasterUserPassword: '{{resolve:secretsmanager:MyRDSSecret:SecretString:password}}'

  DBEC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: 'Allow access from anywhwere to database'
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 3306
        ToPort: 3306
        CidrIp: "0.0.0.0/0"

🌐 CloudFormation Stack Sets:

  • Explored CloudFormation stack sets, simplifying the management of stacks across multiple accounts and regions.

AWS CloudFormation stack sets enable you to create, update, or delete stacks across multiple accounts and regions with a single CloudFormation template. Stack sets enable you to manage your infrastructure at scale and reduce the time and effort required to deploy changes across your organization.

🌐 How to create Stack Sets:

To create a stack set, you can use the AWS Management Console or the AWS CLI. Here are the high-level steps to create a stack set:

  1. Create a CloudFormation template that you want to use to create stacks.

  2. Specify the target accounts in which you want to create stacks.

  3. Identify the AWS Regions in which you want to deploy stacks in your target accounts.

  4. Create the stack set using the create-stack-set command in the AWS CLI.

    You can create a stack set with either self-managed or service-managed permissions. With self-managed permissions, you can deploy stack instances to specific AWS accounts in specific Regions. With service-managed permissions, you can deploy stack instances to any AWS account in which you have permission to create an IAM role.

πŸ”„ Finding Stack Set Drifts:

  • Learned how to detect drifts in CloudFormation stack sets, ensuring consistent configurations.

To find stack set drifts, you can use the describe-stack-set-operation command. This command returns information about the status of a stack set operation, including any drift detection results.

🚫 Deleting Stack Sets:

  • Explored the process of deleting CloudFormation stack sets when they are no longer needed.

To delete a stack set, you can use the delete-stack-set command. This command deletes the specified stack set and all associated stack instances.

I am giving you 3 YAML files to learn Stack sets. Refer it and see how everything works.

  1. This is Stack Set
AWSTemplateFormatVersion: 2010-09-09
Description: Enable AWS Config

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Recorder Configuration
        Parameters:
          - AllSupported
          - IncludeGlobalResourceTypes
          - ResourceTypes
      - Label:
          default: Delivery Channel Configuration
        Parameters:
          - DeliveryChannelName
          - Frequency
      - Label:
          default: Delivery Notifications
        Parameters:
          - TopicArn
          - NotificationEmail
    ParameterLabels:
      AllSupported:
        default: Support all resource types
      IncludeGlobalResourceTypes:
        default: Include global resource types
      ResourceTypes:
        default: List of resource types if not all supported
      DeliveryChannelName:
        default: Configuration delivery channel name
      Frequency:
        default: Snapshot delivery frequency
      TopicArn:
        default: SNS topic name
      NotificationEmail:
        default: Notification Email (optional)

Parameters:
  AllSupported:
    Type: String
    Default: True
    Description: Indicates whether to record all supported resource types.
    AllowedValues:
      - True
      - False

  IncludeGlobalResourceTypes:
    Type: String
    Default: True
    Description: Indicates whether AWS Config records all supported global resource types.
    AllowedValues:
      - True
      - False

  ResourceTypes:
    Type: List<String>
    Description: A list of valid AWS resource types to include in this recording group, such as AWS::EC2::Instance or AWS::CloudTrail::Trail.
    Default: <All>

  DeliveryChannelName:
    Type: String
    Default: <Generated>
    Description: The name of the delivery channel.

  Frequency:
    Type: String
    Default: 24hours
    Description: The frequency with which AWS Config delivers configuration snapshots.
    AllowedValues:
      - 1hour
      - 3hours
      - 6hours
      - 12hours
      - 24hours

  TopicArn:
    Type: String
    Default: <New Topic>
    Description: The Amazon Resource Name (ARN) of the Amazon Simple Notification Service (Amazon SNS) topic that AWS Config delivers notifications to.

  NotificationEmail:
    Type: String
    Default: <None>
    Description: Email address for AWS Config notifications (for new topics).

Conditions:
  IsAllSupported: !Equals
    - !Ref AllSupported
    - True
  IsGeneratedDeliveryChannelName: !Equals
    - !Ref DeliveryChannelName
    - <Generated>
  CreateTopic: !Equals
    - !Ref TopicArn
    - <New Topic>
  CreateSubscription: !And
    - !Condition CreateTopic
    - !Not
      - !Equals
        - !Ref NotificationEmail
        - <None>

Mappings:
  Settings:
    FrequencyMap:
      1hour   : One_Hour
      3hours  : Three_Hours
      6hours  : Six_Hours
      12hours : Twelve_Hours
      24hours : TwentyFour_Hours

Resources:

  ConfigBucket:
    DeletionPolicy: Retain
    Type: AWS::S3::Bucket

  ConfigBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref ConfigBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: AWSConfigBucketPermissionsCheck
            Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
            Action: s3:GetBucketAcl
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}"
          - Sid: AWSConfigBucketDelivery
            Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
            Action: s3:PutObject
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}/AWSLogs/${AWS::AccountId}/*"

  ConfigTopic:
    Condition: CreateTopic
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub "config-topic-${AWS::AccountId}"
      DisplayName: AWS Config Notification Topic

  ConfigTopicPolicy:
    Condition: CreateTopic
    Type: AWS::SNS::TopicPolicy
    Properties:
      Topics:
        - !Ref ConfigTopic
      PolicyDocument:
        Statement:
          - Sid: AWSConfigSNSPolicy
            Action:
              - sns:Publish
            Effect: Allow
            Resource: !Ref ConfigTopic
            Principal:
              Service:
                - config.amazonaws.com

  EmailNotification:
    Condition: CreateSubscription
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: !Ref NotificationEmail
      Protocol: email
      TopicArn: !Ref ConfigTopic

  ConfigRecorderRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AWS_ConfigRole"

  ConfigRecorder:
    Type: AWS::Config::ConfigurationRecorder
    DependsOn:
      - ConfigBucketPolicy
    Properties:
      RoleARN: !GetAtt ConfigRecorderRole.Arn
      RecordingGroup:
        AllSupported: !Ref AllSupported
        IncludeGlobalResourceTypes: !Ref IncludeGlobalResourceTypes
        ResourceTypes: !If
          - IsAllSupported
          - !Ref AWS::NoValue
          - !Ref ResourceTypes

  ConfigDeliveryChannel:
    Type: AWS::Config::DeliveryChannel
    DependsOn:
      - ConfigBucketPolicy
    Properties:
      Name: !If
        - IsGeneratedDeliveryChannelName
        - !Ref AWS::NoValue
        - !Ref DeliveryChannelName
      ConfigSnapshotDeliveryProperties:
        DeliveryFrequency: !FindInMap
          - Settings
          - FrequencyMap
          - !Ref Frequency
      S3BucketName: !Ref ConfigBucket
      SnsTopicARN: !If
        - CreateTopic
        - !Ref ConfigTopic
        - !Ref TopicArn
  1. This is to set the execution role.
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetExecutionRole to enable use of your account as a target account in AWS CloudFormation StackSets.

Parameters:
  AdministratorAccountId:
    Type: String
    Description: AWS Account Id of the administrator account (the account in which StackSets will be created).
    MaxLength: 12
    MinLength: 12

Resources:
  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AWSCloudFormationStackSetExecutionRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Ref AdministratorAccountId
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - !Sub arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess
  1. To assume role.
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetAdministrationRole to enable use of AWS CloudFormation StackSets.

Resources:
  AdministrationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AWSCloudFormationStackSetAdministrationRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: AssumeRole-AWSCloudFormationStackSetExecutionRole
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - sts:AssumeRole
                Resource:
                  - "arn:*:iam::*:role/AWSCloudFormationStackSetExecutionRole"

This Day 3 journey was a comprehensive exploration of AWS CloudFormation, offering in-depth insights into its multitude of features and capabilities. Stay tuned for more as the AWS DevOps journey unfolds!

0
Subscribe to my newsletter

Read articles from Nirav Raychura directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nirav Raychura
Nirav Raychura

πŸš€ Tech Enthusiast since 2014 | Cloud Maestro with expertise in AWS, Azure, GCP, and Oracle Cloud ☁️ | Navigating the cloud landscape since 2022 | Holder of 8 Cloud Certificates πŸ… | BCA Graduate πŸŽ“ | Proficient in the programming languages of C, C++, GO, VB, and more πŸ–₯️ | Entrepreneur with a focus on servers, NAS, firewalls, networking, and CCTV 🌐 | Architecting the future of tech, one line of code at a time.