I’ve prepared such code, and all resources were created successfully -
main.tf
locals {
project_name = "xfusion"
environment = "dev"
common_name = "${local.project_name}-${local.environment}"
default_tags = {
Project = local.project_name
Environment = local.environment
Owner = "iptcp"
Team = "IT"
}
}
# SNS topic
resource "aws_sns_topic" "sns_topic" {
name = "${local.common_name}-topic"
tags = local.default_tags
}
# SQS queue
resource "aws_sqs_queue" "sqs_queue" {
name = "${local.common_name}-queue"
tags = local.default_tags
}
# SNS topic subscription to the SQS queue
resource "aws_sns_topic_subscription" "queue_subscription" {
endpoint = aws_sqs_queue.sqs_queue.arn
protocol = "sqs"
topic_arn = aws_sns_topic.sns_topic.arn
raw_message_delivery = true
depends_on = [
aws_sns_topic.sns_topic,
aws_sqs_queue.sqs_queue
]
}
# SQS queue policy to allow SNS to send messages
resource "aws_sqs_queue_policy" "sqs_queue_policy" {
queue_url = aws_sqs_queue.sqs_queue.url
policy = data.aws_iam_policy_document.sqs_policy.json
}
data "aws_iam_policy_document" "sqs_policy" {
statement {
actions = ["SQS:SendMessage"]
resources = [aws_sqs_queue.sqs_queue.arn]
principals {
type = "Service"
identifiers = ["sns.amazonaws.com"]
}
}
}
# DynamoDB table
resource "aws_dynamodb_table" "dynamo_table" {
name = "${local.common_name}-events"
hash_key = "event_id"
billing_mode = "PROVISIONED"
read_capacity = 5
write_capacity = 5
attribute {
name = "event_id"
type = "S"
}
tags = local.default_tags
}
# IAM role for SNS to assume
resource "aws_iam_role" "iam_role" {
name = "${local.common_name}-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "sns.amazonaws.com"
}
}
]
})
tags = local.default_tags
}
# IAM policy for specific actions
resource "aws_iam_policy" "iam_policy" {
name = "${local.common_name}-policy"
description = "IAM policy for allowing specific actions"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
for action in var.KKE_IAM_ACTIONS : {
Effect = "Allow"
Action = action
Resource = "*"
}
]
})
}
# Attach IAM policy to IAM role
resource "aws_iam_role_policy_attachment" "policy_attachment" {
role = aws_iam_role.iam_role.name
policy_arn = aws_iam_policy.iam_policy.arn
}
# CloudWatch alarm for queue depth
resource "aws_cloudwatch_metric_alarm" "queue_depth_alarm" {
alarm_name = "${local.common_name}-alarm"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = "1"
metric_name = "ApproximateNumberOfMessagesVisible"
namespace = "AWS/SQS"
period = "60"
statistic = "Maximum"
threshold = var.KKE_QUEUE_DEPTH_THRESHOLD
alarm_description = "Alarm for when the SQS queue depth exceeds the threshold"
insufficient_data_actions = []
dimensions = {
QueueName = aws_sqs_queue.sqs_queue.name
}
}
variables.tf
locals {
valid_regions = ["us-east-1"]
}
variable "KKE_AWS_REGION" {
description = "AWS region to be used"
type = string
default = "us-east-1"
validation {
condition = contains(local.valid_regions, var.KKE_AWS_REGION)
error_message = "The AWS region must be one of the following: us-east-1."
}
}
# Validation for queue depth threshold
variable "KKE_QUEUE_DEPTH_THRESHOLD" {
description = "CloudWatch alarm threshold for queue depth"
type = number
default = 50
validation {
condition = var.KKE_QUEUE_DEPTH_THRESHOLD >= 1 && var.KKE_QUEUE_DEPTH_THRESHOLD <= 1000
error_message = "The queue depth threshold must be between 1 and 1000."
}
}
variable "KKE_IAM_ACTIONS" {
description = "List of IAM actions to allow in dynamic policy"
type = list(string)
default = ["sqs:ReceiveMessage", "dynamodb:PutItem", "sns:Publish"]
}
outputs.tf
output "kke_cloudwatch_alarm_name" {
value = aws_cloudwatch_metric_alarm.queue_depth_alarm.alarm_name
}
output "kke_dynamodb_table_name" {
value = aws_dynamodb_table.dynamo_table.name
}
output "kke_iam_role_arn" {
value = aws_iam_role.iam_role.arn
}
output "kke_sns_topic_arn" {
value = aws_sns_topic.sns_topic.arn
}
output "kke_sqs_queue_url" {
value = aws_sqs_queue.sqs_queue.url
}
Task validation is failing on such error -
No worries!!
Uh oh! Looks like the task was not completed successfully. But it’s Ok. You can try again next time this task is assigned to you.
You may check your work again to see what went wrong. The environment expires in 5 minutes.
If you think you did your work correctly and is marked failed, you may request for a review from your task dashboard. Or alternatively please submit outputs/screenshot(s) of your work and post to community.kodekloud.com
You can also view your results in your dashboard under the “Active Practice” page.
@raymond.baoly Could you please advise how can I complete this lab?
Hi @petya.bogdan
Thanks for your detailed feedback. Could you please share the validation message? It seems to be missing from your post. Was the message “SNS topic is not ensured to be created before subscription”?
Actually now I don’t see any SNS topic image, I only see this -
Thank you for your feedback. I’m trying to reproduce it to find the root cause.
I second this, having the same issues.
@Mederbek @petya.bogdan
This is a valid issue. The team is working on updating the task, and I’ll keep you updated.
Hi guys,
The task has been updated, and I was able to complete it. Please try again.
not sure, what’s happening to the lab, it’s giving weird errors.
Hi @Mederbek
The task requires using an inline policy, so we need to create an IAM role and attach the policy as inline, for example:
resource "aws_iam_role" "iam_role" {
name = "${local.common_name}-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = {
Service = "sns.amazonaws.com"
}
Action = "sts:AssumeRole"
}]
})
tags = local.default_tags
}
resource "aws_iam_role_policy" "inline_policy" {
name = "${local.common_name}-policy"
role = aws_iam_role.iam_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
for action in var.KKE_IAM_ACTIONS : {
Effect = "Allow"
Action = action
Resource = "*"
}
]
})
}
I was able to complete the task, thanks @raymond.baoly for your help
1 Like
Hi @raymond.baoly
I am facing issue in completing this task, it is not giving any error message.
Kindly suggest.
Thanks
Could you please tell us what you are actually doing to complete the task – without knowing what you’re doing, it’s really hard to know what you’re doing wrong 
Hello@rob_kodekloud, I am trying to solve it with the below solution
Mian.tf
locals {
project-name = "datcenter"
environment = "dev"
name-prefix = "${local.project-name}-${local.environment}"
default-tags = {
Project = local.project-name
Environment = local.environment
Owner = "Terraform"
Team = "Devops"
}
}
resource "aws_sns_topic" "sns-test" {
name = "${local.name-prefix}-topic"
tags = local.default-tags
}
resource "aws_sqs_queue" "queue-test" {
name = "${local.name-prefix}-queue"
tags = local.default-tags
}
resource "aws_sns_topic_subscription" "subscription-test" {
depends_on = [aws_sns_topic.sns-test, aws_sqs_queue.queue-test]
topic_arn = aws_sns_topic.sns-test.arn
protocol = "sqs"
endpoint = aws_sqs_queue.queue-test.arn
}
resource "aws_dynamodb_table" "dynamodb-test" {
name = "${local.name-prefix}-events"
billing_mode = "PROVISIONED"
read_capacity = 5
write_capacity = 5
hash_key = "event_id"
attribute {
name = "event_id"
type = "S"
}
tags = local.default-tags
}
resource "aws_iam_role" "role-test" {
name = "${local.name-prefix}-role"
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "sns.amazonaws.com"
}
},
]
})
inline_policy {
name = "datcenter-inrole"
policy = jsonencode({Version = "2012-10-17"
Statement = [
for action in var.KKE_IAM_ACTIONS: {
Action = action
Effect = "Allow"
Resource = "*"
}
]
})
}
tags = local.default-tags
}
resource "aws_cloudwatch_metric_alarm" "alarm-test" {
alarm_name = "${local.project-name}-${local.environment}-alarm"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "1"
metric_name = "ApproximateNumberOfMessagesVisible"
namespace = "AWS/SQS"
period = "60"
statistic = "Maximum"
threshold = "50"
dimensions = {
QueueName = aws_sqs_queue.queue-test.name
}
tags = local.default-tags
}
Variables.tf
variable "KKE_AWS_REGION" {
type = string
validation {
condition = var.KKE_AWS_REGION == "us-east-1"
error_message = "unallowed Region selected"
}
}
variable "KKE_QUEUE_DEPTH_THRESHOLD" {
type = string
default = 50
validation {
condition = var.KKE_QUEUE_DEPTH_THRESHOLD >= 1 && var.KKE_QUEUE_DEPTH_THRESHOLD <= 1000
error_message = "SNS que depth not in desired range"
}
}
variable "KKE_IAM_ACTIONS" {
type = list(string)
description = "IAM actions to allow in dynamic policy."
}
terraform.tfvars
KKE_AWS_REGION = "us-east-1"
KKE_IAM_ACTIONS = ["sqs:ReceiveMessage","dynamodb:PutItem","sns:Publish"]
outputs.tf
output "kke_cloudwatch_alarm_name" {
value = aws_cloudwatch_metric_alarm.alarm-test.alarm_name
}
output "kke_dynamodb_table_name" {
value = aws_dynamodb_table.dynamodb-test.name
}
output "kke_iam_role_arn" {
value = aws_iam_role.role-test.arn
}
output "kke_sqs_queue_url" {
value = aws_sqs_queue.queue-test.url
}
Hi @Md_Danish
Please set the threshold using a variable instead of the hard-coded value 50.
Hello @raymond.baoly , Tried that but still the same result.
Hi @Md_Danish
I also couldn’t find what was wrong with your answer. Here is my passing task answer, please refer to it and try again:
main.tf
locals {
project_name = "datacenter"
environment = "dev"
common_name = "${local.project_name}-${local.environment}"
default_tags = {
Project = local.project_name
Environment = local.environment
Owner = "iptcp"
Team = "IT"
}
}
# SNS topic
resource "aws_sns_topic" "sns_topic" {
name = "${local.common_name}-topic"
tags = local.default_tags
}
# SQS queue
resource "aws_sqs_queue" "sqs_queue" {
name = "${local.common_name}-queue"
tags = local.default_tags
}
# SNS topic subscription to SQS
resource "aws_sns_topic_subscription" "queue_subscription" {
endpoint = aws_sqs_queue.sqs_queue.arn
protocol = "sqs"
topic_arn = aws_sns_topic.sns_topic.arn
raw_message_delivery = true
depends_on = [
aws_sns_topic.sns_topic,
aws_sqs_queue.sqs_queue
]
}
# SQS queue policy to allow SNS -> SQS
resource "aws_sqs_queue_policy" "sqs_queue_policy" {
queue_url = aws_sqs_queue.sqs_queue.url
policy = data.aws_iam_policy_document.sqs_policy.json
}
data "aws_iam_policy_document" "sqs_policy" {
statement {
actions = ["SQS:SendMessage"]
resources = [aws_sqs_queue.sqs_queue.arn]
principals {
type = "Service"
identifiers = ["sns.amazonaws.com"]
}
}
}
# DynamoDB Table
resource "aws_dynamodb_table" "dynamo_table" {
name = "${local.common_name}-events"
hash_key = "event_id"
billing_mode = "PROVISIONED"
read_capacity = 5
write_capacity = 5
attribute {
name = "event_id"
type = "S"
}
tags = local.default_tags
}
# IAM role
resource "aws_iam_role" "iam_role" {
name = "${local.common_name}-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = {
Service = "sns.amazonaws.com"
}
Action = "sts:AssumeRole"
}]
})
tags = local.default_tags
}
resource "aws_iam_role_policy" "inline_policy" {
name = "${local.common_name}-policy"
role = aws_iam_role.iam_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
for action in var.KKE_IAM_ACTIONS : {
Effect = "Allow"
Action = action
Resource = "*"
}
]
})
}
# CloudWatch alarm
resource "aws_cloudwatch_metric_alarm" "queue_depth_alarm" {
alarm_name = "${local.common_name}-alarm"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "ApproximateNumberOfMessagesVisible"
namespace = "AWS/SQS"
period = 60
statistic = "Maximum"
threshold = var.KKE_QUEUE_DEPTH_THRESHOLD
alarm_description = "Alarm for SQS queue depth exceeding threshold"
dimensions = {
QueueName = aws_sqs_queue.sqs_queue.name
}
tags = local.default_tags
}
Thanks @raymond.baoly for the help but getting the same result.
Hi @Md_Danish
I’ve just checked it and it’s worked well from my end.