~ajk/santas-little-helper

5cb387eed5a40a30899ee5423a1dfb3587bc2335 — Andrew Kay 9 months ago f5bd6bc
Terraform configuration
3 files changed, 199 insertions(+), 0 deletions(-)

A terraform/.gitignore
A terraform/main.tf
A terraform/versions.tf
A terraform/.gitignore => terraform/.gitignore +29 -0
@@ 0,0 1,29 @@
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log

# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
#
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

A terraform/main.tf => terraform/main.tf +155 -0
@@ 0,0 1,155 @@
provider "aws" {
  region = "us-east-1"
}

variable "zone_id" {
  default = "Z1GYWJFJ4NHMBW"
}

variable "web_domain" {
  default = "santa.ajk.me"
}

variable "certificate_arn" {
  default = "arn:aws:acm:us-east-1:953259464456:certificate/e956f431-f394-45cf-9841-ca2ac1f76e89"
}

locals {
  default_aws_tags = {
    "Application" : "santas-little-helper"
  }
}

resource "aws_s3_bucket" "web" {
  bucket = var.web_domain

  website {
    index_document = "index.html"
    error_document = "error.html"
  }

  tags = local.default_aws_tags
}

resource "aws_s3_bucket_policy" "web" {
  bucket = aws_s3_bucket.web.id
  policy = data.aws_iam_policy_document.web_public_access.json
}

data "aws_iam_policy_document" "web_public_access" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["${aws_s3_bucket.web.arn}/*"]

    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
  }
}

resource "aws_cloudfront_distribution" "web_distribution" {
  origin {
    domain_name = aws_s3_bucket.web.website_endpoint
    origin_id   = "S3-${var.web_domain}"

    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "http-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }

  aliases = [var.web_domain]

  enabled         = true
  is_ipv6_enabled = true

  default_root_object = "index.html"

  custom_error_response {
    error_code         = 404
    response_code      = 200
    response_page_path = "/index.html"
  }

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "S3-${var.web_domain}"

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "redirect-to-https"
    compress               = true
  }

  viewer_certificate {
    acm_certificate_arn      = var.certificate_arn
    ssl_support_method       = "sni-only"
    minimum_protocol_version = "TLSv1.1_2016"
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  tags = local.default_aws_tags
}

resource "aws_route53_record" "web_dns" {
  zone_id = var.zone_id
  name    = var.web_domain
  type    = "A"

  alias {
    name                   = aws_cloudfront_distribution.web_distribution.domain_name
    zone_id                = aws_cloudfront_distribution.web_distribution.hosted_zone_id
    evaluate_target_health = false
  }
}

resource "heroku_app" "api" {
  name       = "slh-api"
  region     = "us"
  stack      = "heroku-20"
  buildpacks = ["heroku/python"]
  config_vars = {
    JWKS_URL     = "https://andrewjk.auth0.com/.well-known/jwks.json"
    JWT_AUDIENCE = "slh-api"
  }
}

resource "heroku_addon" "database" {
  app  = heroku_app.api.id
  plan = "heroku-postgresql:hobby-dev"
}

resource "heroku_build" "api" {
  app = heroku_app.api.id
  source = {
    path = "../api-flask"
  }
}

resource "heroku_formation" "api_web" {
  app      = heroku_app.api.id
  type     = "web"
  quantity = 1
  size     = "free"

  depends_on = [heroku_build.api]
}

output "api_base_url" {
  value = heroku_app.api.web_url
}

A terraform/versions.tf => terraform/versions.tf +15 -0
@@ 0,0 1,15 @@
terraform {
  required_version = ">= 0.13"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }

    heroku = {
      source  = "heroku/heroku"
      version = "~> 3.0"
    }
  }
}