diff --git a/common/design/main.tf b/common/design/main.tf index df4bf628..b1b11d89 100644 --- a/common/design/main.tf +++ b/common/design/main.tf @@ -1,7 +1,3 @@ -data "http" "agent_ip" { - url = "http://ipv4.icanhazip.com" -} - locals { domain_name = "${lower(var.cluster_name)}.${lower(var.domain)}" @@ -52,21 +48,7 @@ locals { volume_per_instance = transpose({ for key, value in local.instance_per_volume : key => value["instances"] }) - # We look for firewall rules that allow SSH connection from the Terraform agent's ip - # and we memorize the corresponding tags so we can determine which instances can be used as a - # first hop when transferring files or executing remote commands with Terraform. - agent_ip = chomp(data.http.agent_ip.response_body) - bastion_tags = distinct(concat(var.bastion_tags, [ - for rule, values in var.firewall_rules : - values.tag - if values.ethertype == "IPv4" && - 22 <= values.from_port && values.to_port <= 22 && - alltrue([ - for i, v in split(".", local.agent_ip) : - tonumber(split(".", strcontains(values.cidr, "/") ? cidrhost(values.cidr, 0) : values.cidr)[i]) <= tonumber(v) && - tonumber(split(".", strcontains(values.cidr, "/") ? cidrhost(values.cidr, -1) : values.cidr)[i]) >= tonumber(v) - ]) - ])) + bastion_tags = [for rule, values in var.firewall_rules : values.tag if values.from_port == 22 && values.cidr == "0.0.0.0/0"] } check "disk_space_per_tag" { diff --git a/common/design/variables.tf b/common/design/variables.tf index 4622943e..eded67c4 100644 --- a/common/design/variables.tf +++ b/common/design/variables.tf @@ -6,4 +6,4 @@ variable "pool" {} variable "firewall_rules" {} variable "min_disk_size" {} variable "image" {} -variable "bastion_tags" {} \ No newline at end of file + diff --git a/common/provision/main.tf b/common/provision/main.tf index 95e9b1eb..45eedcdc 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -9,6 +9,10 @@ variable "hieradata_dir" {} variable "eyaml_key" {} variable "puppetfile" {} +variable "bastion_remote" { + default = {} +} + locals { provision_folder = "etc_puppetlabs" } @@ -69,9 +73,9 @@ resource "terraform_data" "deploy_puppetserver_files" { connection { type = "ssh" agent = false - bastion_host = contains(local.bastion_host.tags, "public") ? local.bastion_host.public_ip : local.bastion_host.local_ip - bastion_user = "tf" - bastion_private_key = var.configuration.ssh_key.private + bastion_host = coalesce(var.bastion_remote.host, contains(local.bastion_host.tags, "public") ? local.bastion_host.public_ip : local.bastion_host.local_ip) + bastion_user = coalesce(var.bastion_remote.user, "tf") + bastion_private_key = coalesce(var.bastion_remote.private_key, var.configuration.ssh_key.private) user = "tf" host = each.value private_key = var.configuration.ssh_key.private diff --git a/examples/incus/main.tf b/examples/incus/main.tf index 33b9d980..3a0da609 100644 --- a/examples/incus/main.tf +++ b/examples/incus/main.tf @@ -17,11 +17,6 @@ module "incus" { node = { type = "container", cpus = 2, ram = 3000, gpus = 0, tags = ["node"], count = 1 } } - firewall_rules = { - http = { "from_port" = 80, "to_port" = 80, tag = "proxy", "cidr" = "0.0.0.0/0" }, - https = { "from_port" = 443, "to_port" = 443, tag = "proxy", "cidr" = "0.0.0.0/0" }, - } - bastion_tags = ["login"] volumes = {} @@ -40,6 +35,18 @@ module "incus" { # Set to true to make port 80 and 443 of the proxy container forwarded on the host # There is a maximum of 1 cluster with forward_proxy = true per incus server. forward_proxy = false + + # Use the Incus host as bastion (useful when deploying using Incus remote) + # bastion_remote = { + # host = "" + # user = "" + # private_key = file("") + # } + + # Use the local ip as bastion (when deploying Terraform directly from the Incus host) + bastion_remote = { + host = chomp(data.http.agent_ip.response_body) + } } output "accounts" { @@ -55,9 +62,10 @@ output "public_ip" { } -# data "http" "agent_ip" { -# url = "http://ipv4.icanhazip.com" -# } +data "http" "agent_ip" { + url = "http://ipv4.icanhazip.com" +} + # locals { # public_instances = { for host, values in module.incus.public_instances: host => merge(values, { "public_ip" = chomp(data.http.agent_ip.response_body) }) } # } diff --git a/incus/incus.tf b/incus/incus.tf index 77dd62ad..8c6e9120 100644 --- a/incus/incus.tf +++ b/incus/incus.tf @@ -34,3 +34,13 @@ variable "network_type" { error_message = "network_type must be either 'bridge' or 'ovn'." } } + +variable "bastion_remote" { + default = {} + description = "Optional bastion SSH connection configuration. Useful for remote Incus deployments when no instance is publicly accessible." + type = object({ + host = optional(string) + user = optional(string) + private_key = optional(string) + }) +} diff --git a/incus/infrastructure.tf b/incus/infrastructure.tf index 5ad78c89..f5e6a98c 100644 --- a/incus/infrastructure.tf +++ b/incus/infrastructure.tf @@ -32,12 +32,13 @@ module "configuration" { } module "provision" { - source = "../common/provision" - configuration = module.configuration - hieradata = var.hieradata - hieradata_dir = var.hieradata_dir - eyaml_key = var.eyaml_key - puppetfile = var.puppetfile + source = "../common/provision" + configuration = module.configuration + hieradata = var.hieradata + hieradata_dir = var.hieradata_dir + eyaml_key = var.eyaml_key + puppetfile = var.puppetfile + bastion_remote = var.bastion_remote } resource "random_id" "project_name" {