This terraform module allows to communicate with a resource via an SSH tunnel.
It is used, for instance, to create and configure databases on AWS RDS instances. Creating RDS instances is easy, as it uses the AWS API, which is public but, creating databases is harder because it requires connecting to the instance which is, usually, connected to private subnets only. Running terraform on a host inside the AWS VPC would be a solution but often too complex to install and manage.
An alternate solution is to access remote resources via an SSH tunnel through an SSH bastion host. There are two conditions :
- The bastion host can open a connection to the target host/port,
- and you can open an SSH connection to the bastion from your client.
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, this module can be used in a scenario where you don't know in advance if your connection will require a tunnel or not, passing configuration parameters you receive from the outside, and using the host/port you receive from the module.
By default, the module uses the 'ssh -o StrictHostKeyChecking=no' string in the command to launch the SSH client. If you use a different SSH client name/path or if you want to add/remove options, you can modify this string by setting the 'ssh_cmd' input variable. This may be used, for instance, to set the private key to use with a '-i' option.
When supplying the target DNS name, 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.
The SSH client process inherits your environment, including a possible SSH agent configuration to retrieve your private key.
Please also note that the module cannot be used to create a tunnel running through a set of several SSH gateways, each one opening an SSH connection to the next one. This is technically possible using the 'ProxyJump' feature introduced in OpenSSH v7.3 and the feature may be added in a future version, depending on user's demand (I personally don't need it yet).
You may also be interested by the terraform-ssh-tunnel-databases module, which uses SSH tunnels to manage MySql/PostgreSql databases, roles, and permissions.
# On AWS, if your bastions are in an autoscaling group,here's a way
# to get a public IP address to use as a 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.10.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
....
No requirements.
Name | Version |
---|---|
external | n/a |
No modules.
Name | Type |
---|---|
external_external.free_port | data source |
external_external.ssh_tunnel | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
create | If false, do nothing and return target host | bool |
true |
no |
gateway_host | Name or IP of SSH gateway - empty string if no gateway (direct connection) | any |
"" |
no |
gateway_port | Gateway port | number |
22 |
no |
gateway_user | User to use on SSH gateway (default = empty string = current username) | any |
"" |
no |
local_host | Local host name or IP. Set only if you cannot use the '127.0.0.1' default value | string |
"127.0.0.1" |
no |
putin_khuylo | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | bool |
true |
no |
python_cmd | Command to run python | string |
"python" |
no |
shell_cmd | Command to run a shell | string |
"bash" |
no |
ssh_cmd | Shell command to use to start ssh client | string |
"ssh -o StrictHostKeyChecking=no" |
no |
ssh_tunnel_check_sleep | extra time to wait for ssh tunnel to connect | string |
"0s" |
no |
target_host | The target host. Name will be resolved by gateway | string |
n/a | yes |
target_port | Target port number | number |
n/a | yes |
timeout | Timeout value ensures tunnel won't remain open forever | string |
"30m" |
no |
Name | Description |
---|---|
host | Host to connect to |
port | Port number to connect to |