Created
May 8, 2021 20:35
-
-
Save lucashmsilva/506ca4017547e9da522247608a572bab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
provider "aws" { | |
region = var.region | |
# para tentar rodar no localstack | |
# skip_credentials_validation = true | |
# skip_metadata_api_check = true | |
# skip_requesting_account_id = true | |
# endpoints { | |
# apigateway = "http://localhost:4566" | |
# sns = "http://localhost:4566" | |
# sqs = "http://localhost:4566" | |
# iam = "http://localhost:4566" | |
# } | |
} | |
variable "region" { | |
default = "us-west-2" | |
type = string | |
} | |
# ********** SQS e SNS *********** | |
# Cria tópico SNS que irá fazer o roteamento das mensagens recebidas do API Gateway | |
resource "aws_sns_topic" "message_broker" { | |
name = "webhook_types_broker" | |
} | |
# Cria as filas SQS e as inscreve no tópico. | |
resource "aws_sqs_queue" "account_blocked_webhooks" { | |
name = "account_blocked_webhooks" | |
delay_seconds = 0 | |
max_message_size = 262144 | |
message_retention_seconds = 1209600 | |
receive_wait_time_seconds = 10 | |
depends_on = [aws_sns_topic.message_broker] | |
} | |
resource "aws_sns_topic_subscription" "messages_sqs_target_1" { | |
topic_arn = aws_sns_topic.message_broker.arn | |
protocol = "sqs" | |
endpoint = aws_sqs_queue.account_blocked_webhooks.arn | |
raw_message_delivery = true | |
filter_policy = <<EOF | |
{ | |
"message_type": [ | |
"account_blocked" | |
] | |
} | |
EOF | |
depends_on = [aws_sqs_queue.account_blocked_webhooks] | |
} | |
resource "aws_sqs_queue" "transaction_webhooks" { | |
name = "transaction_webhooks" | |
delay_seconds = 0 | |
max_message_size = 262144 | |
message_retention_seconds = 1209600 | |
receive_wait_time_seconds = 10 | |
depends_on = [aws_sns_topic.message_broker] | |
} | |
resource "aws_sns_topic_subscription" "messages_sqs_target_2" { | |
topic_arn = aws_sns_topic.message_broker.arn | |
protocol = "sqs" | |
endpoint = aws_sqs_queue.transaction_webhooks.arn | |
raw_message_delivery = true | |
filter_policy = <<EOF | |
{ | |
"message_type": [ | |
"transaction" | |
] | |
} | |
EOF | |
depends_on = [aws_sqs_queue.transaction_webhooks] | |
} | |
resource "aws_sqs_queue" "webhook_sink" { | |
name = "webhook_sink" | |
delay_seconds = 0 | |
max_message_size = 262144 | |
message_retention_seconds = 1209600 | |
receive_wait_time_seconds = 10 | |
depends_on = [aws_sns_topic.message_broker] | |
} | |
resource "aws_sns_topic_subscription" "messages_sqs_target_3" { | |
topic_arn = aws_sns_topic.message_broker.arn | |
protocol = "sqs" | |
endpoint = aws_sqs_queue.webhook_sink.arn | |
raw_message_delivery = true | |
depends_on = [aws_sqs_queue.webhook_sink] | |
} | |
# Configura as permissões de SendMessage para o SNS em cada uma das filas | |
resource "aws_sqs_queue_policy" "account_blocked_webhooks_sqs_policy" { | |
queue_url = aws_sqs_queue.account_blocked_webhooks.id | |
policy = <<POLICY | |
{ | |
"Version": "2012-10-17", | |
"Id": "sqspolicy", | |
"Statement": [ | |
{ | |
"Sid": "First", | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "sns.amazonaws.com" | |
}, | |
"Action": "sqs:SendMessage", | |
"Resource": "${aws_sqs_queue.account_blocked_webhooks.arn}", | |
"Condition": { | |
"ArnEquals": { | |
"aws:SourceArn": "${aws_sns_topic.message_broker.arn}" | |
} | |
} | |
} | |
] | |
} | |
POLICY | |
} | |
resource "aws_sqs_queue_policy" "transaction_webhooks_sqs_policy" { | |
queue_url = aws_sqs_queue.transaction_webhooks.id | |
policy = <<POLICY | |
{ | |
"Version": "2012-10-17", | |
"Id": "sqspolicy", | |
"Statement": [ | |
{ | |
"Sid": "First", | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "sns.amazonaws.com" | |
}, | |
"Action": "sqs:SendMessage", | |
"Resource": "${aws_sqs_queue.transaction_webhooks.arn}", | |
"Condition": { | |
"ArnEquals": { | |
"aws:SourceArn": "${aws_sns_topic.message_broker.arn}" | |
} | |
} | |
} | |
] | |
} | |
POLICY | |
} | |
resource "aws_sqs_queue_policy" "webhook_sink_sqs_policy" { | |
queue_url = aws_sqs_queue.webhook_sink.id | |
policy = <<POLICY | |
{ | |
"Version": "2012-10-17", | |
"Id": "sqspolicy", | |
"Statement": [ | |
{ | |
"Sid": "First", | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "sns.amazonaws.com" | |
}, | |
"Action": "sqs:SendMessage", | |
"Resource": "${aws_sqs_queue.webhook_sink.arn}", | |
"Condition": { | |
"ArnEquals": { | |
"aws:SourceArn": "${aws_sns_topic.message_broker.arn}" | |
} | |
} | |
} | |
] | |
} | |
POLICY | |
} | |
# ******************************** | |
# ********** API Gatewy *********** | |
# Cria uma nova API REST no API Gateway | |
resource "aws_api_gateway_rest_api" "api" { | |
name = "WebhookReceiver" | |
description = "receive webhooks and pass the payload througth to SNS" | |
# politica para filtrar IPs que podem chamar a API | |
# policy = <<EOF | |
# { | |
# "Version": "2012-10-17", | |
# "Statement": [{ | |
# "Effect": "Allow", | |
# "Principal": "*", | |
# "Action": "execute-api:Invoke", | |
# "Resource": "execute-api:/*/*/*" | |
# }, | |
# { | |
# "Effect": "Deny", | |
# "Principal": "*", | |
# "Action": "execute-api:Invoke", | |
# "Resource": "execute-api:/*/*/*", | |
# "Condition": { | |
# "NotIpAddress": { | |
# "aws:SourceIp": [""] | |
# } | |
# } | |
# } | |
# ] | |
# } | |
# EOF | |
endpoint_configuration { | |
types = ["REGIONAL"] | |
} | |
} | |
# Cria o recurso /message para a API devifinida no API Gateway | |
resource "aws_api_gateway_resource" "MessageResource" { | |
rest_api_id = aws_api_gateway_rest_api.api.id | |
parent_id = aws_api_gateway_rest_api.api.root_resource_id | |
path_part = "message" | |
} | |
# Cria o recurso /message/:type, vinculando ao recurso criado anteriormente | |
resource "aws_api_gateway_resource" "MessageTypeResource" { | |
rest_api_id = aws_api_gateway_rest_api.api.id | |
parent_id = aws_api_gateway_resource.MessageResource.id | |
path_part = "{type}" | |
} | |
# Associa um método POST para o endpoint /message/:type | |
resource "aws_api_gateway_method" "post_message" { | |
rest_api_id = aws_api_gateway_rest_api.api.id | |
resource_id = aws_api_gateway_resource.MessageTypeResource.id | |
api_key_required = false | |
http_method = "POST" | |
authorization = "NONE" | |
} | |
# Configura a integração com o SNS (substiução de URL) | |
resource "aws_api_gateway_integration" "api_sns_integration" { | |
rest_api_id = aws_api_gateway_rest_api.api.id | |
resource_id = aws_api_gateway_resource.MessageTypeResource.id | |
http_method = "POST" | |
type = "AWS" | |
integration_http_method = "POST" | |
passthrough_behavior = "NEVER" | |
credentials = aws_iam_role.api_sns_role.arn | |
uri = "arn:aws:apigateway:${var.region}:sns:path/${aws_sns_topic.message_broker.name}" | |
request_parameters = { | |
"integration.request.header.Content-Type" = "'application/x-www-form-urlencoded'" | |
} | |
# Aqui vem a mágica | |
request_templates = { | |
# Action=Publish& Método da API do SNS | |
# TopicArn=$util.urlEncode('${aws_sns_topic.message_broker.arn}')& Identificação do Tópico | |
# Message=$util.urlEncode($input.body)& Payload | |
# MessageAttributes.entry.1.Name=$util.urlEncode('message_type')& Atributo message_type | |
# MessageAttributes.entry.1.Value.DataType=$util.urlEncode('String')& Tipo de dado do atributo message_type | |
# MessageAttributes.entry.1.Value.StringValue=$util.urlEncode($input.params('type'))" Valor para o atributo setado com o parametro type do path | |
"application/json" = "Action=Publish&TopicArn=$util.urlEncode('${aws_sns_topic.message_broker.arn}')&Message=$util.urlEncode($input.body)&MessageAttributes.entry.1.Name=$util.urlEncode('message_type')&MessageAttributes.entry.1.Value.DataType=$util.urlEncode('String')&MessageAttributes.entry.1.Value.StringValue=$util.urlEncode($input.params('type'))" | |
} | |
depends_on = [ | |
aws_api_gateway_method.post_message, | |
aws_api_gateway_resource.MessageTypeResource | |
] | |
} | |
# Trata a resposta de sucesso da integração com o SNS. | |
resource "aws_api_gateway_method_response" "success" { | |
rest_api_id = aws_api_gateway_rest_api.api.id | |
resource_id = aws_api_gateway_resource.MessageTypeResource.id | |
http_method = aws_api_gateway_method.post_message.http_method | |
status_code = 200 | |
response_models = { | |
"application/json" = "Empty" | |
} | |
} | |
# Configura uma resposta de sucesso personalizada para o endpoint. | |
resource "aws_api_gateway_integration_response" "success" { | |
rest_api_id = aws_api_gateway_rest_api.api.id | |
resource_id = aws_api_gateway_resource.MessageTypeResource.id | |
http_method = aws_api_gateway_method.post_message.http_method | |
status_code = aws_api_gateway_method_response.success.status_code | |
selection_pattern = "^2[0-9][0-9]" | |
response_templates = { | |
"application/json" = "{\"message\": \"success\"}" | |
} | |
depends_on = [aws_api_gateway_integration.api_sns_integration] | |
} | |
# Configura permissões | |
resource "aws_iam_role" "api_sns_role" { | |
name = "api-sns-role" | |
assume_role_policy = <<EOF | |
{ | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Action": "sts:AssumeRole", | |
"Principal": { | |
"Service": "apigateway.amazonaws.com" | |
}, | |
"Effect": "Allow", | |
"Sid": "" | |
} | |
] | |
} | |
EOF | |
} | |
resource "aws_iam_policy" "api_sns_policy" { | |
name = "api-sns-perms" | |
policy = <<EOF | |
{ | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": "sns:Publish", | |
"Resource": "${aws_sns_topic.message_broker.arn}" | |
} | |
] | |
} | |
EOF | |
} | |
resource "aws_iam_role_policy_attachment" "api" { | |
role = aws_iam_role.api_sns_role.name | |
policy_arn = aws_iam_policy.api_sns_policy.arn | |
} | |
# Faz o deploy da API (acessar o painel da AWS e obter a URL) | |
resource "aws_api_gateway_deployment" "api" { | |
rest_api_id = aws_api_gateway_rest_api.api.id | |
stage_name = "main" | |
depends_on = [ | |
aws_api_gateway_integration.api_sns_integration, | |
] | |
triggers = { | |
redeployment = sha1(join(",", tolist([ | |
jsonencode(aws_api_gateway_integration.api_sns_integration), | |
jsonencode(aws_api_gateway_integration_response.success), | |
jsonencode(aws_api_gateway_method_response.success), | |
]))) | |
} | |
} | |
# ********************************* | |
output "deployment_invoke_url" { | |
description = "Deployment invoke url" | |
value = aws_api_gateway_deployment.api.invoke_url | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# instalar terraform https://learn.hashicorp.com/tutorials/terraform/install-cli | |
terraform init | |
terraform apply -auto-approve | |
export URL_DO_DEPLOYMENT=$(terraform output deployment_invoke_url | tr -d '"') | |
echo "Fazendo requests de teste:" | |
curl -H "Content-Type: application/json" -X POST -d \ | |
'{"conta":"bloqueada"}' \ | |
"${URL_DO_DEPLOYMENT}/message/account_blocked" | |
echo "" | |
curl -H "Content-Type: application/json" -X POST -d \ | |
'{"transação":"autorizada"}' \ | |
"${URL_DO_DEPLOYMENT}/message/transaction" | |
echo "" | |
curl -H "Content-Type: application/json" -X POST -d \ | |
'{"ola":"mundo"}' \ | |
"${URL_DO_DEPLOYMENT}/message/qualquer_outra_coisa" | |
echo "" | |
# para limpar tudo | |
# terraform apply -destroy -auto-approve |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment