Skip to content

Instantly share code, notes, and snippets.

@kyl191
Created June 29, 2020 06:02
Show Gist options
  • Save kyl191/86998ee0e031e24c2b316374c3bda706 to your computer and use it in GitHub Desktop.
Save kyl191/86998ee0e031e24c2b316374c3bda706 to your computer and use it in GitHub Desktop.
minimal fedora ec2 instance with IPv6 support + no magic constants
resource "aws_key_pair" "ansible_key" {
key_name = "ansible_key"
public_key = file("id_rsa.pub")
}
data "aws_ami" "fedora_cloud" {
owners = [125523088429] # fedora infra
most_recent = true
filter {
name = "name"
values = ["Fedora-Cloud-Base-32*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "block-device-mapping.volume-type"
values = ["gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_ebs_encryption_by_default" "example" {
enabled = true
}
data "aws_ebs_default_kms_key" "current" {}
resource "random_shuffle" "az" {
input = data.aws_availability_zones.azs.zone_ids
result_count = 1
}
resource "aws_instance" "instance" {
key_name = aws_key_pair.ansible_key.key_name
ami = data.aws_ami.fedora_cloud.id
instance_type = "t3.micro"
disable_api_termination = true
tags = {
Name = "fedora"
}
root_block_device {
volume_type = "gp2"
volume_size = 20
encrypted = true
kms_key_id = data.aws_ebs_default_kms_key.current.key_arn
delete_on_termination = false
}
credit_specification {
cpu_credits = "standard"
}
vpc_security_group_ids = [aws_security_group.allow_default_ports.id]
ipv6_address_count = 1
subnet_id = aws_subnet.subnets[random_shuffle.az.result[0]].id
# Ignore the kms key id changing because the alias is resolved once the instance is created
# https://github.com/terraform-providers/terraform-provider-aws/issues/13860
lifecycle {
ignore_changes = [root_block_device[0].kms_key_id]
}
user_data = file("cloud-init-user-data.yaml")
}
resource "aws_security_group" "allow_default_ports" {
name_prefix = "default_ports"
description = "Allow http/https/ssh+ping"
vpc_id = aws_vpc.default.id
lifecycle {
create_before_destroy = true
}
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
# Allow ICMP protocols
# type/code from http://shouldiblockicmp.com/
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html#sg-rules-ping
# implies icmpv6 types are supported, but in practice they aren't
ingress {
description = "icmp echo"
protocol = "icmp"
from_port = 8 # ICMP type
to_port = 0 # ICMP code
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
description = "icmp fragmentation required"
protocol = "icmp"
from_port = 3 # ICMP type
to_port = 4 # ICMP code
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
description = "icmp time excceded"
protocol = "icmp"
from_port = 11 # ICMP type
to_port = 0 # ICMP code
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
description = "icmpv6"
protocol = "icmpv6"
from_port = -1 # ICMP type
to_port = -1 # ICMP code
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Name = "default_ports"
}
}
resource "aws_eip" "ip" {
vpc = true
instance = aws_instance.instance.id
}
# To allow IPv6 communication, we need to
# * Add an IPv6 block to the VPC
# * Add a ::0/0 route to the route table pointing at the internet gateway
# * Add IPv6 blocks to the subnets
resource "random_id" "vpc_cidr_block" {
byte_length = 1
}
resource "aws_vpc" "default" {
enable_dns_support = true
enable_dns_hostnames = true
assign_generated_ipv6_cidr_block = true
cidr_block = "10.${random_id.vpc_cidr_block.dec}.0.0/16"
}
resource "aws_internet_gateway" "default" {
vpc_id = aws_vpc.default.id
}
resource "aws_default_route_table" "default" {
default_route_table_id = aws_vpc.default.default_route_table_id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.default.id
}
route {
ipv6_cidr_block = "::/0"
gateway_id = aws_internet_gateway.default.id
}
}
# I'm over complicating things, and create a subnet for every AZ in the region
data "aws_availability_zones" "azs" {}
resource "aws_subnet" "subnets" {
for_each = {
for zid in data.aws_availability_zones.azs.zone_ids :
zid => index(data.aws_availability_zones.azs.zone_ids, zid)
}
vpc_id = aws_vpc.default.id
availability_zone_id = each.key
cidr_block = cidrsubnet(aws_vpc.default.cidr_block, 4, each.value)
map_public_ip_on_launch = true
ipv6_cidr_block = cidrsubnet(aws_vpc.default.ipv6_cidr_block, 8, each.value)
assign_ipv6_address_on_creation = true
}
resource "aws_route_table_association" "default" {
for_each = aws_subnet.subnets
subnet_id = each.value.id
route_table_id = aws_default_route_table.default.id
}
# Create endpoints for s3 and dynamodb
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.default.id
service_name = "com.amazonaws.us-west-2.s3"
auto_accept = true
route_table_ids = [aws_default_route_table.default.id]
}
resource "aws_vpc_endpoint" "dynamodb" {
vpc_id = aws_vpc.default.id
service_name = "com.amazonaws.us-west-2.dynamodb"
auto_accept = true
route_table_ids = [aws_default_route_table.default.id]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment