Skip to content
This repository was archived by the owner on Jul 20, 2024. It is now read-only.

Variables #64

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ Move "module.nat.aws_eip.this" to "aws_eip.nat"
Successfully moved 1 object(s).
```

## Changes for latest version 3.0.0

Default is on-demand and not a spot instance. Also instance type is default t4g.nano to change this you need to add


instance_types = ["t3.nano"]

architecture = ["x86_64"]

## Contributions

Expand All @@ -163,22 +171,22 @@ No requirements.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Enable or not costly resources | `bool` | `true` | no |
| <a name="input_image_id"></a> [image\_id](#input\_image\_id) | AMI of the NAT instance. Default to the latest Amazon Linux 2 | `string` | `""` | no |
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | Candidates of spot instance type for the NAT instance. This is used in the mixed instances policy | `list(string)` | <pre>[<br> "t3.nano",<br> "t3a.nano"<br>]</pre> | no |
| <a name="input_key_name"></a> [key\_name](#input\_key\_name) | Name of the key pair for the NAT instance. You can set this to assign the key pair to the NAT instance | `string` | `""` | no |
| <a name="input_name"></a> [name](#input\_name) | Name for all the resources as identifier | `string` | n/a | yes |
| <a name="input_private_route_table_ids"></a> [private\_route\_table\_ids](#input\_private\_route\_table\_ids) | List of ID of the route tables for the private subnets. You can set this to assign the each default route to the NAT instance | `list(string)` | `[]` | no |
| <a name="input_private_subnets_cidr_blocks"></a> [private\_subnets\_cidr\_blocks](#input\_private\_subnets\_cidr\_blocks) | List of CIDR blocks of the private subnets. The NAT instance accepts connections from this subnets | `list(string)` | n/a | yes |
| <a name="input_public_subnet"></a> [public\_subnet](#input\_public\_subnet) | ID of the public subnet to place the NAT instance | `string` | n/a | yes |
| <a name="input_ssm_policy_arn"></a> [ssm\_policy\_arn](#input\_ssm\_policy\_arn) | SSM Policy to be attached to instance profile | `string` | `"arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags applied to resources created with this module | `map(string)` | `{}` | no |
| <a name="input_use_spot_instance"></a> [use\_spot\_instance](#input\_use\_spot\_instance) | Whether to use spot or on-demand EC2 instance | `bool` | `true` | no |
| <a name="input_user_data_runcmd"></a> [user\_data\_runcmd](#input\_user\_data\_runcmd) | Additional runcmd section of cloud-init | `list(list(string))` | `[]` | no |
| <a name="input_user_data_write_files"></a> [user\_data\_write\_files](#input\_user\_data\_write\_files) | Additional write\_files section of cloud-init | `list(any)` | `[]` | no |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | ID of the VPC | `string` | n/a | yes |
| Name | Description | Type | Default | Required |
|------|-------------------------------------------------------------------------------------------------------------------------------|------|----------------------------------------------------------|:--------:|
| <a name="input_enabled"></a> [enabled](#input\_enabled) | This variable is for enabling auto scaling desired capacity and minimum size in the auto scaling group. | `bool` | `true` | no |
| <a name="input_image_id"></a> [image\_id](#input\_image\_id) | AMI of the NAT instance. Default to the latest Amazon Linux 2 | `string` | `""` | no |
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | Candidates of spot instance type for the NAT instance. This is used in the mixed instances policy | `list(string)` | <pre>[<br> "t3.nano",<br> "t3a.nano"<br>]</pre> | no |
| <a name="input_key_name"></a> [key\_name](#input\_key\_name) | Name of the key pair for the NAT instance. You can set this to assign the key pair to the NAT instance | `string` | `""` | no |
| <a name="input_name"></a> [name](#input\_name) | Name for all the resources as identifier | `string` | n/a | yes |
| <a name="input_private_route_table_ids"></a> [private\_route\_table\_ids](#input\_private\_route\_table\_ids) | List of ID of the route tables for the private subnets. You can set this to assign the each default route to the NAT instance | `list(string)` | `[]` | no |
| <a name="input_private_subnets_cidr_blocks"></a> [private\_subnets\_cidr\_blocks](#input\_private\_subnets\_cidr\_blocks) | List of CIDR blocks of the private subnets. The NAT instance accepts connections from this subnets | `list(string)` | n/a | yes |
| <a name="input_public_subnet"></a> [public\_subnet](#input\_public\_subnet) | ID of the public subnet to place the NAT instance | `string` | n/a | yes |
| <a name="input_ssm_policy_arn"></a> [ssm\_policy\_arn](#input\_ssm\_policy\_arn) | SSM Policy to be attached to instance profile | `string` | `"arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags applied to resources created with this module | `map(string)` | `{}` | no |
| <a name="input_use_spot_instance"></a> [use\_spot\_instance](#input\_use\_spot\_instance) | Whether to use spot or on-demand EC2 instance | `bool` | `false` | no |
| <a name="input_user_data_runcmd"></a> [user\_data\_runcmd](#input\_user\_data\_runcmd) | Additional runcmd section of cloud-init | `list(list(string))` | `[]` | no |
| <a name="input_user_data_write_files"></a> [user\_data\_write\_files](#input\_user\_data\_write\_files) | Additional write\_files section of cloud-init | `list(any)` | `[]` | no |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | ID of the VPC | `string` | n/a | yes |

## Outputs

Expand Down
43 changes: 14 additions & 29 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
data "aws_network_interface" "this" {
id = aws_network_interface.this.id
}

resource "aws_security_group" "this" {
name_prefix = var.name
vpc_id = var.vpc_id
Expand All @@ -10,17 +14,17 @@ resource "aws_security_group_rule" "egress" {
type = "egress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 65535
protocol = "tcp"
to_port = 0
protocol = "-1"
}

resource "aws_security_group_rule" "ingress_any" {
security_group_id = aws_security_group.this.id
type = "ingress"
cidr_blocks = var.private_subnets_cidr_blocks
from_port = 0
to_port = 65535
protocol = "all"
to_port = 0
protocol = "-1"
}

resource "aws_network_interface" "this" {
Expand All @@ -44,23 +48,23 @@ data "aws_ami" "this" {
owners = ["amazon"]
filter {
name = "architecture"
values = ["x86_64"]
values = var.architecture
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
values = ["al2023-ami-minimal*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "block-device-mapping.volume-type"
values = ["gp2"]
values = ["gp3"]
}
}

Expand All @@ -79,9 +83,8 @@ resource "aws_launch_template" "this" {
}

network_interfaces {
associate_public_ip_address = true
security_groups = [aws_security_group.this.id]
delete_on_termination = true
device_index = 0
network_interface_id = aws_network_interface.this.id
}

tag_specifications {
Expand Down Expand Up @@ -124,7 +127,7 @@ resource "aws_autoscaling_group" "this" {
desired_capacity = var.enabled ? 1 : 0
min_size = var.enabled ? 1 : 0
max_size = 1
vpc_zone_identifier = [var.public_subnet]
availability_zones = [data.aws_network_interface.this.availability_zone]

mixed_instances_policy {
instances_distribution {
Expand Down Expand Up @@ -191,21 +194,3 @@ resource "aws_iam_role_policy_attachment" "ssm" {
role = aws_iam_role.this.name
}

resource "aws_iam_role_policy" "eni" {
role = aws_iam_role.this.name
name_prefix = var.name
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AttachNetworkInterface"
],
"Resource": "*"
}
]
}
EOF
}
11 changes: 6 additions & 5 deletions runonce.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/bin/bash -x

#The below is no longer needed.
# attach the ENI
aws ec2 attach-network-interface \
--region "$(/opt/aws/bin/ec2-metadata -z | sed 's/placement: \(.*\).$/\1/')" \
--instance-id "$(/opt/aws/bin/ec2-metadata -i | cut -d' ' -f2)" \
--device-index 1 \
--network-interface-id "${eni_id}"
#aws ec2 attach-network-interface \
# --region "$(/opt/aws/bin/ec2-metadata -z | sed 's/placement: \(.*\).$/\1/')" \
# --instance-id "$(/opt/aws/bin/ec2-metadata -i | cut -d' ' -f2)" \
# --device-index 1 \
# --network-interface-id "${eni_id}"

# start SNAT
systemctl enable snat
Expand Down
4 changes: 3 additions & 1 deletion snat.service
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[Unit]
Description = SNAT via ENI eth1
Description = Configure this machine to act as a NAT instance.
Wants = network-online.target
After = network-online.target

[Service]
ExecStart = /opt/nat/snat.sh
Expand Down
74 changes: 57 additions & 17 deletions snat.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,64 @@
#!/bin/bash
set -x
#!/bin/sh

# wait for eth1
while ! ip link show dev eth1; do
sleep 1
done
yum install iptables-services -y

if test -f "/etc/nat.conf"; then
echo "Found nat configuration at /etc/nat.conf"
. /etc/nat.conf
else
echo "No nat configuration at /etc/nat.conf"
fi

if test -n "$eni_id"; then
echo "Found eni_id configuration, attaching $eni_id..."

aws_region="$(/opt/aws/bin/ec2-metadata -z | cut -f2 -d' ' | sed 's/.$//')"
instance_id="$(/opt/aws/bin/ec2-metadata -i | cut -f2 -d' ')"

eth0_mac="$(cat /sys/class/net/eth0/address)"

token="$(curl -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 300' http://169.254.169.254/latest/api/token)"
eth0_eni_id="$(curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/network/interfaces/macs/$eth0_mac/interface-id)"

# enable IP forwarding and NAT
aws ec2 modify-network-interface-attribute \
--region "$aws_region" \
--network-interface-id "$eth0_eni_id" \
--no-source-dest-check

aws ec2 attach-network-interface \
--region "$aws_region" \
--instance-id "$instance_id" \
--device-index 1 \
--network-interface-id "$eni_id"

while ! ip link show dev eth1; do
echo "Waiting for ENI to come up..."
sleep 1
done

nat_interface="eth0"
elif test -n "$interface"; then
echo "Found interface configuration, using $interface"
nat_interface=$interface
else
nat_interface=$(ip route | grep default | cut -d ' ' -f 5)
echo "No eni_id or interface configuration found, using default interface $nat_interface"
fi

echo "Enabling ip_forward..."
sysctl -q -w net.ipv4.ip_forward=1
sysctl -q -w net.ipv4.conf.eth1.send_redirects=0
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

# prevent setting the default route to eth0 after reboot
rm -f /etc/sysconfig/network-scripts/ifcfg-eth0
echo "Disabling reverse path protection..."
for i in $(find /proc/sys/net/ipv4/conf/ -name rp_filter) ; do
echo 0 > $i;
done

echo "Flushing NAT table..."
iptables -t nat -F

# switch the default route to eth1
ip route del default dev eth0
echo "Adding NAT rule..."
iptables -t nat -A POSTROUTING -o "$nat_interface" -j MASQUERADE -m comment --comment "NAT routing rule installed"

# wait for network connection
curl --retry 10 http://www.example.com
service iptables save

# reestablish connections
systemctl restart amazon-ssm-agent.service
echo "Done!"
10 changes: 8 additions & 2 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@ variable "image_id" {
variable "instance_types" {
description = "Candidates of spot instance type for the NAT instance. This is used in the mixed instances policy"
type = list(string)
default = ["t3.nano", "t3a.nano"]
default = ["t4g.nano"]
}

variable "architecture" {
description = "Candidates of spot instance type for the NAT instance. This is used in the mixed instances policy"
type = list(string)
default = ["arm64"]
}

variable "use_spot_instance" {
description = "Whether to use spot or on-demand EC2 instance"
type = bool
default = true
default = false
}

variable "key_name" {
Expand Down
10 changes: 10 additions & 0 deletions version.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 0.13.1"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}