Initial commit: Terraform infrastructure, pipelines, docs and scripts
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
bucket = "ccsoft-terraform-state-739086995772"
|
||||
key = "proyectosacc/terraform.tfstate"
|
||||
region = "mx-central-1"
|
||||
encrypt = true
|
||||
dynamodb_table = "terraform-locks-proyectosacc-prod"
|
||||
@@ -0,0 +1,21 @@
|
||||
# ===============================================================================================================
|
||||
# backend.tf - Configuración del backend de estado para proyectosacc
|
||||
# Descripción:
|
||||
# Configura el backend remoto de Terraform en S3 para estado compartido.
|
||||
#
|
||||
# Uso:
|
||||
# - DEV (default): terraform init
|
||||
# - PROD: terraform init -backend-config=backend.prod.hcl
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
terraform {
|
||||
backend "s3" {
|
||||
bucket = "ccsoft-terraform-state"
|
||||
key = "proyectosacc/terraform.tfstate"
|
||||
region = "mx-central-1"
|
||||
encrypt = true
|
||||
dynamodb_table = "terraform-locks"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# ===============================================================================================================
|
||||
# dev.tfvars - Variables de ambiente develop para proyectosacc
|
||||
# Descripción:
|
||||
# Valores representativos para el ambiente de desarrollo.
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
# Nota: mx-central-1 es una región opt-in. Debe estar habilitada en la cuenta de AWS antes del despliegue.
|
||||
|
||||
environment = "dev"
|
||||
aws_region = "mx-central-1"
|
||||
vpc_cidr = "10.1.0.0/16"
|
||||
availability_zones = ["mx-central-1a", "mx-central-1b"]
|
||||
ec2_instance_type = "t3.small"
|
||||
ec2_key_name = "ccsoft-dev-key"
|
||||
pipeline_public_key = "ssh-ed25519 AAAAC3NzaC... bitbucket.pipeline.ci.cd.proyectosacc.thoth.develop@computocontable.com"
|
||||
db_instance_class = "db.t3.micro"
|
||||
db_name = "sacc_db_dev"
|
||||
db_username = "sacc_admin_dev"
|
||||
db_password = "<cambiar-por-secret-real>"
|
||||
s3_frontend_bucket = "ccsoft-proyectosacc-frontend-dev"
|
||||
s3_artifacts_bucket = "ccsoft-proyectosacc-artifacts-dev"
|
||||
cloudfront_price_class = "PriceClass_100"
|
||||
@@ -0,0 +1,24 @@
|
||||
# ===============================================================================================================
|
||||
# prod.tfvars - Variables de ambiente producción para proyectosacc
|
||||
# Descripción:
|
||||
# Valores representativos para el ambiente de producción.
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
# Nota: mx-central-1 es una región opt-in. Debe estar habilitada en la cuenta de AWS antes del despliegue.
|
||||
|
||||
environment = "prod"
|
||||
aws_region = "mx-central-1"
|
||||
vpc_cidr = "10.2.0.0/16"
|
||||
availability_zones = ["mx-central-1a", "mx-central-1b"]
|
||||
ec2_instance_type = "t3.small"
|
||||
ec2_key_name = "ccsoft-prod-key"
|
||||
pipeline_public_key = "ssh-ed25519 AAAAC3NzaC... bitbucket.pipeline.ci.cd.proyectosacc.thoth.prod@computocontable.com"
|
||||
db_instance_class = "db.t3.micro"
|
||||
db_name = "sacc_db_prod"
|
||||
db_username = "sacc_admin_prod"
|
||||
db_password = "<cambiar-por-secret-real>"
|
||||
s3_frontend_bucket = "ccsoft-proyectosacc-frontend-prod"
|
||||
s3_artifacts_bucket = "ccsoft-proyectosacc-artifacts-prod"
|
||||
cloudfront_price_class = "PriceClass_100"
|
||||
@@ -0,0 +1,576 @@
|
||||
# ===============================================================================================================
|
||||
# main.tf - Recursos principales de infraestructura para proyectosacc
|
||||
# Descripción:
|
||||
# Crea VPC, EC2, RDS, S3, CloudFront, Route 53, ACM e IAM para la
|
||||
# arquitectura híbrida S3+CloudFront+EC2 de SACC.
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# VPC y Networking
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_vpc" "main" {
|
||||
cidr_block = var.vpc_cidr
|
||||
enable_dns_support = true
|
||||
enable_dns_hostnames = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-vpc-${var.environment}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_internet_gateway" "main" {
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-igw-${var.environment}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "public" {
|
||||
count = length(var.availability_zones)
|
||||
vpc_id = aws_vpc.main.id
|
||||
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
|
||||
availability_zone = var.availability_zones[count.index]
|
||||
map_public_ip_on_launch = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-public-${var.availability_zones[count.index]}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "private" {
|
||||
count = length(var.availability_zones)
|
||||
vpc_id = aws_vpc.main.id
|
||||
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + 10)
|
||||
availability_zone = var.availability_zones[count.index]
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-private-${var.availability_zones[count.index]}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_eip" "nat" {
|
||||
domain = "vpc"
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-nat-eip-${var.environment}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_nat_gateway" "main" {
|
||||
allocation_id = aws_eip.nat.id
|
||||
subnet_id = aws_subnet.public[0].id
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-nat-${var.environment}"
|
||||
}
|
||||
|
||||
depends_on = [aws_internet_gateway.main]
|
||||
}
|
||||
|
||||
resource "aws_route_table" "public" {
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
route {
|
||||
cidr_block = "0.0.0.0/0"
|
||||
gateway_id = aws_internet_gateway.main.id
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-public-rt-${var.environment}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route_table_association" "public" {
|
||||
count = length(aws_subnet.public)
|
||||
subnet_id = aws_subnet.public[count.index].id
|
||||
route_table_id = aws_route_table.public.id
|
||||
}
|
||||
|
||||
resource "aws_route_table" "private" {
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
route {
|
||||
cidr_block = "0.0.0.0/0"
|
||||
nat_gateway_id = aws_nat_gateway.main.id
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-private-rt-${var.environment}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route_table_association" "private" {
|
||||
count = length(aws_subnet.private)
|
||||
subnet_id = aws_subnet.private[count.index].id
|
||||
route_table_id = aws_route_table.private.id
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Security Groups
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_security_group" "ec2_api" {
|
||||
name_prefix = "${var.project_name}-ec2-api-"
|
||||
vpc_id = aws_vpc.main.id
|
||||
description = "Security Group para la API backend de ${var.project_name}"
|
||||
|
||||
ingress {
|
||||
description = "SSH desde IPs confiables"
|
||||
from_port = 22
|
||||
to_port = 22
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["10.0.0.0/8"] # Ajustar a IP/VPN real del pipeline
|
||||
}
|
||||
|
||||
ingress {
|
||||
description = "HTTP API"
|
||||
from_port = 80
|
||||
to_port = 80
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
description = "HTTPS API"
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
description = "API backend directo"
|
||||
from_port = 8080
|
||||
to_port = 8080
|
||||
protocol = "tcp"
|
||||
cidr_blocks = [aws_vpc.main.cidr_block]
|
||||
}
|
||||
|
||||
egress {
|
||||
description = "Salida libre"
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-sg-ec2-api"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group" "rds" {
|
||||
name_prefix = "${var.project_name}-rds-"
|
||||
vpc_id = aws_vpc.main.id
|
||||
description = "Security Group para RDS MariaDB de ${var.project_name}"
|
||||
|
||||
ingress {
|
||||
description = "MariaDB desde EC2 API"
|
||||
from_port = 3306
|
||||
to_port = 3306
|
||||
protocol = "tcp"
|
||||
security_groups = [aws_security_group.ec2_api.id]
|
||||
}
|
||||
|
||||
egress {
|
||||
description = "Salida libre"
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-sg-rds"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# IAM Role / Instance Profile para EC2
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_iam_role" "ec2_role" {
|
||||
name = "${var.project_name}-ec2-role-${var.environment}"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [{
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "ec2.amazonaws.com"
|
||||
}
|
||||
Action = "sts:AssumeRole"
|
||||
}]
|
||||
})
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-ec2-role"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "ec2_policy" {
|
||||
name = "${var.project_name}-ec2-policy-${var.environment}"
|
||||
role = aws_iam_role.ec2_role.id
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"s3:GetObject",
|
||||
"s3:ListBucket"
|
||||
]
|
||||
Resource = [
|
||||
aws_s3_bucket.artifacts.arn,
|
||||
"${aws_s3_bucket.artifacts.arn}/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents"
|
||||
]
|
||||
Resource = "arn:aws:logs:*:*:*"
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"cloudfront:CreateInvalidation"
|
||||
]
|
||||
Resource = "*"
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_iam_instance_profile" "ec2_profile" {
|
||||
name = "${var.project_name}-ec2-profile-${var.environment}"
|
||||
role = aws_iam_role.ec2_role.name
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-ec2-profile"
|
||||
}
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# EC2 (API Backend)
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_instance" "api" {
|
||||
ami = var.ec2_ami
|
||||
instance_type = var.ec2_instance_type
|
||||
subnet_id = aws_subnet.public[0].id
|
||||
vpc_security_group_ids = [aws_security_group.ec2_api.id]
|
||||
iam_instance_profile = aws_iam_instance_profile.ec2_profile.name
|
||||
key_name = var.ec2_key_name
|
||||
|
||||
root_block_device {
|
||||
volume_type = "gp3"
|
||||
volume_size = var.ec2_root_volume_size
|
||||
encrypted = true
|
||||
delete_on_termination = true
|
||||
}
|
||||
|
||||
user_data = base64encode(templatefile("${path.module}/user-data.sh", {
|
||||
pipeline_public_key = var.pipeline_public_key
|
||||
}))
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-api-${var.environment}"
|
||||
Environment = var.environment
|
||||
}
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# RDS MariaDB
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_db_subnet_group" "rds" {
|
||||
name = "${var.project_name}-rds-subnet-group-${var.environment}"
|
||||
subnet_ids = aws_subnet.private[*].id
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-rds-subnet-group"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_db_instance" "main" {
|
||||
identifier = "${var.project_name}-db-${var.environment}"
|
||||
engine = var.db_engine
|
||||
engine_version = var.db_engine_version
|
||||
instance_class = var.db_instance_class
|
||||
allocated_storage = var.db_allocated_storage
|
||||
storage_type = "gp3"
|
||||
storage_encrypted = true
|
||||
db_name = var.db_name
|
||||
username = var.db_username
|
||||
password = var.db_password
|
||||
db_subnet_group_name = aws_db_subnet_group.rds.name
|
||||
vpc_security_group_ids = [aws_security_group.rds.id]
|
||||
publicly_accessible = false
|
||||
skip_final_snapshot = true
|
||||
backup_retention_period = 7
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-rds"
|
||||
Environment = var.environment
|
||||
}
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# S3 Buckets
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_s3_bucket" "frontend" {
|
||||
bucket = var.s3_frontend_bucket
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-frontend"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_versioning" "frontend" {
|
||||
bucket = aws_s3_bucket.frontend.id
|
||||
|
||||
versioning_configuration {
|
||||
status = "Enabled"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_public_access_block" "frontend" {
|
||||
bucket = aws_s3_bucket.frontend.id
|
||||
|
||||
block_public_acls = true
|
||||
block_public_policy = true
|
||||
ignore_public_acls = true
|
||||
restrict_public_buckets = true
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_website_configuration" "frontend" {
|
||||
bucket = aws_s3_bucket.frontend.id
|
||||
|
||||
index_document {
|
||||
suffix = "index.html"
|
||||
}
|
||||
|
||||
error_document {
|
||||
key = "index.html"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket" "artifacts" {
|
||||
bucket = var.s3_artifacts_bucket
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-artifacts"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_versioning" "artifacts" {
|
||||
bucket = aws_s3_bucket.artifacts.id
|
||||
|
||||
versioning_configuration {
|
||||
status = "Enabled"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_public_access_block" "artifacts" {
|
||||
bucket = aws_s3_bucket.artifacts.id
|
||||
|
||||
block_public_acls = true
|
||||
block_public_policy = true
|
||||
ignore_public_acls = true
|
||||
restrict_public_buckets = true
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# CloudFront Origin Access Control
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_cloudfront_origin_access_control" "frontend" {
|
||||
name = "${var.project_name}-oac-${var.environment}"
|
||||
description = "OAC para bucket frontend de ${var.project_name}"
|
||||
origin_access_control_origin_type = "s3"
|
||||
signing_behavior = "always"
|
||||
signing_protocol = "sigv4"
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_policy" "frontend" {
|
||||
bucket = aws_s3_bucket.frontend.id
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [{
|
||||
Sid = "AllowCloudFrontOAC"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "cloudfront.amazonaws.com"
|
||||
}
|
||||
Action = "s3:GetObject"
|
||||
Resource = "${aws_s3_bucket.frontend.arn}/*"
|
||||
Condition = {
|
||||
StringEquals = {
|
||||
"AWS:SourceArn" = aws_cloudfront_distribution.main.arn
|
||||
}
|
||||
}
|
||||
}]
|
||||
})
|
||||
|
||||
depends_on = [aws_s3_bucket_public_access_block.frontend]
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# ACM Certificate (us-east-1 obligatorio para CloudFront)
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_acm_certificate" "main" {
|
||||
provider = aws.us_east_1
|
||||
domain_name = var.domain_name
|
||||
validation_method = "DNS"
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-cert"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route53_record" "cert_validation" {
|
||||
for_each = {
|
||||
for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
|
||||
name = dvo.resource_record_name
|
||||
record = dvo.resource_record_value
|
||||
type = dvo.resource_record_type
|
||||
}
|
||||
}
|
||||
|
||||
allow_overwrite = true
|
||||
name = each.value.name
|
||||
records = [each.value.record]
|
||||
ttl = 60
|
||||
type = each.value.type
|
||||
zone_id = data.aws_route53_zone.main.zone_id
|
||||
}
|
||||
|
||||
resource "aws_acm_certificate_validation" "main" {
|
||||
provider = aws.us_east_1
|
||||
certificate_arn = aws_acm_certificate.main.arn
|
||||
validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Route 53
|
||||
# -------------------------------------------------------------------------------
|
||||
data "aws_route53_zone" "main" {
|
||||
name = "ccsoft.mx"
|
||||
private_zone = false
|
||||
}
|
||||
|
||||
resource "aws_route53_record" "main" {
|
||||
zone_id = data.aws_route53_zone.main.zone_id
|
||||
name = var.domain_name
|
||||
type = "A"
|
||||
|
||||
alias {
|
||||
name = aws_cloudfront_distribution.main.domain_name
|
||||
zone_id = aws_cloudfront_distribution.main.hosted_zone_id
|
||||
evaluate_target_health = false
|
||||
}
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# CloudFront Distribution
|
||||
# -------------------------------------------------------------------------------
|
||||
resource "aws_cloudfront_distribution" "main" {
|
||||
enabled = true
|
||||
is_ipv6_enabled = true
|
||||
comment = "CDN para ${var.project_name}"
|
||||
default_root_object = "index.html"
|
||||
aliases = [var.domain_name]
|
||||
price_class = var.cloudfront_price_class
|
||||
|
||||
origin {
|
||||
domain_name = aws_s3_bucket.frontend.bucket_regional_domain_name
|
||||
origin_id = "saccS3Origin"
|
||||
origin_access_control_id = aws_cloudfront_origin_access_control.frontend.id
|
||||
}
|
||||
|
||||
origin {
|
||||
domain_name = aws_instance.api.public_dns
|
||||
origin_id = "saccApiOrigin"
|
||||
|
||||
custom_origin_config {
|
||||
http_port = 80
|
||||
https_port = 443
|
||||
origin_protocol_policy = "http-only"
|
||||
origin_ssl_protocols = ["TLSv1.2"]
|
||||
}
|
||||
}
|
||||
|
||||
default_cache_behavior {
|
||||
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
|
||||
cached_methods = ["GET", "HEAD"]
|
||||
target_origin_id = "saccS3Origin"
|
||||
viewer_protocol_policy = "redirect-to-https"
|
||||
compress = true
|
||||
|
||||
forwarded_values {
|
||||
query_string = false
|
||||
cookies {
|
||||
forward = "none"
|
||||
}
|
||||
}
|
||||
|
||||
min_ttl = 0
|
||||
default_ttl = 3600
|
||||
max_ttl = 86400
|
||||
}
|
||||
|
||||
ordered_cache_behavior {
|
||||
path_pattern = "/api/*"
|
||||
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
|
||||
cached_methods = ["GET", "HEAD"]
|
||||
target_origin_id = "saccApiOrigin"
|
||||
viewer_protocol_policy = "redirect-to-https"
|
||||
compress = true
|
||||
|
||||
forwarded_values {
|
||||
query_string = true
|
||||
headers = ["Origin", "Access-Control-Request-Headers", "Access-Control-Request-Method"]
|
||||
cookies {
|
||||
forward = "all"
|
||||
}
|
||||
}
|
||||
|
||||
min_ttl = 0
|
||||
default_ttl = 0
|
||||
max_ttl = 0
|
||||
}
|
||||
|
||||
restrictions {
|
||||
geo_restriction {
|
||||
restriction_type = "none"
|
||||
}
|
||||
}
|
||||
|
||||
viewer_certificate {
|
||||
acm_certificate_arn = aws_acm_certificate_validation.main.certificate_arn
|
||||
ssl_support_method = "sni-only"
|
||||
minimum_protocol_version = "TLSv1.2_2021"
|
||||
}
|
||||
|
||||
depends_on = [aws_acm_certificate_validation.main]
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-cdn"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
# ===============================================================================================================
|
||||
# outputs.tf - Outputs de infraestructura para proyectosacc
|
||||
# Descripción:
|
||||
# Expone información útil de los recursos creados por Terraform.
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
output "ec2_public_ip" {
|
||||
description = "IP pública del servidor de la API"
|
||||
value = aws_instance.api.public_ip
|
||||
}
|
||||
|
||||
output "ec2_public_dns" {
|
||||
description = "DNS público del servidor de la API"
|
||||
value = aws_instance.api.public_dns
|
||||
}
|
||||
|
||||
output "rds_endpoint" {
|
||||
description = "Endpoint de conexión a la base de datos"
|
||||
value = aws_db_instance.main.endpoint
|
||||
}
|
||||
|
||||
output "s3_frontend_bucket" {
|
||||
description = "Nombre del bucket S3 del frontend React"
|
||||
value = aws_s3_bucket.frontend.bucket
|
||||
}
|
||||
|
||||
output "s3_artifacts_bucket" {
|
||||
description = "Nombre del bucket S3 de artefactos de la API"
|
||||
value = aws_s3_bucket.artifacts.bucket
|
||||
}
|
||||
|
||||
output "cloudfront_domain" {
|
||||
description = "Dominio de la distribución CloudFront"
|
||||
value = aws_cloudfront_distribution.main.domain_name
|
||||
}
|
||||
|
||||
output "cloudfront_distribution_id" {
|
||||
description = "ID de la distribución CloudFront"
|
||||
value = aws_cloudfront_distribution.main.id
|
||||
}
|
||||
|
||||
output "route53_record" {
|
||||
description = "Registro DNS creado en Route 53"
|
||||
value = aws_route53_record.main.name
|
||||
}
|
||||
|
||||
output "acm_certificate_arn" {
|
||||
description = "ARN del certificado SSL en ACM"
|
||||
value = aws_acm_certificate.main.arn
|
||||
}
|
||||
|
||||
output "vpc_id" {
|
||||
description = "ID de la VPC creada"
|
||||
value = aws_vpc.main.id
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
# ===============================================================================================================
|
||||
# provider.tf - Configuración del proveedor AWS para proyectosacc
|
||||
# Descripción:
|
||||
# Define la región y versiones del provider AWS para Terraform.
|
||||
#
|
||||
# Uso:
|
||||
# terraform init
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = var.aws_region
|
||||
|
||||
default_tags {
|
||||
tags = {
|
||||
Project = var.project_name
|
||||
ManagedBy = "terraform"
|
||||
Environment = var.environment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Provider exclusivo para ACM en us-east-1 (requerido por CloudFront)
|
||||
provider "aws" {
|
||||
alias = "us_east_1"
|
||||
region = "us-east-1"
|
||||
|
||||
default_tags {
|
||||
tags = {
|
||||
Project = var.project_name
|
||||
ManagedBy = "terraform"
|
||||
Environment = var.environment
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+122
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env bash
|
||||
# ===============================================================================================================
|
||||
# user-data.sh - Script de inicialización de la EC2 para proyectosacc
|
||||
# Descripción:
|
||||
# Configura la instancia EC2 al primer boot: instala dependencias,
|
||||
# crea usuarios, configura Nginx como proxy de API, y prepara
|
||||
# directorios de despliegue.
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Variables
|
||||
# -------------------------------------------------------------------------------
|
||||
PIPELINE_PUBLIC_KEY="${pipeline_public_key}"
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Actualizar sistema e instalar dependencias
|
||||
# -------------------------------------------------------------------------------
|
||||
apt-get update -y
|
||||
apt-get install -y nginx openjdk-21-jdk awscli curl jq
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Crear usuarios del sistema
|
||||
# -------------------------------------------------------------------------------
|
||||
useradd -m -s /bin/bash thoth || true
|
||||
useradd -m -s /bin/bash osiris || true
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Configurar SSH para el pipeline (usuario thoth)
|
||||
# -------------------------------------------------------------------------------
|
||||
mkdir -p /home/thoth/.ssh
|
||||
chmod 700 /home/thoth/.ssh
|
||||
|
||||
echo "$PIPELINE_PUBLIC_KEY" > /home/thoth/.ssh/authorized_keys
|
||||
chmod 600 /home/thoth/.ssh/authorized_keys
|
||||
chown -R thoth:thoth /home/thoth/.ssh
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Crear estructura de directorios de despliegue
|
||||
# -------------------------------------------------------------------------------
|
||||
mkdir -p /home/thoth/deploy/artifacts/{backup,current,logs,pids}
|
||||
mkdir -p /home/thoth/deploy/{scripts,setup}
|
||||
chown -R thoth:thoth /home/thoth/deploy
|
||||
|
||||
mkdir -p /var/log/proyectosacc/proyectosacc-app
|
||||
chown -R osiris:osiris /var/log/proyectosacc
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Configurar Nginx como proxy inverso SOLO para la API
|
||||
# -------------------------------------------------------------------------------
|
||||
cat > /etc/nginx/sites-available/proyectosacc-api <<'NGINX_EOF'
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
server_name _;
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://localhost:8080/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
NGINX_EOF
|
||||
|
||||
rm -f /etc/nginx/sites-enabled/default
|
||||
ln -sf /etc/nginx/sites-available/proyectosacc-api /etc/nginx/sites-enabled/proyectosacc-api
|
||||
|
||||
nginx -t
|
||||
systemctl enable nginx
|
||||
systemctl restart nginx
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Crear servicio systemd template para la API (será sobrescrito por deploy.sh)
|
||||
# -------------------------------------------------------------------------------
|
||||
cat > /etc/systemd/system/proyectosacc-app.service <<'SYSTEMD_EOF'
|
||||
[Unit]
|
||||
Description=Proyecto SACC App Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=osiris
|
||||
Group=osiris
|
||||
WorkingDirectory=/home/thoth/deploy/artifacts/current
|
||||
ExecStart=/usr/bin/java -jar /home/thoth/deploy/artifacts/current/proyectosacc-app.jar
|
||||
SuccessExitStatus=143
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
StandardOutput=append:/var/log/proyectosacc/proyectosacc-app/proyectosacc-app-service.log
|
||||
StandardError=append:/var/log/proyectosacc/proyectosacc-app/proyectosacc-app-service.log
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
SYSTEMD_EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable proyectosacc-app.service || true
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Ajustar permisos finales
|
||||
# -------------------------------------------------------------------------------
|
||||
usermod -aG osiris thoth || true
|
||||
chown -R osiris:osiris /home/thoth/deploy/artifacts
|
||||
chmod 750 /home/thoth/deploy/artifacts
|
||||
@@ -0,0 +1,148 @@
|
||||
# ===============================================================================================================
|
||||
# variables.tf - Variables de infraestructura para proyectosacc
|
||||
# Descripción:
|
||||
# Define todas las variables parametrizables de la infraestructura AWS.
|
||||
#
|
||||
# Autor: Área de Tecnología y Desarrollo - CCsoft
|
||||
# ===============================================================================================================
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Generales
|
||||
# -------------------------------------------------------------------------------
|
||||
variable "aws_region" {
|
||||
description = "Región principal de AWS"
|
||||
type = string
|
||||
default = "mx-central-1"
|
||||
}
|
||||
|
||||
variable "project_name" {
|
||||
description = "Nombre del proyecto"
|
||||
type = string
|
||||
default = "proyectosacc"
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
description = "Ambiente de despliegue (dev, uat, prod)"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "domain_name" {
|
||||
description = "Dominio principal de la aplicación"
|
||||
type = string
|
||||
default = "sacc.ccsoft.mx"
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Red
|
||||
# -------------------------------------------------------------------------------
|
||||
variable "vpc_cidr" {
|
||||
description = "CIDR block de la VPC"
|
||||
type = string
|
||||
default = "10.0.0.0/16"
|
||||
}
|
||||
|
||||
variable "availability_zones" {
|
||||
description = "Zonas de disponibilidad a utilizar"
|
||||
type = list(string)
|
||||
default = ["mx-central-1a", "mx-central-1b"]
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# EC2 (API Backend)
|
||||
# -------------------------------------------------------------------------------
|
||||
variable "ec2_instance_type" {
|
||||
description = "Tipo de instancia EC2 para la API"
|
||||
type = string
|
||||
default = "t3.small"
|
||||
}
|
||||
|
||||
variable "ec2_ami" {
|
||||
description = "AMI de Ubuntu 22.04 LTS"
|
||||
type = string
|
||||
# AMI oficial de Ubuntu 22.04 LTS en mx-central-1 (validada: 2026-04-10)
|
||||
default = "ami-09289f290e76061f8"
|
||||
}
|
||||
|
||||
variable "ec2_root_volume_size" {
|
||||
description = "Tamaño del volumen raíz en GB"
|
||||
type = number
|
||||
default = 20
|
||||
}
|
||||
|
||||
variable "ec2_key_name" {
|
||||
description = "Nombre del Key Pair SSH para acceso inicial (administrado externamente)"
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "pipeline_public_key" {
|
||||
description = "Llave pública SSH del pipeline CI/CD (usuario thoth)"
|
||||
type = string
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# RDS (Base de datos)
|
||||
# -------------------------------------------------------------------------------
|
||||
variable "db_instance_class" {
|
||||
description = "Clase de instancia RDS"
|
||||
type = string
|
||||
default = "db.t3.micro"
|
||||
}
|
||||
|
||||
variable "db_engine" {
|
||||
description = "Motor de base de datos"
|
||||
type = string
|
||||
default = "mariadb"
|
||||
}
|
||||
|
||||
variable "db_engine_version" {
|
||||
description = "Versión del motor de base de datos"
|
||||
type = string
|
||||
default = "10.11"
|
||||
}
|
||||
|
||||
variable "db_name" {
|
||||
description = "Nombre de la base de datos inicial"
|
||||
type = string
|
||||
default = "sacc_db"
|
||||
}
|
||||
|
||||
variable "db_username" {
|
||||
description = "Usuario administrador de la base de datos"
|
||||
type = string
|
||||
default = "sacc_admin"
|
||||
}
|
||||
|
||||
variable "db_password" {
|
||||
description = "Contraseña del usuario administrador de la base de datos"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "db_allocated_storage" {
|
||||
description = "Almacenamiento asignado a RDS en GB"
|
||||
type = number
|
||||
default = 20
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# S3
|
||||
# -------------------------------------------------------------------------------
|
||||
variable "s3_frontend_bucket" {
|
||||
description = "Nombre del bucket S3 para el frontend React"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "s3_artifacts_bucket" {
|
||||
description = "Nombre del bucket S3 para artefactos de la API"
|
||||
type = string
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# CloudFront / ACM
|
||||
# -------------------------------------------------------------------------------
|
||||
variable "cloudfront_price_class" {
|
||||
description = "Clase de precio de CloudFront"
|
||||
type = string
|
||||
default = "PriceClass_100"
|
||||
}
|
||||
Reference in New Issue
Block a user