Example of Terraform module to create an SQS queue with modular policy documents
## | |
## Main configuration: creates several SQS queues using a module, then | |
## combines their policies into an application role. | |
## | |
provider "aws" {} | |
module "notifications_queue" { | |
source = "./modules/sqs" | |
queue_name = "Notifications" | |
} | |
module "rendering_queue" { | |
source = "./modules/sqs" | |
queue_name = "Rendering" | |
} | |
module "reports_queue" { | |
source = "./modules/sqs" | |
queue_name = "ReportGeneration" | |
visibility_timeout = 600 | |
receive_count = 1 | |
} | |
resource "aws_iam_role" "application_role" { | |
name = "ApplicationRole" | |
assume_role_policy = jsonencode({ | |
"Version" = "2012-10-17", | |
"Statement" = [ | |
{ | |
"Effect" = "Allow" | |
"Action" = "sts:AssumeRole" | |
"Principal" = { "Service" = "ec2.amazonaws.com" } | |
} | |
] | |
}) | |
} | |
resource "aws_iam_role_policy" "application_role_queue_policy" { | |
name = "application_role_queue_policy" | |
role = aws_iam_role.application_role.id | |
policy = jsonencode({ | |
"Version" = "2012-10-17", | |
"Statement" = [ | |
module.notifications_queue.producer_policy_statement, | |
module.rendering_queue.producer_policy_statement, | |
module.reports_queue.producer_policy_statement | |
] | |
}) | |
} |
## | |
## A module to create an SQS queue, along with its dead-letter queue and access policies | |
## | |
provider "aws" {} | |
data "aws_region" "current" {} | |
## | |
## The primary and dead-letter queues | |
## | |
resource "aws_sqs_queue" "base_queue" { | |
name = var.queue_name | |
message_retention_seconds = var.retention_period | |
visibility_timeout_seconds = var.visibility_timeout | |
redrive_policy = jsonencode({ | |
"deadLetterTargetArn" = aws_sqs_queue.deadletter_queue.arn, | |
"maxReceiveCount" = var.receive_count | |
}) | |
} | |
resource "aws_sqs_queue" "deadletter_queue" { | |
name = "${var.queue_name}-DLQ" | |
message_retention_seconds = var.retention_period | |
visibility_timeout_seconds = var.visibility_timeout | |
} | |
## | |
## the policy statements are defined as locals so that they can be | |
## used by the consuming module to build a larger policy | |
## | |
locals { | |
consumer_policy_statement = { | |
"Sid" = "c${sha1(aws_sqs_queue.base_queue.arn)}" | |
"Effect" = "Allow", | |
"Action" = [ | |
"sqs:ChangeMessageVisibility", | |
"sqs:ChangeMessageVisibilityBatch", | |
"sqs:DeleteMessage", | |
"sqs:DeleteMessageBatch", | |
"sqs:GetQueueAttributes", | |
"sqs:GetQueueUrl", | |
"sqs:ReceiveMessage" | |
], | |
"Resource" = [ | |
aws_sqs_queue.base_queue.arn, | |
aws_sqs_queue.deadletter_queue.arn | |
] | |
} | |
producer_policy_statement = { | |
"Sid" = "p${sha1(aws_sqs_queue.base_queue.arn)}" | |
"Effect" = "Allow", | |
"Action" = [ | |
"sqs:GetQueueAttributes", | |
"sqs:GetQueueUrl", | |
"sqs:SendMessage", | |
"sqs:SendMessageBatch" | |
], | |
"Resource" = [ | |
aws_sqs_queue.base_queue.arn | |
] | |
} | |
} | |
## | |
## managed policies are created for convenience when there's | |
## just a few queues that an application might use | |
## | |
resource "aws_iam_policy" "consumer_policy" { | |
name = "SQS-${var.queue_name}-${data.aws_region.current.name}-consumer" | |
description = "Attach this policy to consumers of the ${var.queue_name} queue" | |
policy = jsonencode({ | |
"Version" = "2012-10-17", | |
"Statement" = [local.consumer_policy_statement] | |
}) | |
} | |
resource "aws_iam_policy" "producer_policy" { | |
name = "SQS-${var.queue_name}-${data.aws_region.current.name}-producer" | |
description = "Attach this policy to producers for the ${var.queue_name} queue" | |
policy = jsonencode({ | |
"Version" = "2012-10-17", | |
"Statement" = [local.producer_policy_statement] | |
}) | |
} |
output "base_queue_url" { | |
value = aws_sqs_queue.base_queue.id | |
} | |
output "deadletter_queue_url" { | |
value = aws_sqs_queue.deadletter_queue.id | |
} | |
output "consumer_policy_statement" { | |
value = local.consumer_policy_statement | |
} | |
output "producer_policy_statement" { | |
value = local.producer_policy_statement | |
} | |
output "consumer_policy_arn" { | |
value = aws_iam_policy.consumer_policy.arn | |
} | |
output "producer_policy_arn" { | |
value = aws_iam_policy.producer_policy.arn | |
} | |
variable "queue_name" { | |
description = "The name of the queue. Used as a prefix for related resource names." | |
type = string | |
} | |
variable "retention_period" { | |
description = "Time (in seconds) that messages will remain in queue before being purged" | |
type = number | |
default = 86400 | |
} | |
variable "visibility_timeout" { | |
description = "Time (in seconds) that consumers have to process a message before it becomes available again" | |
type = number | |
default = 60 | |
} | |
variable "receive_count" { | |
description = "The number of times that a message can be retrieved before being moved to the dead-letter queue" | |
type = number | |
default = 3 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment