Initial commit: AWS CloudFront with OpenTofu infrastructure

- Complete CloudFront distribution setup with origin.servidor.it.com
- WAF v2 integration for security protection
- S3 backend for Terraform state management
- CloudFront logging to S3
- HTTP-only origin protocol configuration (resolves 504 Gateway Timeout)
- Comprehensive documentation with deployment guide

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
kappa
2025-09-09 09:08:17 +09:00
commit 210c454359
12 changed files with 1386 additions and 0 deletions

224
main.tf Normal file
View File

@@ -0,0 +1,224 @@
# CloudFront Origin Access Control
resource "aws_cloudfront_origin_access_control" "oac" {
name = "${var.project_name}-${var.environment}-oac"
description = "OAC for ${var.project_name}"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
# CloudFront Distribution
resource "aws_cloudfront_distribution" "main" {
# Origin configuration for custom domain
origin {
domain_name = var.origin_domain
origin_id = "${var.project_name}-${var.environment}-origin"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = var.origin_protocol_policy
origin_ssl_protocols = ["TLSv1.2"]
origin_read_timeout = 30
origin_keepalive_timeout = 5
}
# Custom headers (optional)
# custom_header {
# name = "User-Agent"
# value = "CloudFront-${var.project_name}"
# }
}
enabled = true
is_ipv6_enabled = true
comment = "CloudFront distribution for ${var.project_name} - ${var.environment}"
default_root_object = "index.html"
# Aliases (custom domain names) - Disabled for default certificate
# aliases = var.cloudfront_aliases
# Default cache behavior
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "${var.project_name}-${var.environment}-origin"
cache_policy_id = var.cache_policy_id
origin_request_policy_id = var.origin_request_policy_id
viewer_protocol_policy = var.viewer_protocol_policy
compress = true
# Forward headers, query strings, and cookies
# Use cache policies instead for better performance
}
# Ordered cache behaviors (optional)
ordered_cache_behavior {
path_pattern = "/api/*"
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "${var.project_name}-${var.environment}-origin"
cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" # CachingDisabled
viewer_protocol_policy = "https-only"
compress = true
}
# Price class
price_class = var.price_class
# Geographic restrictions
restrictions {
geo_restriction {
restriction_type = "none"
# locations = []
}
}
# SSL/TLS certificate - Use CloudFront default certificate (temporary)
viewer_certificate {
cloudfront_default_certificate = true
}
# Custom error responses
custom_error_response {
error_code = 404
response_code = 200
response_page_path = "/index.html"
error_caching_min_ttl = 300
}
custom_error_response {
error_code = 403
response_code = 200
response_page_path = "/index.html"
error_caching_min_ttl = 300
}
# Web Application Firewall (optional)
web_acl_id = var.enable_waf ? aws_wafv2_web_acl.cloudfront[0].arn : null
# Logging configuration
dynamic "logging_config" {
for_each = var.enable_cloudfront_logging ? [1] : []
content {
bucket = "${var.cloudfront_logs_bucket}.s3.amazonaws.com"
prefix = var.cloudfront_logs_prefix
include_cookies = false
}
}
tags = {
Name = "${var.project_name}-${var.environment}-distribution"
Origin = var.origin_domain
}
}
# CloudFormation Stack (optional - for additional AWS resources)
resource "aws_cloudformation_stack" "network" {
count = var.enable_cloudformation_stack ? 1 : 0
name = "${var.project_name}-${var.environment}-network-stack"
parameters = {
VPCCidr = "10.0.0.0/16"
Environment = var.environment
ProjectName = var.project_name
}
template_body = jsonencode({
AWSTemplateFormatVersion = "2010-09-09"
Description = "Network resources for ${var.project_name}"
Parameters = {
VPCCidr = {
Type = "String"
Default = "10.0.0.0/16"
Description = "CIDR block for the VPC"
}
Environment = {
Type = "String"
Description = "Environment name"
}
ProjectName = {
Type = "String"
Description = "Project name"
}
}
Resources = {
VPC = {
Type = "AWS::EC2::VPC"
Properties = {
CidrBlock = { Ref = "VPCCidr" }
EnableDnsHostnames = true
EnableDnsSupport = true
Tags = [
{
Key = "Name"
Value = { "Fn::Sub" = "$${ProjectName}-$${Environment}-vpc" }
}
]
}
}
InternetGateway = {
Type = "AWS::EC2::InternetGateway"
Properties = {
Tags = [
{
Key = "Name"
Value = { "Fn::Sub" = "$${ProjectName}-$${Environment}-igw" }
}
]
}
}
AttachGateway = {
Type = "AWS::EC2::VPCGatewayAttachment"
Properties = {
VpcId = { Ref = "VPC" }
InternetGatewayId = { Ref = "InternetGateway" }
}
}
PublicSubnet = {
Type = "AWS::EC2::Subnet"
Properties = {
VpcId = { Ref = "VPC" }
CidrBlock = "10.0.1.0/24"
AvailabilityZone = { "Fn::Select" = [0, { "Fn::GetAZs" = "" }] }
MapPublicIpOnLaunch = true
Tags = [
{
Key = "Name"
Value = { "Fn::Sub" = "$${ProjectName}-$${Environment}-public-subnet" }
}
]
}
}
}
Outputs = {
VPCId = {
Description = "VPC ID"
Value = { Ref = "VPC" }
Export = {
Name = { "Fn::Sub" = "$${ProjectName}-$${Environment}-VPC-ID" }
}
}
PublicSubnetId = {
Description = "Public Subnet ID"
Value = { Ref = "PublicSubnet" }
Export = {
Name = { "Fn::Sub" = "$${ProjectName}-$${Environment}-PublicSubnet-ID" }
}
}
}
})
capabilities = ["CAPABILITY_IAM"]
tags = {
Name = "${var.project_name}-${var.environment}-network"
ManagedBy = "OpenTofu"
}
}