<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Esther Ninyo</title>
    <description>The latest articles on DEV Community by Esther Ninyo (@ninyhorlah).</description>
    <link>https://dev.to/ninyhorlah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F479215%2Ffc409be0-48c3-441a-9d09-91835f7c4e7f.jpg</url>
      <title>DEV Community: Esther Ninyo</title>
      <link>https://dev.to/ninyhorlah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ninyhorlah"/>
    <language>en</language>
    <item>
      <title>Implementation of a notification system using AWS part 2 - Lambda function and AWS SES setup</title>
      <dc:creator>Esther Ninyo</dc:creator>
      <pubDate>Mon, 31 Mar 2025 21:02:19 +0000</pubDate>
      <link>https://dev.to/aws-builders/implementation-of-a-notification-system-using-aws-part-2-lambda-function-and-aws-ses-setup-1ico</link>
      <guid>https://dev.to/aws-builders/implementation-of-a-notification-system-using-aws-part-2-lambda-function-and-aws-ses-setup-1ico</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrvwx0hc3usnyn4m76k8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrvwx0hc3usnyn4m76k8.png" alt="Architecture diagram" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;INTRODUCTION&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this post, we'll continue from where we left off and set up a Lambda function to process messages from the SQS queue and send emails using Amazon SES.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources to be created&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lambda&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS SES&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br&gt;
Create a lambda function that consumes the messages from the sqs queue, processes it and send it to the receiver's email address or send it to a dead letter queue when faced with a problem.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose &lt;code&gt;Author from scratch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enter the function name &lt;code&gt;emailNotificationFunction&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;runtime&lt;/code&gt;, choose &lt;code&gt;python&lt;/code&gt; from the dropdown list&lt;/li&gt;
&lt;li&gt;Then click on create function.
This will automatically create an IAM role. Follow the steps below to see the role created and to also update the policy to what is required.&lt;/li&gt;
&lt;li&gt;Click on the function you just created to see the overview. Scroll down a bit, click on the configuration tab.&lt;/li&gt;
&lt;li&gt;On the left pane, click on permissions. Locate the execution role and click on the link under the role name to take you to the role created. &lt;/li&gt;
&lt;li&gt;You will see a policy name that starts with &lt;code&gt;AWSLambdaBasicExecutionRole-&lt;/code&gt;. Edit it with the permission below and save it.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:REGION:ACCOUNT_ID:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:REGION:ACCOUNT_ID:log-group:/aws/lambda/emailNotificationFunction:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "sqs:ReceiveMessage",
                "sqs:GetQueueAttributes",
                "sqs:DeleteMessage"
            ],
            "Resource": [
                "arn:aws:sqs:REGION:ACCOUNT_ID:emailNotificationQueue"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "ses:SendEmail",
            "Resource": "*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Leave everything else as it is. We will update it later.&lt;br&gt;
Check the images below for pictorial reference&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7id9sl6j0jlgtax883fi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7id9sl6j0jlgtax883fi.png" alt="picture reference" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatclpi1fftso3pmk29io.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatclpi1fftso3pmk29io.png" alt="picture reference" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyus9lkpkeat86vgk6b6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyus9lkpkeat86vgk6b6g.png" alt="picture reference" width="800" height="722"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig606fvgnatduv6swrv6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig606fvgnatduv6swrv6.png" alt="picture reference" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n81ob5fwc0f3k7zgpn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n81ob5fwc0f3k7zgpn0.png" alt="picture reference" width="533" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EMAIL SETUP&lt;/strong&gt;&lt;br&gt;
The next thing we will doing is to setup the email address that our notification will go to. Once you have your email address handy, head over to the step below to verify your email address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr2lsut7fympcpa7eo6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr2lsut7fympcpa7eo6n.png" alt="picture reference" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffepk7ky916c8shrj681x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffepk7ky916c8shrj681x.png" alt="picture reference" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2n0t4umi82a3wsgan7jy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2n0t4umi82a3wsgan7jy.png" alt="picture reference" width="800" height="863"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SUBSCRIPTION&lt;/strong&gt;&lt;br&gt;
Subscribe lambda to SQS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the sqs queue you created, scroll down a bit and click on the lambda triggers tab.&lt;/li&gt;
&lt;li&gt;Click on configure lambda function trigger, choose your lambda function from the drop down or type in the lambda arn and click on save. See images below for reference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbe7oi71fmylwwbe9hdyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbe7oi71fmylwwbe9hdyc.png" alt="picture reference" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wyeqt4cwllohw4l03qb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wyeqt4cwllohw4l03qb.png" alt="picture reference" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LAMBDA FUNCTION LOGIC&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Step One&lt;/strong&gt;: Write the code to process messages from the SQS queue and send emails using SES.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step Two&lt;/strong&gt;: Deploy the function and test it to ensure it works correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example lambda logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import logging
import boto3
from botocore.exceptions import ClientError

# Set up logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# Initialize SES client
ses_client = boto3.client('ses', region_name='REGION-NAME')  # Replace 'REGION-NAME' with the AWS region where SES is available

SENDER = "Your Name &amp;lt;EMAIL-ADDRESS&amp;gt;"  # Replace with your sender email
CHARSET = "UTF-8"

def send_email(to_email, subject, body):
    try:
        response = ses_client.send_email(
            Destination={
                'ToAddresses': [
                    to_email,
                ],
            },
            Message={
                'Body': {
                    'Text': {
                        'Charset': CHARSET,
                        'Data': body,
                    },
                },
                'Subject': {
                    'Charset': CHARSET,
                    'Data': subject,
                },
            },
            Source=SENDER,
        )
    except ClientError as e:
        logger.error(f"Failed to send email: {e.response['Error']['Message']}")
        return False
    else:
        logger.info(f"Email sent! Message ID: {response['MessageId']}")
        return True

def process_message(message_body):
    try:
        msg = json.loads(message_body)
    except json.JSONDecodeError:
        logger.error(f"Failed to decode message: {message_body}")
        return

    try:
        message = json.loads(msg.get('Message'))
    except json.JSONDecodeError:
        logger.error(f"Failed to decode message: {msg.get('Message')}")
        return

    print(message)

    event_type = message.get('eventType')
    if event_type == 'UserRegistration':
        user_name = message.get('userName')
        email = message.get('email')

        if user_name and email:
            subject = "Welcome to Our Service!"
            body = f"Hello {user_name},\n\nThank you for registering with us.\n\nBest regards,\nYour Company"
            send_email(email, subject, body)
        else:
            logger.error(f"Missing userName or email in message: {message}")
    else:
        logger.warning(f"Unknown event type: {event_type}")
        raise ValueError("Unknown EventType")

def lambda_handler(event, context):
    for record in event['Records']:
        message_body = record['body']
        logger.info(f"Received message: {message_body}")
        process_message(message_body)

    return {
        'statusCode': 200,
        'body': json.dumps('Messages processed successfully!')
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CONCLUSION&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By following these steps, you've successfully created a Lambda function and set up Amazon SES to send email notifications. Your system is now ready to process messages and send emails based on the notifications received.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>ses</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Implementation of a notification system using AWS - SNS and SQS setup</title>
      <dc:creator>Esther Ninyo</dc:creator>
      <pubDate>Mon, 31 Mar 2025 21:01:28 +0000</pubDate>
      <link>https://dev.to/aws-builders/implementation-of-a-notification-system-using-aws-sns-and-sqs-setup-2c8o</link>
      <guid>https://dev.to/aws-builders/implementation-of-a-notification-system-using-aws-sns-and-sqs-setup-2c8o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67clr4vrb55yjdqdyufs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67clr4vrb55yjdqdyufs.png" alt="Architecture diagram" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;INTRODUCTION&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this post, we'll walk through the steps to set up Amazon SNS and SQS to handle email notifications. This setup will allow you to send messages to an SQS queue via SNS, which can then be processed by a Lambda function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources to be created&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SNS (Simple Notification System)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SQS (Simple Queue Service)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br&gt;
From the AWS console, navigate to the SNS dashboard and create a topic called &lt;code&gt;emailNotificationTopic&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose sns-type &lt;code&gt;standard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enter the sns topic name &lt;code&gt;emailNotificationTopic&lt;/code&gt; and display name (optional).&lt;/li&gt;
&lt;li&gt;Then click on create topic. &lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;emailNotificationTopic&lt;/code&gt; page, scroll down a bit and locate the access policy tab. Edit the access policy by adding the policy below
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "SNS:Publish",
        "SNS:RemovePermission",
        "SNS:SetTopicAttributes",
        "SNS:DeleteTopic",
        "SNS:ListSubscriptionsByTopic",
        "SNS:GetTopicAttributes",
        "SNS:AddPermission",
        "SNS:Subscribe"
      ],
      "Resource": "arn:aws:sns:REGION:ACCOUNT_ID:TOPIC_NAME",
      "Condition": {
        "StringEquals": {
          "AWS:SourceOwner": "ACCOUNT_ID"
        }
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the images below for pictorial reference&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchjbfhxa69sfgx01pqt3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchjbfhxa69sfgx01pqt3.png" alt="Image One" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehvyvjwizkn90ec4h2on.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehvyvjwizkn90ec4h2on.png" alt="Image Two" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mr5v8kn2zsstbvnlmkk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mr5v8kn2zsstbvnlmkk.png" alt="Image Three" width="800" height="984"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faucq2k8t0a49tqx2dbp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faucq2k8t0a49tqx2dbp5.png" alt="Image Four" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs2dcpmqjcwdj6wu9egp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs2dcpmqjcwdj6wu9egp.png" alt="picture reference" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;br&gt;
Create an SQS queue that receives and stores the messages sent from the SNS topic until it is consumed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose queue-type &lt;code&gt;standard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enter the sqs name &lt;code&gt;emailNotificationQueue&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then click on create queue. &lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;emailNotificationQueue&lt;/code&gt; page, scroll down a bit and locate the access policy tab. Edit the access policy by adding the policy below
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "sns.amazonaws.com"
      },
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:REGION:ACCOUNT_ID:QUEUE_NAME",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:sns:REGION:ACCOUNT_ID:TOPIC_NAME"
        }
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave everything else as it is. We will update it later.&lt;br&gt;
Check the images below for pictorial reference&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrqiwnqqcyxmyw2xyfm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrqiwnqqcyxmyw2xyfm6.png" alt="Image Five" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcek6gozhk9l3orgw2z0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcek6gozhk9l3orgw2z0.png" alt="Image 6" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5oy4y1afvr7pg3pcznn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5oy4y1afvr7pg3pcznn9.png" alt="Image 7" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr57lh4os6nbp2ih71npx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr57lh4os6nbp2ih71npx.png" alt="Image 8" width="800" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6xhgtpwrl1k8ir43f2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6xhgtpwrl1k8ir43f2d.png" alt="picture reference" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SUBSCRIPTION&lt;/strong&gt;&lt;br&gt;
In this section, we will subscribe the sqs queue to the sns topic so that the queue can consume any message from the topic. &lt;br&gt;
Subscribe queue to SNS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the sns topic you created, scroll down a bit and click on the subscription tab.&lt;/li&gt;
&lt;li&gt;Click on create subscription, fill in the details and click on create. See images below for reference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfmzonm0vu21929qcu9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfmzonm0vu21929qcu9f.png" alt="picture reference" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5j3dlyp30kvuqldzf53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5j3dlyp30kvuqldzf53.png" alt="picture reference" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONCLUSION&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By following these steps, you've successfully set up an SNS topic and an SQS queue, and subscribed the queue to the topic. In the next post, we'll cover how to create a Lambda function to process these messages and send emails using Amazon SES.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>sns</category>
      <category>systemdesign</category>
      <category>sqs</category>
    </item>
    <item>
      <title>Provisioning AWS CloudTrail using Terraform (Step-by-Step)</title>
      <dc:creator>Esther Ninyo</dc:creator>
      <pubDate>Sun, 31 Mar 2024 05:09:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/provisioning-aws-cloudtrail-using-terraform-step-by-step-hn4</link>
      <guid>https://dev.to/aws-builders/provisioning-aws-cloudtrail-using-terraform-step-by-step-hn4</guid>
      <description>&lt;p&gt;CloudTrail is an AWS service that enables governance, compliance, operational and risk auditing of your AWS account. It captures all the events that happens within your AWS account and it is recorded as events in CloudTrail. The trail will be stored in an s3 bucket of your choice. &lt;br&gt;
To read more on CloudTrail, please visit the &lt;a href="https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html"&gt;documentation page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this technical post, we'll walk through the steps to provision CloudTrail using Terraform.&lt;/p&gt;
&lt;h5&gt;
  
  
  Resources to be created:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;S3 bucket&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KMS (Key Management System) for S3 objects encryption&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CloudTrail&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prerequisite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An AWS account with permissions to create CloudTrail resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS cli configured&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terraform installed&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h6&gt;
  
  
  Folder Structure
&lt;/h6&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cloudtrail  #this is a folder
---&amp;gt; providers.tf
---&amp;gt; s3.tf
---&amp;gt; main.tf
---&amp;gt; kms.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  Step 1:
&lt;/h5&gt;

&lt;p&gt;Create a new directory (cloudtrail) and navigate into it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir cloudtrail
cd cloudtrail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;providers.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_version = "~&amp;gt; 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "eu-west-1"

  default_tags {
    tags = {
      Environment = terraform.workspace,
      ManagedBy   = "Terraform"
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Step 2:
&lt;/h5&gt;

&lt;p&gt;Initialize your project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful initialization should look like the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8un6z5ernysl9c7xxeou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8un6z5ernysl9c7xxeou.png" alt="terraform init" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the code below to your main.tf file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_cloudtrail" "cloudtrail" {
  name                       = "cloudtrail-tutorial"
  s3_bucket_name             = aws_s3_bucket.cloudtrail_s3.id
  kms_key_id                 = aws_kms_key.cloudtrail_kms_key.arn
  enable_log_file_validation = true
  is_multi_region_trail      = true
  enable_logging             = true

  depends_on = [
    aws_s3_bucket.cloudtrail_s3,
    data.aws_iam_policy_document.cloudtrail_s3_policy,
    aws_kms_key.cloudtrail_kms_key
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the code below to your s3.tf file&lt;br&gt;
&lt;code&gt;s3.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket" "cloudtrail_s3" {
  bucket        = "cloudtrail-bucket"
  force_destroy = true
}

resource "aws_s3_bucket_acl" "s3_bucket" {
  bucket = aws_s3_bucket.cloudtrail_s3.id

  acl = "private"
}

resource "aws_s3_bucket_public_access_block" "pub_access" {
  bucket                  = aws_s3_bucket.cloudtrail_s3.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}


resource "aws_s3_bucket_policy" "cloudtrail_s3_policy" {
  bucket = aws_s3_bucket.cloudtrail_s3.id
  policy = data.aws_iam_policy_document.cloudtrail_s3_policy.json
}

data "aws_iam_policy_document" "cloudtrail_s3_policy" {
  statement {
    sid       = "AWSCloudTrailAclCheck"
    effect    = "Allow"
    resources = ["${aws_s3_bucket.cloudtrail_s3.arn}"]
    actions   = ["s3:GetBucketAcl"]

    condition {
      test     = "StringEquals"
      variable = "AWS:SourceArn"
      values   = ["arn:aws:cloudtrail:eu-west-1:${data.aws_caller_identity.current.account_id}:trail/cloudtrail-${terraform.workspace}"]
    }

    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }
  }

  statement {
    sid       = "AWSCloudTrailWrite"
    effect    = "Allow"
    resources = ["${aws_s3_bucket.cloudtrail_s3.arn}/AWSLogs/${data.aws_caller_identity.current.account_id}/*"]
    actions   = ["s3:PutObject"]

    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values   = ["bucket-owner-full-control"]
    }

    condition {
      test     = "StringEquals"
      variable = "AWS:SourceArn"
      values   = ["arn:aws:cloudtrail:eu-west-1:${data.aws_caller_identity.current.account_id}:trail/cloudtrail-${terraform.workspace}"]
    }

    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the code below to your kms.tf file&lt;br&gt;
&lt;code&gt;kms.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_caller_identity" "current" {}

resource "aws_kms_key" "cloudtrail_kms_key" {
  description         = "KMS key for cloudtrail"
  enable_key_rotation = true
  policy              = data.aws_iam_policy_document.kms_policy.json

  depends_on = [
    data.aws_iam_policy_document.kms_policy
  ]
}

resource "aws_kms_alias" "kms_alias" {
  name          = "alias/cloudtrail_kms"
  target_key_id = aws_kms_key.cloudtrail_kms_key.key_id
}


# KMS KEY POLICY
data "aws_iam_policy_document" "kms_policy" {
  # Allow root users full management access to key
  statement {
    sid       = "Enable IAM User Permissions"
    effect    = "Allow"
    actions   = ["kms:*"]
    resources = ["*"]
    principals {
      type = "AWS"
      identifiers = [
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
    }
  }
  statement {
    sid       = "Allow CloudTrail to encrypt logs"
    effect    = "Allow"
    actions   = ["kms:GenerateDataKey*"]
    resources = ["*"]
    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }
    condition {
      test     = "StringEquals"
      variable = "AWS:SourceArn"
      values   = ["arn:aws:cloudtrail:eu-west-1:${data.aws_caller_identity.current.account_id}:trail/cloudtrail-${terraform.workspace}"]
    }
    condition {
      test     = "StringLike"
      variable = "kms:EncryptionContext:aws:cloudtrail:arn"
      values   = ["arn:aws:cloudtrail:*:${data.aws_caller_identity.current.account_id}:trail/*"]
    }
  }
  statement {
    sid       = "Allow CloudTrail to describe key"
    effect    = "Allow"
    actions   = ["kms:DescribeKey"]
    resources = ["*"]
    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }
  }
  statement {
    sid    = "Allow principals in the account to decrypt log files"
    effect = "Allow"
    actions = [
      "kms:Decrypt",
      "kms:ReEncryptFrom"
    ]
    resources = ["*"]
    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
    condition {
      test     = "StringEquals"
      variable = "kms:CallerAccount"
      values   = ["${data.aws_caller_identity.current.account_id}"]
    }
    condition {
      test     = "StringLike"
      variable = "kms:EncryptionContext:aws:cloudtrail:arn"
      values   = ["arn:aws:cloudtrail:*:${data.aws_caller_identity.current.account_id}:trail/*"]
    }
  }
  statement {
    sid       = "Allow alias creation during setup"
    effect    = "Allow"
    actions   = ["kms:CreateAlias"]
    resources = ["*"]
    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
    condition {
      test     = "StringEquals"
      variable = "kms:CallerAccount"
      values   = ["${data.aws_caller_identity.current.account_id}"]
    }
    condition {
      test     = "StringEquals"
      variable = "kms:ViaService"
      values   = ["ec2.eu-west-1.amazonaws.com"]
    }
  }
  statement {
    sid    = "Enable cross account log decryption"
    effect = "Allow"
    actions = [
      "kms:Decrypt",
      "kms:ReEncryptFrom"
    ]
    resources = ["*"]
    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
    condition {
      test     = "StringEquals"
      variable = "kms:CallerAccount"
      values   = ["${data.aws_caller_identity.current.account_id}"]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Step 3:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful plan should look like the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqysw45mfysquvdjx2amt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqysw45mfysquvdjx2amt.png" alt="terraform plan" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Step 4:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful plan should look like the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5a5z6tbmwaztghwq88o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5a5z6tbmwaztghwq88o.png" alt="terraform apply" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Conclusion
&lt;/h5&gt;

&lt;p&gt;You have successfully created an AWS CloudTrail service.&lt;br&gt;
Do you have any question? Please send it my way. Kindly follow me on &lt;a href="https://www.linkedin.com/in/esther-ninyo"&gt;LinkedIn&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudtrail</category>
      <category>terraform</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Monitor EC2 instance metrics with Datadog (step-by-step)</title>
      <dc:creator>Esther Ninyo</dc:creator>
      <pubDate>Wed, 27 Mar 2024 15:27:44 +0000</pubDate>
      <link>https://dev.to/aws-builders/monitor-ec2-instance-metrics-with-datadog-step-by-step-3c35</link>
      <guid>https://dev.to/aws-builders/monitor-ec2-instance-metrics-with-datadog-step-by-step-3c35</guid>
      <description>&lt;p&gt;Hi there,&lt;br&gt;
Ever thought of a straight forward way to monitor your EC2 instance metrics with Datadog but couldn't get a simplified solution? Look no further!&lt;/p&gt;

&lt;p&gt;The three phases to get this up and running are:&lt;br&gt;
Phase one: Enable the AWS integration in Datadog&lt;br&gt;
Phase two: Deploy the Datadog agent on your EC2 instance&lt;br&gt;
Phase three: Start creating your monitors&lt;/p&gt;

&lt;p&gt;Datadog agent can be installed directly on your EC2 instances which gives you the ability to collect metrics such as memory, CPU, disk etc within a short period of time.&lt;br&gt;
To have a robust understanding of how this works, please visit the &lt;a href="https://www.datadoghq.com/blog/monitoring-ec2-instances-with-datadog/"&gt;Datadog blog post&lt;/a&gt; for more detail.&lt;/p&gt;
&lt;h5&gt;
  
  
  Pre-requisite:
&lt;/h5&gt;

&lt;p&gt;To continue with this hands-on, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;EC2 instance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Datadog account&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  Project deep dive
&lt;/h5&gt;

&lt;p&gt;For the scope of this project, we will be monitoring the following system-level EC2 metrics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;High CPU Utilization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High Memory Utilization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High Disk Utilization&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  PHASE ONE
&lt;/h5&gt;

&lt;p&gt;This phase consist of enabling the AWS integration in Datadog to allow monitoring of the EC2 instance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will setup the Datadog integration using terraform. You can get it &lt;a href="https://docs.datadoghq.com/integrations/guide/aws-terraform-setup/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h6&gt;
  
  
  Folder structure
&lt;/h6&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--&amp;gt; EC2 monitoring
------&amp;gt; provider.tf
------&amp;gt; main.tf
------&amp;gt; variables.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "datadog_aws_integration_assume_role" {
   statement {
   actions = ["sts:AssumeRole"]

   principals {
      type = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
   }
   condition {
      test = "StringEquals"
      variable = "sts:ExternalId"

      values = [
         "${datadog_integration_aws.sandbox.external_id}"
      ]
   }
   }
}

data "aws_iam_policy_document" "datadog_aws_integration" {
   statement {
        actions = [
            "ec2:Describe*",
            "ec2:GetTransitGatewayPrefixListReferences",
            "ec2:SearchTransitGatewayRoutes"
        ]

   resources = ["arn:aws:ec2:${var.region}:${data.aws_caller_identity.current.account_id}:instance/${var.instance_id}"]
   }
}

resource "aws_iam_policy" "datadog_aws_integration" {
   name = "TutorialDatadogAWSIntegrationPolicy"
   policy = "${data.aws_iam_policy_document.datadog_aws_integration.json}"
}

resource "aws_iam_role" "datadog_aws_integration" {
   name = "TutorialDatadogAWSIntegrationRole"
   description = "Role for Datadog AWS Integration"
   assume_role_policy = "${data.aws_iam_policy_document.datadog_aws_integration_assume_role.json}"
}

resource "aws_iam_role_policy_attachment" "datadog_aws_integration" {
   role = "${aws_iam_role.datadog_aws_integration.name}"
   policy_arn = "${aws_iam_policy.datadog_aws_integration.arn}"
}

resource "datadog_integration_aws" "sandbox" {
   account_id  = "${data.aws_caller_identity.current.account_id}"
   role_name   = "TutorialDatadogAWSIntegrationRole"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;variable.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "region" {
  type        = string
  description = "The AWS region to use."
  default     = "eu-west-1"
}

variable "datadog_api_key" {
  type        = string
  description = "The Datadog API key."
  default     = "&amp;lt;REDACTED&amp;gt;"
}

variable "datadog_app_key" {
  type        = string
  description = "The Datadog application key."  
  default     = "&amp;lt;REDACTED&amp;gt;"
}

variable "instance_id" {
  type        = string
  description = "EC2 instance ID."  
  default     = "&amp;lt;REDACTED"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;provider.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_version = "~&amp;gt; 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
    }
    datadog = {
      source  = "DataDog/datadog"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = var.region

  default_tags {
    tags = {
      Environment = terraform.workspace,
      ManagedBy   = "Terraform"
    }
  }
}

# Configure the Datadog provider
provider "datadog" {
    api_key = var.datadog_api_key
    app_key = var.datadog_app_key
    api_url = "https://api.datadoghq.eu"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Get datadog app key, api key and api url&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your datadog profile at the bottom left and click on organisation settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqyurza82kmvyzfbalgus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqyurza82kmvyzfbalgus.png" alt="datadog profile image" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Locate the navigation pane at the left (1), under access (2), click on application key (3) to create a new key. Also click on the api key (4) to create a new key to be used.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffumy39dd062fi7pk9352.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffumy39dd062fi7pk9352.png" alt="datadog key" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on &lt;a href="https://docs.datadoghq.com/getting_started/site/?site=eu"&gt;this link&lt;/a&gt; to access the api url depending the Datadog site you use. Replace app with api.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;WHAT NEXT?&lt;/strong&gt;&lt;br&gt;
The next line of action is to initialise, plan and apply your terraform changes. To do this, use the command below in your folder home directory:&lt;br&gt;
&lt;code&gt;terraform init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform apply&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If the &lt;em&gt;terraform plan&lt;/em&gt; is successful, you should see the resources that will be created after running terraform apply like the result below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform plan
data.aws_iam_policy_document.datadog_aws_integration: Reading...
data.aws_caller_identity.current: Reading...
data.aws_iam_policy_document.datadog_aws_integration: Read complete after 0s [id=1400131043]
data.aws_caller_identity.current: Read complete after 0s [id=134130342652]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
 &amp;lt;= read (data resources)

Terraform will perform the following actions:

  # data.aws_iam_policy_document.datadog_aws_integration_assume_role will be read during apply
  # (config refers to values not yet known)
 &amp;lt;= data "aws_iam_policy_document" "datadog_aws_integration_assume_role" {
      + id   = (known after apply)
      + json = (known after apply)

      + statement {
          + actions = [
              + "sts:AssumeRole",
            ]

          + condition {
              + test     = "StringEquals"
              + values   = [
                  + (known after apply),
                ]
              + variable = "sts:ExternalId"
            }

          + principals {
              + identifiers = [
                  + "arn:aws:iam::&amp;lt;REDACTED&amp;gt;:root",
                ]
              + type        = "AWS"
            }
        }
    }

  # aws_iam_policy.datadog_aws_integration will be created
  + resource "aws_iam_policy" "datadog_aws_integration" {
      + arn         = (known after apply)
      + id          = (known after apply)
      + name        = "TutorialDatadogAWSIntegrationPolicy"
      + name_prefix = (known after apply)
      + path        = "/"
      + policy      = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = [
                          + "ec2:SearchTransitGatewayRoutes",
                          + "ec2:GetTransitGatewayPrefixListReferences",
                          + "ec2:Describe*",
                        ]
                      + Effect   = "Allow"
                      + Resource = "arn:aws:ec2:&amp;lt;REDACTED&amp;gt;:instance/&amp;lt;REDACTED&amp;gt;"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id   = (known after apply)
      + tags_all    = {
          + "Environment" = "default"
          + "ManagedBy"   = "Terraform"
        }
    }

  # aws_iam_role.datadog_aws_integration will be created
  + resource "aws_iam_role" "datadog_aws_integration" {
      + arn                   = (known after apply)
      + assume_role_policy    = (known after apply)
      + create_date           = (known after apply)
      + description           = "Role for Datadog AWS Integration"
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "TutorialDatadogAWSIntegrationRole"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = {
          + "Environment" = "default"
          + "ManagedBy"   = "Terraform"
        }
      + unique_id             = (known after apply)
    }

  # aws_iam_role_policy_attachment.datadog_aws_integration will be created
  + resource "aws_iam_role_policy_attachment" "datadog_aws_integration" {
      + id         = (known after apply)
      + policy_arn = (known after apply)
      + role       = "TutorialDatadogAWSIntegrationRole"
    }

  # datadog_integration_aws.sandbox will be created
  + resource "datadog_integration_aws" "sandbox" {
      + account_id                       = "&amp;lt;REDACTED&amp;gt;"
      + cspm_resource_collection_enabled = (known after apply)
      + external_id                      = (known after apply)
      + id                               = (known after apply)
      + metrics_collection_enabled       = (known after apply)
      + resource_collection_enabled      = (known after apply)
      + role_name                        = "TutorialDatadogAWSIntegrationRole"
    }

Plan: 4 to add, 0 to change, 0 to destroy.

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  PHASE TWO
&lt;/h5&gt;

&lt;p&gt;The second phase is to deploy the agent.&lt;br&gt;
Use the command below to install the agent on ubuntu server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DD_API_KEY=&amp;lt;API_KEY DD_SITE=&amp;lt;DATADOG_SITE&amp;gt; DD_APM_INSTRUMENTATION_ENABLED=host bash -c "$(curl -L https://s3.amazonaws.com/dd-agent/scripts/install_script_agent7.sh)"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where:&lt;br&gt;
API_KEY = your Datadog api key&lt;br&gt;
DATADOG_SITE = Datadog site. For this exercise, we use "datadog.eu".&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Depending on the operating system you use, navigate to &lt;a href="https://docs.datadoghq.com/agent/"&gt;this site&lt;/a&gt; to get the command for installing Datadog agent.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After the Datadog agent agent has been installed, go to your Datadog account, navigate to metrics and you will start to see the reports of your EC2 metrics in Datadog like the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzy7vfa1rccbc2b652bx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzy7vfa1rccbc2b652bx.png" alt="Datadog agent installation image" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  PHASE THREE
&lt;/h5&gt;

&lt;p&gt;In this phase, we will create monitors for our EC2 instance for the metrics listed at the beginning of this tutorial.&lt;/p&gt;

&lt;p&gt;A. HIGH CPU UTILISATION&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the monitors page in Datadog, on the top right, click on new monitor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l7y8toend1vex4lhlh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l7y8toend1vex4lhlh3.png" alt="metrics image" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on metrics and configure your monitor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ij69m58wm32rwxfclbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ij69m58wm32rwxfclbd.png" alt="metrics image" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The image below shows the configuration needed to monitor your EC2 cpu utilisation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2y03ukkmz9u2dawiz1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2y03ukkmz9u2dawiz1g.png" alt="metrics image" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxyjt9tgepxbjmttvae3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxyjt9tgepxbjmttvae3.png" alt="metrics image" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ytvsvmp3ecdz1mg2o70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ytvsvmp3ecdz1mg2o70.png" alt="metrics image" width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your monitor should look like this after creation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrop2ucice20dkat4yz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrop2ucice20dkat4yz0.png" alt="metrics image" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ywb1wwo8w2uuyago0im.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ywb1wwo8w2uuyago0im.png" alt="metrics image" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To understand each options used in creating the monitor, click &lt;a href="https://docs.datadoghq.com/monitors/types/metric/?tab=threshold"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;B. HIGH MEMORY UTILISATION&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zzzgz9qekueqlvxy58r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zzzgz9qekueqlvxy58r.png" alt="metrics image" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2cpcirj7odk1ib3oqcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2cpcirj7odk1ib3oqcw.png" alt="metrics image" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxb6nia0yjxrejm5cbo9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxb6nia0yjxrejm5cbo9.png" alt="metrics image" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your monitor should look like this after creation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyby6vnhionk68gzhjivj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyby6vnhionk68gzhjivj.png" alt="metrics image" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C. HIGH DISK UTILISATION&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5x44x0x9g9xnlf9wasew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5x44x0x9g9xnlf9wasew.png" alt="metrics image" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqsjsv1xp9zo85q6ezdc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqsjsv1xp9zo85q6ezdc.png" alt="metrics image" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rds7gsobo85ripftaeb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rds7gsobo85ripftaeb.png" alt="metrics image" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope you are able to follow through and also are able to create the Datadog monitors for your metrics. Do you have any question? Please send it my way. Kindly follow me on &lt;a href="//www.linkedin.com/in/esther-ninyo"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>datadog</category>
      <category>aws</category>
      <category>ec2</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Create AWS ECR Repository using Cloudformation</title>
      <dc:creator>Esther Ninyo</dc:creator>
      <pubDate>Fri, 12 Aug 2022 18:42:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/create-aws-ecr-repository-using-cloudformation-55km</link>
      <guid>https://dev.to/aws-builders/create-aws-ecr-repository-using-cloudformation-55km</guid>
      <description>&lt;p&gt;Cloudformation is an infrastructure as code (iac) tool that gives us the super powers to easily replicate infrastructures on AWS platform and also gives the users the ability to easily control and track changes to the infrastructure. &lt;/p&gt;

&lt;p&gt;Cloudformation helps set up AWS resources using templates written in json or yaml format which reduces the time spent on managing the resources and gives us more time to focus on the application running in AWS. To read more on the super powers of cloudformation, please find the documentation &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article comprises on how to use cloudformation to spin up ecr repo on AWS. Should in case you're interested on how to use terraform to spin up ecr repo, please find my article on how to do that &lt;a href="https://dev.to/ninyhorlah/provision-aws-elastic-container-registry-repository-using-terraform-373g"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Prerequisite:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Download and install AWS CLI so you can interact with AWS services from your command line interface&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure your AWS credentials via your cli using AWS configure command. To do that, you need to create a user using IAM on AWS.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Project Structure&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;For this project, we need three files as seen and explained below:&lt;br&gt;
&lt;strong&gt;ecr.yml&lt;/strong&gt;: This is the cloudformation template used in creating the ecr repo resource on AWS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ecr.json&lt;/strong&gt;: This is the cloudformation parameters that allows us to dynamically input values whenever a stack is created or updated. Cloudformation parameters are written in json format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;create.sh&lt;/strong&gt;: This is mainly a file that contains the command that creates the cloudformation stack instead of typing the command repeatedly. &lt;/p&gt;

&lt;p&gt;Ecr_cloudformation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ecr.yml&lt;/li&gt;
&lt;li&gt;ecr.json&lt;/li&gt;
&lt;li&gt;create.sh&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6yhp4goefrv4t7vgon0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6yhp4goefrv4t7vgon0.png" alt="project structure"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Project configuration
&lt;/h4&gt;

&lt;p&gt;Step 1: Open up the ecr.json file, paste the following code in it and save. This is our parameter template.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[
   {
       "ParameterKey": "repoName",
       "ParameterValue": "ecr"
   }
]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftz9k8muddhucxniocbgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftz9k8muddhucxniocbgi.png" alt="parameter template"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Step 2: Open up the ecr.yml file, paste the following lines of code in it and save. This is our resource template written in yaml format and the indentation is very important.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

AWSTemplateFormatVersion: 2010-09-09
Description: Elastic Container Registory Repository using Cloudformation

#------------------------
#   PARAMETERS
#------------------------
Parameters:
  repoName: 
    Description: Name for ecr repo 
    Type: String

#------------------------
#   RESOURCES
#------------------------ 
Resources:
  ecrRepo:
    Type: AWS::ECR::Repository
    Properties: 
      RepositoryName: !Sub ${repoName}-repo
      ImageScanningConfiguration: 
        ScanOnPush: true


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5hd4svh90fnr9kz1eha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5hd4svh90fnr9kz1eha.png" alt="resource template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;line 1: This identifies the capabilities of the template and the only valid version value is 2010-09-09. The value must be a literal string and this section is optional.&lt;/p&gt;

&lt;p&gt;line 2: This section enables you to add comment about the template and it is optional.&lt;/p&gt;

&lt;p&gt;line 7 - 10: This is the parameter section and the parameter declared here is &lt;em&gt;repoName&lt;/em&gt; with its default value declared in the ecr.json file.&lt;/p&gt;

&lt;p&gt;line 15 - 21: This is the resource section that declares the AWS resources you want to include in the stack. The resource declared here is &lt;em&gt;ecrRepo&lt;/em&gt;. Under the properties, the repositoryName made use of the parameter by substituting it with additional extension &lt;em&gt;-repo&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;Step 3: To spin up the resources, we will be using cloudformation create-stack command but we will be including it in the create.sh file we created so it can be easily accessed and used.&lt;br&gt;
Open up the create.sh file and add the following command to it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws cloudformation create-stack --stack-name $1 --template-body file://$2 --parameter file://$3 --region=us-east-1


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybkb13ey8b4fpdebbdyy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybkb13ey8b4fpdebbdyy.png" alt="cloudformation create-stack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before you can execute that command, you need to move into the project directory and give the create.sh file execute access by using the command below: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

chmod +x create.sh


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoeik2gdht0flyxfvk2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoeik2gdht0flyxfvk2u.png" alt="chmod command"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the file has been given execute access, you can then safely create the cloudformation stack that will spin up the ecr repo using the command below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

./create.sh ecr-repo ecr.yml ecr.json


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwwpbrbyqpe4uxvryfqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwwpbrbyqpe4uxvryfqb.png" alt="created repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The response above shows that the cloudformation stack has been created successfully.&lt;/p&gt;

&lt;p&gt;Note the following in the create.sh file: &lt;br&gt;
$1 = ecr-repo&lt;br&gt;
$2 = ecr.yml&lt;br&gt;
$3 = ecr.json&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1wofkn5521y1hpiwrsk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1wofkn5521y1hpiwrsk1.png" alt="complete cloudformation stack"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Completely created cloudformation stack&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zbr6h5osi8mnxkqix87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zbr6h5osi8mnxkqix87.png" alt="ecr repo"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Successfully created ecr repo&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You have successfully created an elastic container registry repository using cloudformation and you can safely publish your container images to it.&lt;/p&gt;




&lt;p&gt;Thank you for reading to the end. Kindly reach out to me in the comment section if you have any questions or on &lt;a href="https://www.linkedin.com/in/esther-ninyo/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://twitter.com/ninyhorlah" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; on ways to improve or to say hi.&lt;/p&gt;

&lt;p&gt;Till next time, cheers.&lt;/p&gt;

</description>
      <category>cloudformation</category>
      <category>aws</category>
      <category>automation</category>
      <category>iac</category>
    </item>
    <item>
      <title>Provision AWS Elastic Container Registry Repository using Terraform</title>
      <dc:creator>Esther Ninyo</dc:creator>
      <pubDate>Thu, 21 Jul 2022 13:48:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/provision-aws-elastic-container-registry-repository-using-terraform-373g</link>
      <guid>https://dev.to/aws-builders/provision-aws-elastic-container-registry-repository-using-terraform-373g</guid>
      <description>&lt;p&gt;Automation is very crucial in development which eliminates/reduces human error during manual provisioning. Automation enables teams to focus on work that adds value to the business which in turn increases revenue.&lt;br&gt;
In this article, I will walk you through how to set up AWS elastic container registry repository using terraform. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terms and Technologies&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Terraform&lt;/strong&gt; : Terraform is an open-source iac (infrastructure as code) tool that is used to provision, change and improve infrastructure on any environment. To read more on terraform, visit &lt;a href="https://www.terraform.io/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform backend config&lt;/strong&gt;: The terraform backend defines where terraform stores its state data files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform provider&lt;/strong&gt;: In terraform, infrastructures are provisioned across public cloud providers such  as amazon web services, google cloud, azure etc. The provider block is used to state the cloud provider you want to use and in this tutorial, we will be making use of amazon web service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download and install AWS CLI so you can interact with aws services from your command line interface&lt;/li&gt;
&lt;li&gt;Configure your AWS credentials via your cli using aws configure command. To do that, you need to create a user using IAM on AWS.&lt;/li&gt;
&lt;li&gt;Download and install terraform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Structure&lt;/strong&gt;&lt;br&gt;
Terraform-ecr &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend.tf&lt;/li&gt;
&lt;li&gt;Main.tf&lt;/li&gt;
&lt;li&gt;Provider.tf&lt;/li&gt;
&lt;li&gt;Variable.auto.tfvars&lt;/li&gt;
&lt;li&gt;Variables.tf&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xmx189mrl4ukop38091.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xmx189mrl4ukop38091.png" alt="project folder structure" width="420" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project Configuration&lt;/strong&gt;&lt;br&gt;
The first thing we will be doing is to create an s3 bucket that will hold the state files. Then, add the terraform configuration block that stores state data files for this project inside the s3 bucket created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvyaf71zyrypjjnnof6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvyaf71zyrypjjnnof6a.png" alt="s3 bucket created" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open up your backend.tf file and add the following line of code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
 backend "s3" {
   bucket = "myawspracticebucket12"
   key = "~/.aws/config"
   region = "us-east-1"
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxv3ow34sgtcbnbiw0g7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxv3ow34sgtcbnbiw0g7.png" alt="terraform block using s3 as backend" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Line 1&lt;/strong&gt;: This is the terraform block needed to create our backend config&lt;br&gt;
&lt;strong&gt;Line 2&lt;/strong&gt;: describes the backend block  which contains the information of where the backend will stored&lt;br&gt;
&lt;strong&gt;Line 3&lt;/strong&gt;: The name of the bucket we created&lt;br&gt;
&lt;strong&gt;Line 4&lt;/strong&gt;: The path to your credential file. This is available when you do aws configure. You can also decide to use a different credential. All you need to do is to specify the path.&lt;br&gt;
&lt;strong&gt;Line 5&lt;/strong&gt;: Region of the s3 bucket&lt;br&gt;
Before we move on, let’s initialize the backend using the terminal to see if we’ve not made any mistake by using this command:&lt;br&gt;
&lt;code&gt;Terraform init&lt;/code&gt;&lt;br&gt;
This will be the output if everything is done correctly&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym21i8oxjpzymnpicylq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym21i8oxjpzymnpicylq.png" alt="terraform init result" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you do not have that, crosscheck the path to your credential file and also your bucket name if they are correct.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: In this step, i add the terraform provider which is “hashicorp/aws” with its version, i also added the aws region declared in the variable.tf Open up your provider.tf file and add the following lines of code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
 required_providers {
     aws = {
         source = "hashicorp/aws"
         version = "~&amp;gt;4.19.0"
     }
 }
}

provider "aws" {
 region = var.region
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1hq7pc97dutygrdfqnmk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1hq7pc97dutygrdfqnmk.png" alt="terraform providers block" width="798" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: In this step, I added the resource block that creates the elastic container registry  (ecr) on aws. Open up your main.tf file and add the following lines of code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_ecr_repository" "ecr_repo" {
 name                 = var.ecr
 image_tag_mutability = "IMMUTABLE"

 image_scanning_configuration {
   scan_on_push = true
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7v5mec5oxxpcy6s63mk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7v5mec5oxxpcy6s63mk.png" alt="ecr resource block" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Line 1&lt;/strong&gt;: This is the resource block that holds information used in creating the elastic container registry&lt;br&gt;
&lt;strong&gt;Line 2&lt;/strong&gt;: The name of the repository stored in the variable file&lt;br&gt;
&lt;strong&gt;Line 3&lt;/strong&gt;: This prevents image tags from being overwritten&lt;br&gt;
&lt;strong&gt;Line 6&lt;/strong&gt;: This scans images for vulnerabilities&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: In this step, I will declare the variables used in the previous files such as the region and repository name. Open up your  variables.tf file and add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "region" {
 description = "AWS region"
 type = string
}

variable "ecr" {
 description = "Repository name"
 type = string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pqtb81ghe795zq8z6kc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pqtb81ghe795zq8z6kc.png" alt="variable block" width="756" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will notice that we do not have any default value in the variables.tf file, the values will be stored in the variables.auto.tfvars file. &lt;br&gt;
Open up your variables.auto.tfvars file and add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;region = "us-east-1"
ecr = "web"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntstbr1qxp04ag9j2yy6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntstbr1qxp04ag9j2yy6.png" alt="variable values" width="564" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;: In this step, i will use terraform command to spin up our infrastructure&lt;br&gt;
&lt;code&gt;Terraform init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkl4f0v5clxz7b7z0hqy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkl4f0v5clxz7b7z0hqy5.png" alt="terraform init result" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Terraform plan&lt;/code&gt; to see the resources we’re creating&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd0a8kpl6k6wwbisgoab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd0a8kpl6k6wwbisgoab.png" alt="terraform plan result" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Terraform apply&lt;/code&gt; to spin up the resource&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmqkenmif58kv9h977eel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmqkenmif58kv9h977eel.png" alt="terraform apply result" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s head over to the console to see what we created&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0qisjx30oc7xno80k63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0qisjx30oc7xno80k63.png" alt="created repository" width="800" height="111"&gt;&lt;/a&gt;&lt;em&gt;Repository created&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You have successfully created an elastic container registry repository and you can safely publish your container images to it.&lt;/p&gt;

&lt;p&gt;Thank you for reading to the end. Kindly reach out to me in the comment section if you have any question or on &lt;a href="https://www.linkedin.com/in/esther-ninyo/"&gt;linkedin&lt;/a&gt; and &lt;a href="https://twitter.com/ninyhorlah"&gt;twitter&lt;/a&gt; on ways to improve.&lt;/p&gt;

&lt;p&gt;Till next time, cheers.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>iac</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
