WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 82cf625

Browse files
committed
Add ability to use "myipv4" as a pseudo-address in firewall rules. The ip-address is then fetched on terraform run from opendns (google as secondary)
1 parent ee1b6ba commit 82cf625

File tree

5 files changed

+80
-4
lines changed

5 files changed

+80
-4
lines changed

data.tf

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,35 @@ data "hcloud_ssh_keys" "keys_by_selector" {
3232
count = length(var.ssh_hcloud_key_label) > 0 ? 1 : 0
3333
with_selector = var.ssh_hcloud_key_label
3434
}
35+
36+
data "external" "my_ip" {
37+
count = local.is_ref_myipv4_used ? 1 : 0
38+
39+
program = [
40+
"bash",
41+
"-c",
42+
<<-EOT
43+
set -euo pipefail
44+
error_exit() {
45+
echo "Error: $1" >&2
46+
exit 1
47+
}
48+
49+
if ! command -v dig &> /dev/null; then
50+
error_exit "'dig' command not found. Please install it (e.g., 'apt-get install dnsutils' or 'yum install bind-utils')."
51+
fi
52+
IPV4=$(dig +time=5 +tries=2 -4 +short myip.opendns.com @resolver1.opendns.com | head -n 1 || true)
53+
if [ -z "$IPV4" ]; then
54+
IPV4=$(dig +time=5 +tries=2 -4 +short TXT o-o.myaddr.l.google.com @ns1.google.com | head -n 1 | tr -d '"' || true)
55+
fi
56+
if [ -z "$IPV4" ]; then
57+
error_exit "Failed to retrieve public IPv4 address. The command returned an empty string. Please check network connectivity."
58+
fi
59+
if [[ "$IPV4" =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; then
60+
echo "{\"ipv4\": \"$IPV4\"}"
61+
else
62+
error_exit "Retrieved value '$IPV4' is not a valid public IPv4 address."
63+
fi
64+
EOT
65+
]
66+
}

kube.tf.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,12 +784,14 @@ module "kube-hetzner" {
784784
# you would have to connect to any control plane node via SSH, as you can run kubectl from within these.
785785
# Please be advised that this setting has no effect on the load balancer when the use_control_plane_lb variable is set to true. This is
786786
# because firewall rules cannot be applied to load balancers yet.
787+
# Note: You can use the string "myipv4" as an IP address in the array and it will be replaced with the CIDR/32 of your IP as reported by myip.opendns.com. Use of "myipv4" requires `dig` to be available.
787788
# firewall_kube_api_source = null
788789

789790
# Allow SSH access from the specified networks. Default: ["0.0.0.0/0", "::/0"]
790791
# Allowed values: null (disable SSH rule entirely) or a list of allowed networks with CIDR notation.
791792
# Ideally you would set your IP there. And if it changes after cluster deploy, you can always update this variable and apply again.
792-
# firewall_ssh_source = ["1.2.3.4/32"]
793+
# Note: You can use the string "myipv4" as an IP address in the array and it will be replaced with the CIDR/32 of your IP as reported by myip.opendns.com. Use of "myipv4" requires `dig` to be available.
794+
# firewall_ssh_source = ["myipv4", "1.2.3.4/32"]
793795

794796
# By default, SELinux is enabled in enforcing mode on all nodes. For container-specific SELinux issues,
795797
# consider using the pre-installed 'udica' tool to create custom, targeted SELinux policies instead of
@@ -798,6 +800,7 @@ module "kube-hetzner" {
798800

799801
# Adding extra firewall rules, like opening a port
800802
# More info on the format here https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs/resources/firewall
803+
# Note: You can use the string "myipv4" as an IP address in the `source_ips` or `destination_ips` arrays and it will be replaced with the CIDR/32 of your IP as reported by myip.opendns.com. Use of "myipv4" requires `dig` to be available.
801804
# extra_firewall_rules = [
802805
# {
803806
# description = "For Postgres"

locals.tf

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ locals {
2727
dns_servers_ipv4 = [for ip in var.dns_servers : ip if provider::assert::ipv4(ip)]
2828
dns_servers_ipv6 = [for ip in var.dns_servers : ip if provider::assert::ipv6(ip)]
2929

30+
# My IPv4 related variables.
31+
is_ref_myipv4_used = (
32+
contains(coalesce(var.firewall_kube_api_source, []), var.myipv4_ref) ||
33+
contains(coalesce(var.firewall_ssh_source, []), var.myipv4_ref) ||
34+
contains(flatten([
35+
for rule in var.extra_firewall_rules : concat(coalesce(rule.source_ips, []), coalesce(rule.destination_ips, []))
36+
]), var.myipv4_ref)
37+
)
38+
my_public_ipv4_cidr = try("${data.external.my_ip[0].result.ipv4}/32", null)
39+
40+
3041
additional_k3s_environment = join("\n",
3142
[
3243
for var_name, var_value in var.additional_k3s_environment :
@@ -509,8 +520,15 @@ locals {
509520
# merge the two lists
510521
firewall_rules_merged = merge(local.firewall_rules, local.extra_firewall_rules)
511522

512-
# convert the merged list back to a list
513-
firewall_rules_list = values(local.firewall_rules_merged)
523+
# replace "myipv4" (var.myipv4_ref) with the actual value, merge to a list
524+
firewall_rules_list = [for key, rule in local.firewall_rules_merged : {
525+
description = rule.description
526+
direction = rule.direction
527+
protocol = rule.protocol
528+
port = rule.port
529+
source_ips = compact([for ip in lookup(rule, "source_ips", []) : ip == var.myipv4_ref ? local.my_public_ipv4_cidr : ip])
530+
destination_ips = compact([for ip in lookup(rule, "destination_ips", []) : ip == var.myipv4_ref ? local.my_public_ipv4_cidr : ip])
531+
} if rule != null]
514532

515533
labels = {
516534
"provisioner" = "terraform",

variables.tf

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,9 +667,22 @@ variable "automatically_upgrade_os" {
667667
}
668668

669669
variable "extra_firewall_rules" {
670-
type = list(any)
670+
type = list(object({
671+
description = optional(string, "")
672+
direction = string
673+
protocol = optional(string, "tcp")
674+
port = string
675+
source_ips = optional(list(string), [])
676+
destination_ips = optional(list(string), [])
677+
}))
678+
671679
default = []
672680
description = "Additional firewall rules to apply to the cluster."
681+
682+
validation {
683+
condition = alltrue([for rule in var.extra_firewall_rules : contains(["in", "out"], rule.direction)])
684+
error_message = "The direction must be either 'in' or 'out'."
685+
}
673686
}
674687

675688
variable "firewall_kube_api_source" {
@@ -684,6 +697,12 @@ variable "firewall_ssh_source" {
684697
description = "Source networks that have SSH access to the servers."
685698
}
686699

700+
variable "myipv4_ref" {
701+
type = string
702+
default = "myipv4"
703+
description = "Name to be used in firewall rules as a substitute for your own IPv4 address."
704+
}
705+
687706
variable "use_cluster_name_in_node_name" {
688707
type = bool
689708
default = true

versions.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ terraform {
99
source = "hetznercloud/hcloud"
1010
version = ">= 1.51.0"
1111
}
12+
external = {
13+
source = "hashicorp/external"
14+
version = "~> 2.0"
15+
}
1216
local = {
1317
source = "hashicorp/local"
1418
version = ">= 2.5.2"

0 commit comments

Comments
 (0)