How to programmatically use your public Internet IP address in Terraform?

· Updated · 1 min read · Terraform & OpenTofu Tutorials

Programmatically use your public IP in Terraform as source IP for AWS Security Rules #

While testing Terraform plans, sometimes there is a need to create firewall rules that use your current public Internet IP address, for example for SSH access to the created instances.

Updates:

  • 2020 Jun 29: Upgraded to Terraform 0.12
  • 2020 Oct 19: Set IPV4 switch -4 in dig command as suggested by Reque.

There is an easy way to programmatically obtain the IP address using a Terraform External Data Source.

Create a shell script that obtains the IP address and returns the value in a JSON object.

whatismyip.sh

#!/bin/bash
...
set -e
INTERNETIP="$(dig +short myip.opendns.com @resolver1.opendns.com -4)"
echo $(jq -n --arg internetip "$INTERNETIP" '{"internet_ip":$internetip}')

Call the external data source and use the output in a firewall rule. The example in aws_security_group_rules.tf shows how to use the public IP address in an AWS security rule created by Terraform to allow SSH access.

aws_security_group_rules.tf

data "external" "whatismyip" {
  program = ["/bin/bash" , "${path.module}/whatismyip.sh"]
}
resource "aws_security_group_rule" "allow_ssh_from_my_ip" {
 type = "ingress"
 from_port = 22
 to_port = 22
 protocol = "tcp"
 cidr_blocks = [format("%s/%s",data.external.whatismyip.result["internet_ip"],32)]
 security_group_id = "sg-123456"
}

Make sure to install the jq utility and make whatismyip.sh executable using:

sudo apt-get install jq
chmod 755 whatismyip.sh

Since you are now using an additional provider (the External Data Source), initialize Terraform or OpenTofu using:

terraform init   # or: tofu init

Alternative without scripts: the http data source #

The http provider obtains the address without an external script, jq or dig:

data "http" "my_ip" {
  url = "https://checkip.amazonaws.com"
}

resource "aws_vpc_security_group_ingress_rule" "ssh_from_my_ip" {
  security_group_id = aws_security_group.base.id
  ip_protocol       = "tcp"
  from_port         = 22
  to_port           = 22
  cidr_ipv4         = "${chomp(data.http.my_ip.response_body)}/32"
}

Better than opening SSH to a fixed IP address is to use AWS Systems Manager Session Manager, which needs no inbound rules.

See more Terraform and Ansible examples (see also AWS Security Groups):

#AWS #OpenTofu #Terraform