Skip to content

Latest commit

 

History

History
executable file
·
138 lines (99 loc) · 5.01 KB

README.md

File metadata and controls

executable file
·
138 lines (99 loc) · 5.01 KB

This terraform module allows to communicate with a resource via an SSH tunnel.

I use it to create and configure databases on AWS RDS instances but it can be used to access any target/port. My RDS instances are connected to private subnets only and, so, cannot be accessed directly from the desktop I'm running terraform on. Running terraform on a host inside the VPC could be a solution but too complex to install and manage. An easier solution was to access my resources via an SSH tunnel on an SSH bastion host. Everything you need is a host which can connect to your private resources and that you can access from your client using SSH (this is generally named 'bastion host').

Please note that, when the 'create' input variable is false or the 'gateway_host' input variable is an empty string, no tunnel is created and the target host and port are returned, causing a direct connection to the target. So, input variables are used to decide whether a tunnel is wanted or not.

SSH command and options

By default, the module will use the 'ssh' string to launch the SSH client executable. This implies, among others that running 'ssh ' opens a connection to the bastion host (without asking any confirmation).

But you may need to modify this string if, for instance, you want to:

  • specify an absolute path and/or a different name when your SSH client is not in your path or has a different name (some use 'openssh')
  • Add options to pass to the SSH command like, '-o StrictHostKeyChecking=no' to avoid failures on non-registered bastions or '-i <key>' to specify an alternate private key.

Specifying an alternate SSH command is done by setting the 'ssh_cmd' variable to the command with options.

Please note that the SSH process inherits your environment, including a possible SSH agent configuration to retrieve your private key.

Target host name resolution

When supplying the target DNS name, note that the name will be resolved by the bastion host, not by the client you're running terraform on. So, you can use a private DNS name, like 'xxxx.csdfkzpf0iww.eu-west-1.rds.amazonaws.com' without having to convert it to an IP address first.

Combining multiple providers

As you can see in the example below, using a provider alias is encouraged as it is cleaner and makes it possible from a single provider to combine access to multiple targets, either tunneled or not.

Example

# On AWS, if your bastions are in an autoscaling group,here's a way
# to get a public IP address to use as gateway :

data aws_instances bastions {
  instance_tags = {
    "aws:autoscaling:groupName" = "replace_with_bastion_autoscaling_group_name"
  }
}

#----

module db_tunnel {
  # You can also retrieve this module from the terraform registry
  source       = "flaupretre/tunnel/ssh"
  version      = "1.5.0"

  target_host  = aws_db_instance.mydb.address
  target_port  = aws_db_instance.mydb.port

  gateway_host = data.aws_instances.bastions.public_ips[0]
}

#----

provider mysql {
  alias    = "tunnel"

  endpoint = "${module.db_tunnel.host}:${module.db_tunnel.port}"

  # Target credentials
  username = aws_db_instance.mydb.username
  password = aws_db_instance.mydb.password
}

#---- DB resources

resource mysql_database this {
  provider = mysql.tunnel
  name = local.name
}

resource mysql_user user {
  provider = mysql.tunnel
  ....

Requirements

No requirements.

Providers

Name Version
external n/a

Modules

No modules.

Resources

Name Type
external_external.port_forward data source

Inputs

Name Description Type Default Required
kubectl_cmd Kubectl command to use string "kubectl" no
local_port Local port number number n/a yes
resource The target resource. Can be a service, pod, deployment, etc. See kubectl port-forward for more info. string n/a yes
shell_cmd Command to run a shell string "bash" no
target_port Target port number number n/a yes
timeout Timeout value ensures tunnel won't remain open forever string "30m" no
tunnel_check_sleep extra time to wait for kubectl tunnel to connect string "0s" no

Outputs

Name Description
host Port number to connect to
port Port number to connect to