RootBlockDeviceEncryptionLaunchTemplate

nicolaw 11th January 2021 at 9:55pm
AWS CodeSnippets Terraform
variable "unique_example_string" {
  type        = string
  default     = "nicolaw"
  description = "Unique string to avoid resource naming conflicts in order to allow the example to function"
}

resource "aws_vpc" "vpc" {
  cidr_block = "192.168.0.0/22"
}

data "aws_availability_zones" "azs" {
  state = "available"
}

resource "aws_subnet" "subnet_az1" {
  availability_zone = data.aws_availability_zones.azs.names[0]
  cidr_block        = "192.168.0.0/24"
  vpc_id            = aws_vpc.vpc.id
}

resource "aws_security_group" "sg" {
  name_prefix = var.unique_example_string
  vpc_id      = aws_vpc.vpc.id
}

data "aws_ami" "ami" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["amzn2-ami-ecs-hvm-2.0.*"]
  }
  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  filter {
    name   = "architecture"
    values = ["x86_64"]
  }
}

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "kms_policy" {
  # https://docs.aws.amazon.com/autoscaling/ec2/userguide/key-policy-requirements-EBS-encryption.html

  statement {
    sid    = "Allow service-linked role use of the CMK"
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"]
    }
    actions = [
      "kms:Encrypt",
      "kms:Decrypt",
      "kms:ReEncrypt*",
      "kms:GenerateDataKey*",
      "kms:DescribeKey"
    ]
    resources = ["*"]
  }

  statement {
    sid    = "Allow attachment of persistent resources"
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"]
    }
    actions   = ["kms:CreateGrant"]
    resources = ["*"]
    condition {
      test     = "Bool"
      variable = "kms:GrantIsForAWSResource"
      values   = [true]
    }
  }

  statement {
    sid    = "Enable IAM User Permissions"
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
    }
    actions   = ["kms:*"]
    resources = ["*"]
  }
}

resource "aws_kms_key" "kms" {
  description = var.unique_example_string
  policy      = data.aws_iam_policy_document.kms_policy.json
}

resource "aws_launch_template" "example" {
  name_prefix            = var.unique_example_string
  ebs_optimized          = true
  image_id               = data.aws_ami.ami.image_id
  instance_type          = "t3.nano"
  vpc_security_group_ids = [aws_security_group.sg.id]

  dynamic "block_device_mappings" {
    for_each = data.aws_ami.ami.block_device_mappings
    content {
      device_name  = lookup(block_device_mappings.value, "device_name", null)
      no_device    = lookup(block_device_mappings.value, "no_device", null)
      virtual_name = lookup(block_device_mappings.value, "virtual_name", null)

      dynamic "ebs" {
        for_each = flatten(list(lookup(block_device_mappings.value, "ebs", [])))
        content {
          delete_on_termination = true
          encrypted             = true
          iops                  = lookup(ebs.value, "iops", null)
          kms_key_id            = aws_kms_key.kms.arn
          volume_size           = lookup(ebs.value, "volume_size", null)
          volume_type           = lookup(ebs.value, "volume_type", null)
        }
      }
    }
  }
}

resource "aws_autoscaling_group" "example" {
  name_prefix         = var.unique_example_string
  vpc_zone_identifier = [aws_subnet.subnet_az1.id]
  min_size            = 1
  max_size            = 1

  launch_template {
    id      = aws_launch_template.example.id
    version = "$Latest"
  }
}

output "launch_template" {
  value = aws_launch_template.example
}