diff --git a/README.md b/README.md
index c673146..8cfef3f 100644
--- a/README.md
+++ b/README.md
@@ -4,40 +4,44 @@ Best Stock Management System application.
## Descripción de los módulos
-### Api gateway
+### API Gateway
-Recibe pedidos HTTPS. Pueden ser POST o GET. EN el caso de GET, va directo a la lambda de lectura de la tabla. En el caso de POST, se encola en el SQS para luego ir a la lambda.
+Construye una API REST que puede recibir requests POST, GET u OPTIONS. En el caso de GET, va directo a la lambda de lectura de la tabla (`lambdaDB`). Por otro lado, en el caso de un POST, se encola en el SQS para luego ir a otra lambda (`lambdaSQSDB`). Finalmente, el OPTIONS se utiliza para poder soportar y habilitar `CORS` y que, por ende, funcionen correctamente los llamados a la API desde el sitio estático.
-### Cloudfront
+### CloudFront
-Realiza cache de la API y del S3.
+Realiza caché de la API y del S3 (que hostea el sitio estático).
### Dynamo DB
-Guarda los datos de los stocks de los usuarios.
+Guarda los datos de los stocks de los usuarios. Tiene una tabla compuesta por `id` (la partition key) y `stock`.
### Lambda
-Definimos 2 lambdas.
-Una se encarga de realizar escrituras al DynamoDB y la otra de realizar lecturas.
+Definimos 2 lambdas. Una se encarga de realizar escrituras al `DynamoDB` (`lambdaSQSDB`) y la otra de realizar lecturas (`lambdaDB`).
### S3
-Definimos 3 buckets. Uno para logs y dos para front.
+Definimos 3 buckets. Uno para logs y dos para el frontend (el sitio estático en sí y uno `www` que se redirecciona al primero).
### SQS
-Se encarga de encolar POSTs recibidos por la API. Luego dispara la lambda correspondiente
+Se encarga de encolar POSTs recibidos por la API. Luego, dispara la lambda correspondiente (en este caso `lambdaSQSDB`).
### VPC
-Este módulo es [externo](https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest).
+Este módulo es [externo](https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest). Se define en este toda la parte de networking que se detalla en el diagrama de la arquitectura (el cual se encuentra al final de este documento).
+
+### WAF
+
+Protege la aplicación mediante 3 rules. Esto lo hace mediante la creación de un web ACL asociado a la distribución de cloudfront.
## Descripción y referencia de funciones y meta-argumentos
-*Los links solo hacen referencia a la primera aparición en cada archivo.*
+Se debe notar que los links solo hacen referencia a la primera aparición en cada archivo.
### Funciones
+
Junto a cada función se especifica para qué se usa.
- **file**: devuelve como string el contenido del archivo `index.html`. Esto es utilizado para luego poder modificarlo (pues actúa como un template ya que tiene la variable `ENDPOINT` parametrizada) y usarlo.
@@ -95,6 +99,8 @@ Junto a cada función se especifica para qué se usa.
## Diagrama de arquitectura deployada
+Los servicios que deben ser corregidos (asociados a la entrega del TP3) son los numerados.
+
## Rúbrica
@@ -126,10 +132,3 @@ Junto a cada función se especifica para qué se usa.
25% |
-
-## Autores
-- Bellver, Ezequiel (61268)
-- Burgos, Santiago Eduardo (55193)
-- Lo Coco, Santiago (61301)
-- Oillataguerre, Amparo (58714)
-
diff --git a/terraform/modules/apigw/main.tf b/terraform/modules/apigw/main.tf
index 5d3399f..d9954c0 100644
--- a/terraform/modules/apigw/main.tf
+++ b/terraform/modules/apigw/main.tf
@@ -96,41 +96,6 @@ resource "aws_api_gateway_integration" "options" {
depends_on = [aws_api_gateway_method.options]
}
-resource "aws_api_gateway_deployment" "this" {
- rest_api_id = aws_api_gateway_rest_api.this.id
-
- triggers = {
- redeployment = sha1(jsonencode([
- aws_api_gateway_resource.this.id,
- aws_api_gateway_method.this.id,
- aws_api_gateway_method.options.id,
- aws_api_gateway_method.stock_get.id,
- aws_api_gateway_integration.this.id,
- aws_api_gateway_integration.options.id,
- aws_api_gateway_integration.stock_get.id,
- ]))
- }
-
- lifecycle {
- create_before_destroy = true
- }
-
- depends_on = [
- aws_api_gateway_integration.options,
- aws_api_gateway_integration.this,
- aws_api_gateway_integration.stock_get,
- aws_api_gateway_method.options,
- aws_api_gateway_method.this,
- aws_api_gateway_method.stock_get,
- aws_api_gateway_method_response.options200,
- aws_api_gateway_method_response.http200,
- aws_api_gateway_method_response.stock200,
- aws_api_gateway_integration_response.options200,
- aws_api_gateway_integration_response.http200,
- aws_api_gateway_integration_response.stock200,
- ]
-}
-
resource "aws_api_gateway_stage" "this" {
deployment_id = aws_api_gateway_deployment.this.id
rest_api_id = aws_api_gateway_rest_api.this.id
@@ -221,6 +186,41 @@ resource "aws_api_gateway_integration_response" "options200" {
depends_on = [aws_api_gateway_method_response.options200]
}
+resource "aws_api_gateway_deployment" "this" {
+ rest_api_id = aws_api_gateway_rest_api.this.id
+
+ triggers = {
+ redeployment = sha1(jsonencode([
+ aws_api_gateway_resource.this.id,
+ aws_api_gateway_method.this.id,
+ aws_api_gateway_method.options.id,
+ aws_api_gateway_method.stock_get.id,
+ aws_api_gateway_integration.this.id,
+ aws_api_gateway_integration.options.id,
+ aws_api_gateway_integration.stock_get.id,
+ ]))
+ }
+
+ lifecycle {
+ create_before_destroy = true
+ }
+
+ depends_on = [
+ aws_api_gateway_integration.options,
+ aws_api_gateway_integration.this,
+ aws_api_gateway_integration.stock_get,
+ aws_api_gateway_method.options,
+ aws_api_gateway_method.this,
+ aws_api_gateway_method.stock_get,
+ aws_api_gateway_method_response.options200,
+ aws_api_gateway_method_response.http200,
+ aws_api_gateway_method_response.stock200,
+ aws_api_gateway_integration_response.options200,
+ aws_api_gateway_integration_response.http200,
+ aws_api_gateway_integration_response.stock200,
+ ]
+}
+
resource "aws_lambda_permission" "this" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
diff --git a/terraform/modules/sqs/outputs.tf b/terraform/modules/sqs/outputs.tf
index 00aabbf..f9d8524 100644
--- a/terraform/modules/sqs/outputs.tf
+++ b/terraform/modules/sqs/outputs.tf
@@ -1,8 +1,13 @@
# --------------------------------------------------------------------
-# Lambda outputs
+# Amazon Simple Queue Service outputs
# --------------------------------------------------------------------
output "sqs_arn" {
- description = "The ARN of SQS"
+ description = "The ARN of SQS."
value = aws_sqs_queue.this.arn
}
+
+output "name" {
+ description = "The name of the SQS."
+ value = aws_sqs_queue.this.name
+}
diff --git a/terraform/modules/sqs/variables.tf b/terraform/modules/sqs/variables.tf
index 12eeb1c..76306aa 100644
--- a/terraform/modules/sqs/variables.tf
+++ b/terraform/modules/sqs/variables.tf
@@ -3,9 +3,8 @@
# ------------------------------------------------------------------------------
variable "name" {
- description = "This is the human-readable name of the queue. If omitted, Terraform will assign a random name."
+ description = "This is the human-readable name of the queue."
type = string
- default = null
}
variable "message_retention_seconds" {
diff --git a/terraform/modules/waf/main.tf b/terraform/modules/waf/main.tf
new file mode 100644
index 0000000..9a335c1
--- /dev/null
+++ b/terraform/modules/waf/main.tf
@@ -0,0 +1,87 @@
+# --------------------------------------------------------------------
+# WAF
+# --------------------------------------------------------------------
+
+resource "aws_wafv2_web_acl" "this" {
+ name = var.name
+ scope = var.scope
+
+ default_action {
+ allow {}
+ }
+
+ rule {
+ name = "AWS-AWSManagedRulesCommonRuleSet"
+ priority = 1
+
+ override_action {
+ none {}
+ }
+
+ statement {
+ managed_rule_group_statement {
+ name = "AWSManagedRulesCommonRuleSet"
+ vendor_name = "AWS"
+ }
+ }
+
+ visibility_config {
+ cloudwatch_metrics_enabled = true
+ metric_name = "AWS-AWSManagedRulesCommonRuleSet"
+ sampled_requests_enabled = true
+ }
+ }
+
+ rule {
+ name = "AWS-AWSManagedRulesLinuxRuleSet"
+ priority = 2
+
+ statement {
+ managed_rule_group_statement {
+ name = "AWSManagedRulesLinuxRuleSet"
+ vendor_name = "AWS"
+ }
+ }
+
+ override_action {
+ none {}
+ }
+
+ visibility_config {
+ cloudwatch_metrics_enabled = true
+ metric_name = "AWS-AWSManagedRulesLinuxRuleSet"
+ sampled_requests_enabled = true
+ }
+ }
+
+ rule {
+ name = "AWS-AWSManagedRulesKnownBadInputsRuleSet"
+ priority = 3
+
+ override_action {
+ none {}
+ }
+
+ statement {
+ managed_rule_group_statement {
+ name = "AWSManagedRulesKnownBadInputsRuleSet"
+ vendor_name = "AWS"
+ }
+ }
+
+ visibility_config {
+ cloudwatch_metrics_enabled = true
+ metric_name = "AWS-AWSManagedRulesKnownBadInputsRuleSet"
+ sampled_requests_enabled = true
+ }
+ }
+
+
+ visibility_config {
+ cloudwatch_metrics_enabled = true
+ metric_name = "waf-bsmsapp"
+ sampled_requests_enabled = true
+ }
+
+ tags = var.tags
+}
diff --git a/terraform/modules/waf/outputs.tf b/terraform/modules/waf/outputs.tf
new file mode 100644
index 0000000..ba58850
--- /dev/null
+++ b/terraform/modules/waf/outputs.tf
@@ -0,0 +1,8 @@
+# --------------------------------------------------------------------
+# WAF outputs
+# --------------------------------------------------------------------
+
+output "web_acl_arn" {
+ description = "The web ACL ARN."
+ value = aws_wafv2_web_acl.this.arn
+}
diff --git a/terraform/modules/waf/variables.tf b/terraform/modules/waf/variables.tf
new file mode 100644
index 0000000..b59c464
--- /dev/null
+++ b/terraform/modules/waf/variables.tf
@@ -0,0 +1,19 @@
+# ------------------------------------------------------------------------------
+# WAF variables
+# ------------------------------------------------------------------------------
+
+variable "name" {
+ description = "This is the human-readable name of the WAF."
+ type = string
+}
+
+variable "tags" {
+ description = "A mapping of tags to assign to all resources."
+ type = map(string)
+ default = {}
+}
+
+variable "scope" {
+ description = "WAF scope (cloudfront or regional)."
+ type = string
+}
\ No newline at end of file
diff --git a/terraform/modules/waf/versions.tf b/terraform/modules/waf/versions.tf
new file mode 100644
index 0000000..bceb8d0
--- /dev/null
+++ b/terraform/modules/waf/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.0.6"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 4.10.0"
+ }
+ }
+}
diff --git a/terraform/organization/apigw.tf b/terraform/organization/apigw.tf
index cea18da..31bce0d 100644
--- a/terraform/organization/apigw.tf
+++ b/terraform/organization/apigw.tf
@@ -9,7 +9,7 @@ module "apigw" {
module.lambda, module.sqs
]
- name = "AWSAPIGateway-g3"
+ name = "AWSAPIGateway-g3"
lambda = [
{
@@ -21,7 +21,7 @@ module "apigw" {
]
role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/LabRole"
- sqs_arn = "arn:aws:apigateway:${data.aws_region.current.name}:sqs:path/AWS-SQS-g3"
+ sqs_arn = "arn:aws:apigateway:${data.aws_region.current.name}:sqs:path/${module.sqs.name}"
tags = {
name = "api-gateway-g3"
diff --git a/terraform/organization/cloudfront.tf b/terraform/organization/cloudfront.tf
index a7fc8b1..0fe6479 100644
--- a/terraform/organization/cloudfront.tf
+++ b/terraform/organization/cloudfront.tf
@@ -1,12 +1,18 @@
module "cloudfront" {
- source = "../modules/cloudfront"
- depends_on = [module.s3, module.apigw]
+ source = "../modules/cloudfront"
providers = {
aws = aws.aws
}
- enabled = true
+ depends_on = [
+ module.s3,
+ module.apigw,
+ module.waf
+ ]
+
+ enabled = true
+ web_acl_id = module.waf.web_acl_arn
origin = {
api-gateway = {
diff --git a/terraform/organization/html/index.html b/terraform/organization/html/index.html
index ecc4a6c..3e27ca2 100644
--- a/terraform/organization/html/index.html
+++ b/terraform/organization/html/index.html
@@ -16,15 +16,15 @@
@@ -95,7 +95,11 @@
}
var el = document.getElementById("table");
- el.innerHTML = "";
+ if (!list.length) {
+ el.innerHTML = "No items."
+ } else {
+ el.innerHTML = "";
+ }
el.appendChild(table);
}
diff --git a/terraform/organization/locals.tf b/terraform/organization/locals.tf
index f9208b5..64e945e 100644
--- a/terraform/organization/locals.tf
+++ b/terraform/organization/locals.tf
@@ -4,9 +4,9 @@ locals {
s3 = {
website = {
- type = 1
+ type = 1
bucket_name = local.bucket_name
- bucket_acl = "public-read"
+ bucket_acl = "public-read"
path = "../resources"
website = {
@@ -35,18 +35,18 @@ locals {
website = {
redirect_all_requests_to = {
host_name = "${local.bucket_name}.s3-website-${data.aws_region.current.name}.amazonaws.com"
- protocol = "http"
+ protocol = "http"
}
}
bucket_name = "www.${local.bucket_name}"
- bucket_acl = "public-read"
+ bucket_acl = "public-read"
}
logs = {
- type = 2
+ type = 2
bucket_name = "${local.bucket_name}-logs"
- bucket_acl = "log-delivery-write"
+ bucket_acl = "log-delivery-write"
}
}
@@ -66,4 +66,25 @@ locals {
runtime = "python3.9"
}
}
+
+ private_inbound = [
+ {
+ rule_number = 100
+ rule_action = "allow"
+ from_port = 1024
+ to_port = 65535
+ protocol = "tcp"
+ cidr_block = "0.0.0.0/0"
+ }
+ ]
+ private_outbound = [
+ {
+ rule_number = 100
+ rule_action = "allow"
+ from_port = 443
+ to_port = 443
+ protocol = "tcp"
+ cidr_block = "0.0.0.0/0"
+ }
+ ]
}
diff --git a/terraform/organization/sqs.tf b/terraform/organization/sqs.tf
index 52c705a..28378d8 100644
--- a/terraform/organization/sqs.tf
+++ b/terraform/organization/sqs.tf
@@ -9,7 +9,7 @@ module "sqs" {
module.lambda
]
- name = "AWS-SQS-g3"
+ name = "AWS-SQS-g3"
lambda_name = module.lambda["lambdaSQS"].lambda_function_name
tags = {
diff --git a/terraform/organization/vpc.tf b/terraform/organization/vpc.tf
index e578349..1baa3e1 100644
--- a/terraform/organization/vpc.tf
+++ b/terraform/organization/vpc.tf
@@ -1,29 +1,6 @@
-locals {
- private_inbound = [
- {
- rule_number = 100
- rule_action = "allow"
- from_port = 1024
- to_port = 65535
- protocol = "tcp"
- cidr_block = "0.0.0.0/0"
- }
- ]
- private_outbound = [
- {
- rule_number = 100
- rule_action = "allow"
- from_port = 443
- to_port = 443
- protocol = "tcp"
- cidr_block = "0.0.0.0/0"
- }
- ]
-}
-
-################################################################################
+# ------------------------------------------------------------------------------
# VPC Module (from terraform-aws-modules)
-################################################################################
+# ------------------------------------------------------------------------------
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
@@ -47,9 +24,9 @@ module "vpc" {
manage_default_route_table = true
default_route_table_tags = { Name = "vpc-g3-bsmsapp-default" }
- private_dedicated_network_acl = true
- private_inbound_acl_rules = local.private_inbound
- private_outbound_acl_rules = local.private_outbound
+ private_dedicated_network_acl = true
+ private_inbound_acl_rules = local.private_inbound
+ private_outbound_acl_rules = local.private_outbound
manage_default_security_group = true
default_security_group_tags = { Name = "vpc-g3-bsmsapp-default" }
@@ -73,25 +50,21 @@ module "vpc_endpoints" {
endpoints = {
dynamodb = {
- service = "dynamodb"
- service_type = "Gateway"
- route_table_ids = flatten([module.vpc.private_route_table_ids])
- policy = data.aws_iam_policy_document.this.json
- tags = { Name = "dynamodb-vpc-endpoint" }
+ service = "dynamodb"
+ service_type = "Gateway"
+ route_table_ids = flatten([module.vpc.private_route_table_ids])
+ policy = data.aws_iam_policy_document.this.json
+ tags = { Name = "dynamodb-vpc-endpoint" }
security_group_ids = [aws_security_group.dynamodb_sg.id]
}
}
tags = {
- Name = "vpc-g3-bsmsapp"
+ Name = "vpc-g3-bsmsapp"
Endpoint = "true"
}
}
-################################################################################
-# Supporting Resources
-################################################################################
-
resource "aws_vpc_endpoint" "dynamodb_endpoint" {
vpc_id = module.vpc.vpc_id
service_name = "com.amazonaws.us-east-1.dynamodb"
@@ -108,10 +81,10 @@ resource "aws_security_group" "dynamodb_sg" {
vpc_id = module.vpc.vpc_id
egress {
- description = "HTTPs to DynamoDB"
- from_port = 443
- to_port = 443
- protocol = "tcp"
+ description = "HTTPs to DynamoDB"
+ from_port = 443
+ to_port = 443
+ protocol = "tcp"
prefix_list_ids = [aws_vpc_endpoint.dynamodb_endpoint.prefix_list_id]
}
diff --git a/terraform/organization/waf.tf b/terraform/organization/waf.tf
new file mode 100644
index 0000000..6c2bc33
--- /dev/null
+++ b/terraform/organization/waf.tf
@@ -0,0 +1,14 @@
+module "waf" {
+ source = "../modules/waf"
+
+ providers = {
+ aws = aws.aws
+ }
+
+ name = "AWS-WAF-g3"
+ scope = "CLOUDFRONT"
+
+ tags = {
+ name = "WAF"
+ }
+}