Skip to content

Commit

Permalink
New option to disable IPv6 in the connectivity test (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
bwhaley authored Apr 15, 2024
1 parent 53be0b9 commit fadc518
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 17 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ While we'd like for this to be available on the Terraform Registry, it requires
echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf
EOF
```
- If you see errors like: `error connecting to https://www.google.com/: <urlopen error [Errno 97] Address family not supported by protocol>` in the connectivity tester logs, you can set `lambda_has_ipv6 = false`. This will cause the lambda to request IPv4 addresses only in DNS lookups.



## Future work

Expand Down
27 changes: 26 additions & 1 deletion functions/replace-route/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,24 @@
# Which URLs to check for connectivity
DEFAULT_CHECK_URLS = ["https://www.example.com", "https://www.google.com"]


# The timeout for the connectivity checks.
REQUEST_TIMEOUT = 5

# Whether or not use IPv6.
DEFAULT_HAS_IPV6 = True


# Overrides socket.getaddrinfo to perform IPv4 lookups
# See https://github.com/1debit/alternat/issues/87
def disable_ipv6():
prv_getaddrinfo = socket.getaddrinfo
def getaddrinfo_ipv4(*args):
modified_args = (args[0], args[1], socket.AF_INET) + args[3:]
res = prv_getaddrinfo(*modified_args)
return res
socket.getaddrinfo = getaddrinfo_ipv4


def get_az_and_vpc_zone_identifier(auto_scaling_group):
autoscaling = boto3.client("autoscaling")

Expand Down Expand Up @@ -156,6 +171,10 @@ def connectivity_test_handler(event, context):
check_interval = int(os.getenv("CONNECTIVITY_CHECK_INTERVAL", DEFAULT_CONNECTIVITY_CHECK_INTERVAL))
check_urls = "CHECK_URLS" in os.environ and os.getenv("CHECK_URLS").split(",") or DEFAULT_CHECK_URLS

has_ipv6 = get_env_bool("HAS_IPV6", DEFAULT_HAS_IPV6)
if not has_ipv6:
disable_ipv6()

# Run connectivity checks for approximately 1 minute
run = 0
num_runs = 60 / check_interval
Expand All @@ -167,6 +186,12 @@ def connectivity_test_handler(event, context):
break


def get_env_bool(var_name, default_value=False):
value = os.getenv(var_name, default_value)
true_values = ["t", "true", "y", "yes", "1"]
return str(value).lower() in true_values


def handler(event, _):
try:
for record in event["Records"]:
Expand Down
11 changes: 11 additions & 0 deletions functions/replace-route/tests/test_replace_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,14 @@ class Context:
connectivity_test_handler(event=json.loads(cloudwatch_event), context=Context())

verify_nat_gateway_route(mocked_networking)


def test_disable_ipv6():
with mock.patch('socket.getaddrinfo') as mock_getaddrinfo:
from app import disable_ipv6
disable_ipv6()
socket.getaddrinfo('example.com', 80)
mock_getaddrinfo.assert_called()
call_args = mock_getaddrinfo.call_args.args
assert len(call_args) == 3, f"With IPv6 disabled, expected 3 arguments to getaddrinfo, found {len(call_args)}"
assert call_args[2] == socket.AF_INET, "Did not find AF_INET family in args to getaddrinfo"
40 changes: 24 additions & 16 deletions modules/terraform-aws-alternat/lambda.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
locals {
autoscaling_func_env_vars = {
# Lambda function env vars cannot contain hyphens
for obj in var.vpc_az_maps
: replace(upper(obj.az), "-", "_") => join(",", obj.route_table_ids)
}
has_ipv6_env_var = { "HAS_IPV6" = var.lambda_has_ipv6 }
}

data "archive_file" "lambda" {
count = var.lambda_package_type == "Zip" ? 1 : 0
type = "zip"
Expand All @@ -15,7 +24,7 @@ resource "aws_lambda_function" "alternat_autoscaling_hook" {
timeout = var.lambda_timeout
role = aws_iam_role.nat_lambda_role.arn

layers = var.lambda_layer_arns
layers = var.lambda_layer_arns

image_uri = var.lambda_package_type == "Image" ? "${var.alternat_image_uri}:${var.alternat_image_tag}" : null

Expand All @@ -25,22 +34,17 @@ resource "aws_lambda_function" "alternat_autoscaling_hook" {
source_code_hash = var.lambda_package_type == "Zip" ? data.archive_file.lambda[0].output_base64sha256 : null

environment {
variables = merge(local.autoscaling_func_env_vars, var.lambda_environment_variables)
variables = merge(
local.autoscaling_func_env_vars,
var.lambda_environment_variables,
)
}

tags = merge({
FunctionName = "alternat-autoscaling-lifecycle-hook",
}, var.tags)
}

locals {
autoscaling_func_env_vars = {
# Lambda function env vars cannot contain hyphens
for obj in var.vpc_az_maps
: replace(upper(obj.az), "-", "_") => join(",", obj.route_table_ids)
}
}

resource "aws_iam_role" "nat_lambda_role" {
name = var.nat_lambda_function_role_name == "" ? null : var.nat_lambda_function_role_name
name_prefix = var.nat_lambda_function_role_name == "" ? "alternat-lambda-role-" : null
Expand Down Expand Up @@ -129,7 +133,7 @@ resource "aws_lambda_function" "alternat_connectivity_tester" {
timeout = var.lambda_timeout
role = aws_iam_role.nat_lambda_role.arn

layers = var.lambda_layer_arns
layers = var.lambda_layer_arns

image_uri = var.lambda_package_type == "Image" ? "${var.alternat_image_uri}:${var.alternat_image_tag}" : null

Expand All @@ -147,11 +151,15 @@ resource "aws_lambda_function" "alternat_connectivity_tester" {
}

environment {
variables = merge({
ROUTE_TABLE_IDS_CSV = join(",", each.value.route_table_ids),
PUBLIC_SUBNET_ID = each.value.public_subnet_id
CHECK_URLS = join(",", var.connectivity_test_check_urls)
}, var.lambda_environment_variables)
variables = merge(
{
ROUTE_TABLE_IDS_CSV = join(",", each.value.route_table_ids),
PUBLIC_SUBNET_ID = each.value.public_subnet_id
CHECK_URLS = join(",", var.connectivity_test_check_urls)
},
local.has_ipv6_env_var,
var.lambda_environment_variables,
)
}

vpc_config {
Expand Down
6 changes: 6 additions & 0 deletions modules/terraform-aws-alternat/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,12 @@ variable "lambda_environment_variables" {
default = null
}

variable "lambda_has_ipv6" {
description = "Controls whether or not the lambda function can use IPv6."
type = bool
default = true
}

variable "lambda_zip_path" {
description = "The location where the generated zip file should be stored. Required when `lambda_package_type` is \"Zip\"."
type = string
Expand Down

0 comments on commit fadc518

Please sign in to comment.