From: Anil Belur Date: Wed, 22 Oct 2025 12:15:25 +0000 (+1000) Subject: feat: Add Tailscale SSH bastion/jump host support X-Git-Tag: v0.17.0^0 X-Git-Url: https://gerrit.linuxfoundation.org/infra/gitweb?a=commitdiff_plain;h=040655a01331344500ebf0c5300985da0e60e54e;p=releng%2Fcommon-packer.git feat: Add Tailscale SSH bastion/jump host support Add native SSH bastion support to all OpenStack builder templates, enabling Packer builds through jump hosts for environments where direct access to OpenStack networks is not available. Changes: - Add ssh_bastion_* variables to templates with OpenStack sources: * ssh_bastion_host - Bastion IP/hostname * ssh_bastion_username - Bastion authentication username * ssh_bastion_port - Bastion SSH port (default: 22) * ssh_bastion_agent_auth - Use SSH agent auth (default: true) * ssh_bastion_private_key_file - Path to private key file * ssh_bastion_password - Password authentication (not recommended) - Update OpenStack source blocks in all templates to include bastion configuration with conditional null handling for backwards compatibility - Maintain legacy ssh_proxy_host support for existing deployments Templates updated: - templates/builder.pkr.hcl - templates/devstack.pkr.hcl - templates/devstack-pre-pip-yoga.pkr.hcl - templates/docker.pkr.hcl - templates/windows-builder.pkr.hcl - templates/variables.auto.pkr.hcl All bastion variables are optional with empty string defaults, ensuring backward compatibility with existing builds that don't require bastion access. Variables convert to null when empty, so Packer ignores them. This enables CI/CD environments (GitHub Actions, Jenkins) to build OpenStack images via ephemeral bastion hosts like Tailscale SSH or traditional jump servers. Issue: RELENG-5850 Change-Id: If2b18067e491346b26d03da38b0ae1957c78aca1 Signed-off-by: Anil Belur --- diff --git a/releasenotes/notes/add-ssh-bastion-support-0e994a2a7f0d710a.yaml b/releasenotes/notes/add-ssh-bastion-support-0e994a2a7f0d710a.yaml new file mode 100644 index 0000000..83fa331 --- /dev/null +++ b/releasenotes/notes/add-ssh-bastion-support-0e994a2a7f0d710a.yaml @@ -0,0 +1,40 @@ +--- +features: + - | + Add SSH bastion/jump host support for OpenStack builder template. + The following new variables are now available for configuring SSH + bastion connections: + + - ``ssh_bastion_host`` - IP address or hostname of the bastion host + - ``ssh_bastion_username`` - Username for bastion authentication + - ``ssh_bastion_port`` - SSH port on bastion (default: 22) + - ``ssh_bastion_agent_auth`` - Use SSH agent for authentication (default: true) + - ``ssh_bastion_private_key_file`` - Path to SSH private key file + - ``ssh_bastion_password`` - Password for bastion authentication (not recommended) + + All bastion variables are optional with empty string defaults, making them + backward compatible with existing builds that don't require bastion access. + + Example usage: + + .. code-block:: bash + + packer build \\ + -var=ssh_bastion_host=100.64.183.39 \\ + -var=ssh_bastion_username=root \\ + -var-file=vars/ubuntu-22.04.pkrvars.hcl \\ + templates/builder.pkr.hcl + + This enables Packer builds to access OpenStack instances through a + bastion/jump host, which is required when direct access to OpenStack + networks is not available (e.g., in CI/CD environments using Tailscale + or other ephemeral bastion solutions). + + Reference: + https://developer.hashicorp.com/packer/integrations/hashicorp/openstack/latest/components/builder/openstack +upgrade: + - | + Existing builds using ``ssh_proxy_host`` will continue to work without + changes. The legacy proxy support is maintained for backward compatibility. + New deployments should use the SSH bastion variables for native jump host + support instead of proxy-based SSH tunneling. diff --git a/templates/builder.pkr.hcl b/templates/builder.pkr.hcl index 578eefa..8dd4b46 100644 --- a/templates/builder.pkr.hcl +++ b/templates/builder.pkr.hcl @@ -93,6 +93,43 @@ variable "ssh_proxy_host" { default = "" } +variable "ssh_bastion_host" { + type = string + default = "" + description = "Bastion/jump host for SSH access to OpenStack instances" +} + +variable "ssh_bastion_username" { + type = string + default = "" + description = "Username for bastion host authentication" +} + +variable "ssh_bastion_port" { + type = number + default = 22 + description = "SSH port on bastion host" +} + +variable "ssh_bastion_agent_auth" { + type = bool + default = true + description = "Use SSH agent for bastion authentication" +} + +variable "ssh_bastion_private_key_file" { + type = string + default = "" + description = "Path to SSH private key file for bastion authentication" +} + +variable "ssh_bastion_password" { + type = string + default = "" + sensitive = true + description = "Password for bastion host authentication (not recommended)" +} + variable "ssh_user" { type = string } @@ -140,7 +177,18 @@ source "openstack" "builder" { networks = ["${var.cloud_network}"] region = "${var.cloud_region}" source_image_name = "${var.base_image}" + + # Legacy proxy support (kept for backwards compatibility) ssh_proxy_host = "${var.ssh_proxy_host}" + + # Bastion/Jump host support + ssh_bastion_host = var.ssh_bastion_host != "" ? var.ssh_bastion_host : null + ssh_bastion_username = var.ssh_bastion_username != "" ? var.ssh_bastion_username : null + ssh_bastion_port = var.ssh_bastion_port + ssh_bastion_agent_auth = var.ssh_bastion_agent_auth + ssh_bastion_private_key_file = var.ssh_bastion_private_key_file != "" ? var.ssh_bastion_private_key_file : null + ssh_bastion_password = var.ssh_bastion_password != "" ? var.ssh_bastion_password : null + ssh_username = "${var.ssh_user}" use_blockstorage_volume = "${var.vm_use_block_storage}" user_data_file = "${var.cloud_user_data}" diff --git a/templates/devstack-pre-pip-yoga.pkr.hcl b/templates/devstack-pre-pip-yoga.pkr.hcl index 842a1a2..40c3e9d 100644 --- a/templates/devstack-pre-pip-yoga.pkr.hcl +++ b/templates/devstack-pre-pip-yoga.pkr.hcl @@ -80,6 +80,43 @@ variable "ssh_proxy_host" { default = "" } +variable "ssh_bastion_host" { + type = string + default = "" + description = "Bastion/jump host for SSH access to OpenStack instances" +} + +variable "ssh_bastion_username" { + type = string + default = "" + description = "Username for bastion host authentication" +} + +variable "ssh_bastion_port" { + type = number + default = 22 + description = "SSH port on bastion host" +} + +variable "ssh_bastion_agent_auth" { + type = bool + default = true + description = "Use SSH agent for bastion authentication" +} + +variable "ssh_bastion_private_key_file" { + type = string + default = "" + description = "Path to SSH private key file for bastion authentication" +} + +variable "ssh_bastion_password" { + type = string + default = "" + sensitive = true + description = "Password for bastion host authentication (not recommended)" +} + variable "source_ami_filter_name" { type = string default = null @@ -145,7 +182,18 @@ source "openstack" "devstack-pre-pip-yoga" { networks = ["${var.cloud_network}"] region = "${var.cloud_region}" source_image_name = "${var.base_image}" + + # Legacy proxy support (kept for backwards compatibility) ssh_proxy_host = "${var.ssh_proxy_host}" + + # Bastion/Jump host support + ssh_bastion_host = var.ssh_bastion_host != "" ? var.ssh_bastion_host : null + ssh_bastion_username = var.ssh_bastion_username != "" ? var.ssh_bastion_username : null + ssh_bastion_port = var.ssh_bastion_port + ssh_bastion_agent_auth = var.ssh_bastion_agent_auth + ssh_bastion_private_key_file = var.ssh_bastion_private_key_file != "" ? var.ssh_bastion_private_key_file : null + ssh_bastion_password = var.ssh_bastion_password != "" ? var.ssh_bastion_password : null + ssh_username = "${var.ssh_user}" use_blockstorage_volume = "${var.vm_use_block_storage}" user_data_file = "${var.cloud_user_data}" diff --git a/templates/devstack.pkr.hcl b/templates/devstack.pkr.hcl index 771d79d..48feb6a 100644 --- a/templates/devstack.pkr.hcl +++ b/templates/devstack.pkr.hcl @@ -83,6 +83,43 @@ variable "ssh_proxy_host" { default = "" } +variable "ssh_bastion_host" { + type = string + default = "" + description = "Bastion/jump host for SSH access to OpenStack instances" +} + +variable "ssh_bastion_username" { + type = string + default = "" + description = "Username for bastion host authentication" +} + +variable "ssh_bastion_port" { + type = number + default = 22 + description = "SSH port on bastion host" +} + +variable "ssh_bastion_agent_auth" { + type = bool + default = true + description = "Use SSH agent for bastion authentication" +} + +variable "ssh_bastion_private_key_file" { + type = string + default = "" + description = "Path to SSH private key file for bastion authentication" +} + +variable "ssh_bastion_password" { + type = string + default = "" + sensitive = true + description = "Password for bastion host authentication (not recommended)" +} + variable "source_ami_filter_name" { type = string default = null @@ -147,7 +184,18 @@ source "openstack" "devstack" { networks = ["${var.cloud_network}"] region = "${var.cloud_region}" source_image_name = "${var.base_image}" + + # Legacy proxy support (kept for backwards compatibility) ssh_proxy_host = "${var.ssh_proxy_host}" + + # Bastion/Jump host support + ssh_bastion_host = var.ssh_bastion_host != "" ? var.ssh_bastion_host : null + ssh_bastion_username = var.ssh_bastion_username != "" ? var.ssh_bastion_username : null + ssh_bastion_port = var.ssh_bastion_port + ssh_bastion_agent_auth = var.ssh_bastion_agent_auth + ssh_bastion_private_key_file = var.ssh_bastion_private_key_file != "" ? var.ssh_bastion_private_key_file : null + ssh_bastion_password = var.ssh_bastion_password != "" ? var.ssh_bastion_password : null + ssh_username = "${var.ssh_user}" use_blockstorage_volume = "${var.vm_use_block_storage}" user_data_file = "${var.cloud_user_data}" diff --git a/templates/docker.pkr.hcl b/templates/docker.pkr.hcl index 249d695..d157dbf 100644 --- a/templates/docker.pkr.hcl +++ b/templates/docker.pkr.hcl @@ -98,6 +98,43 @@ variable "ssh_proxy_host" { default = "" } +variable "ssh_bastion_host" { + type = string + default = "" + description = "Bastion/jump host for SSH access to OpenStack instances" +} + +variable "ssh_bastion_username" { + type = string + default = "" + description = "Username for bastion host authentication" +} + +variable "ssh_bastion_port" { + type = number + default = 22 + description = "SSH port on bastion host" +} + +variable "ssh_bastion_agent_auth" { + type = bool + default = true + description = "Use SSH agent for bastion authentication" +} + +variable "ssh_bastion_private_key_file" { + type = string + default = "" + description = "Path to SSH private key file for bastion authentication" +} + +variable "ssh_bastion_password" { + type = string + default = "" + sensitive = true + description = "Password for bastion host authentication (not recommended)" +} + variable "ssh_user" { type = string default = null @@ -146,7 +183,18 @@ source "openstack" "docker" { networks = ["${var.cloud_network}"] region = "${var.cloud_region}" source_image_name = "${var.base_image}" + + # Legacy proxy support (kept for backwards compatibility) ssh_proxy_host = "${var.ssh_proxy_host}" + + # Bastion/Jump host support + ssh_bastion_host = var.ssh_bastion_host != "" ? var.ssh_bastion_host : null + ssh_bastion_username = var.ssh_bastion_username != "" ? var.ssh_bastion_username : null + ssh_bastion_port = var.ssh_bastion_port + ssh_bastion_agent_auth = var.ssh_bastion_agent_auth + ssh_bastion_private_key_file = var.ssh_bastion_private_key_file != "" ? var.ssh_bastion_private_key_file : null + ssh_bastion_password = var.ssh_bastion_password != "" ? var.ssh_bastion_password : null + ssh_username = "${var.ssh_user}" use_blockstorage_volume = "${var.vm_use_block_storage}" user_data_file = "${var.cloud_user_data}" diff --git a/templates/variables.auto.pkr.hcl b/templates/variables.auto.pkr.hcl index 5fd45ef..03a3b36 100644 --- a/templates/variables.auto.pkr.hcl +++ b/templates/variables.auto.pkr.hcl @@ -108,6 +108,37 @@ variable "ssh_proxy_host" { default = "" } +variable "ssh_bastion_host" { + type = string + default = "" +} + +variable "ssh_bastion_username" { + type = string + default = "" +} + +variable "ssh_bastion_port" { + type = number + default = 22 +} + +variable "ssh_bastion_agent_auth" { + type = bool + default = true +} + +variable "ssh_bastion_private_key_file" { + type = string + default = "" +} + +variable "ssh_bastion_password" { + type = string + default = "" + sensitive = true +} + variable "ssh_user" { type = string default = null diff --git a/templates/windows-builder.pkr.hcl b/templates/windows-builder.pkr.hcl index c5277d5..f744cc2 100644 --- a/templates/windows-builder.pkr.hcl +++ b/templates/windows-builder.pkr.hcl @@ -83,6 +83,43 @@ variable "ssh_proxy_host" { default = null } +variable "ssh_bastion_host" { + type = string + default = "" + description = "Bastion/jump host for SSH access to OpenStack instances" +} + +variable "ssh_bastion_username" { + type = string + default = "" + description = "Username for bastion host authentication" +} + +variable "ssh_bastion_port" { + type = number + default = 22 + description = "SSH port on bastion host" +} + +variable "ssh_bastion_agent_auth" { + type = bool + default = true + description = "Use SSH agent for bastion authentication" +} + +variable "ssh_bastion_private_key_file" { + type = string + default = "" + description = "Path to SSH private key file for bastion authentication" +} + +variable "ssh_bastion_password" { + type = string + default = "" + sensitive = true + description = "Password for bastion host authentication (not recommended)" +} + variable "ssh_user" { type = string default = null