1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
# Route53 Resolver (Inbound/Outbound) ==========================================
# Resolver Endpoints -----------------------------------------------------------
# Shared resource type for both directions; caller sets `direction` per entry.
# INBOUND endpoints let external resolvers query into this VPC.
# OUTBOUND endpoints let this VPC forward queries to external DNS servers.
resource "aws_route53_resolver_endpoint" "this" {
for_each = var.endpoints
direction = each.value.direction
resolver_endpoint_type = each.value.endpoint_type
name = "${var.name_prefix}-${local.region_abbr}-resolver-ep-${each.value.endpoint_name_suffix}"
security_group_ids = each.value.security_group_ids
dynamic "ip_address" {
for_each = each.value.interfaces
content {
subnet_id = ip_address.value.subnet_id
ip = ip_address.value.ip
}
}
tags = merge(var.tags, each.value.tags, local.module_tags, {
Name = "${var.name_prefix}-${local.region_abbr}-resolver-ep-${each.value.endpoint_name_suffix}"
resource-type = "r53-resolver-endpoint"
})
lifecycle {
precondition {
condition = length("${var.name_prefix}-${local.region_abbr}-resolver-ep-${each.value.endpoint_name_suffix}") <= 64
error_message = "Assembled resolver endpoint name for '${each.key}' exceeds AWS's 64-character limit."
}
}
}
# Resolver Rules ===============================================================
# Only meaningful for OUTBOUND endpoints. Forwards queries for domain_name
# to the specified target IPs via the associated resolver endpoint.
resource "aws_route53_resolver_rule" "this" {
for_each = var.rules
domain_name = each.value.domain_name
rule_type = each.value.rule_type
resolver_endpoint_id = aws_route53_resolver_endpoint.this[each.value.endpoint_key].id
name = "${var.name_prefix}-${local.region_abbr}-resolver-rule-${each.value.rule_name_suffix}"
dynamic "target_ip" {
for_each = each.value.target_ips
content {
ip = target_ip.value.ip
port = target_ip.value.port
}
}
tags = merge(var.tags, each.value.tags, local.module_tags, {
Name = "${var.name_prefix}-${local.region_abbr}-resolver-rule-${each.value.rule_name_suffix}"
resource-type = "r53-resolver-rule"
})
lifecycle {
precondition {
condition = var.endpoints[each.value.endpoint_key].direction == "OUTBOUND"
error_message = "endpoint_key '${each.value.endpoint_key}' for rule '${each.key}' must reference an OUTBOUND endpoint."
}
precondition {
condition = length("${var.name_prefix}-${local.region_abbr}-resolver-rule-${each.value.rule_name_suffix}") <= 64
error_message = "Assembled resolver rule name for '${each.key}' exceeds AWS's 64-character limit."
}
}
}
# Rule Associations =============================================================
# Associates each rule with one or more VPCs. Flattened since a rule can
# target multiple VPCs and each association is its own resource.
resource "aws_route53_resolver_rule_association" "this" {
for_each = { for pair in flatten([
for rule_key, rule in var.rules : [
for vpc_id in rule.vpc_ids : {
key = "${rule_key}-${vpc_id}"
rule_id = rule_key
vpc_id = vpc_id
}
]
]) : pair.key => pair }
resolver_rule_id = aws_route53_resolver_rule.this[each.value.rule_id].id
vpc_id = each.value.vpc_id
}
|