This is not per the docs or the reference

I will caveat much of this blog entry with the fact that I am far from an AWS novice. I don’t mean I am beyond a novice, I literally mean I know the absolute basics and that I am slowly rectifying.

Requirements - Update Security Group with Dynamic IP

I have a deployment of some Nomad and Consul nodes across some Availability Zones. Each role for the instances, such as Nomad Server or Nomad Client, have Security Groups. These groups have rules such as the following in my Terraform Module below:

  ingress_rules = [
    {
      port        = 22
      cidr_blocks = ["10.0.0.0/16"]
    },
    {
      port        = 8300
      cidr_blocks = ["0.0.0.0/0"]
    },

As we can see I am allowing only sources on SSH/22 access to the instances assigned or associated with this Security Group. This is a great posture to have. I had a fork in the road decision to make - do I drop a bastion host or do I open up the instances for SSH from a specific IP?

So to summarise:

  • Learn or discover know IP of my executing devices network
  • Be required to append the address to a new or existing configuration with Terraform
  • Ensure it can be automated end to end or if not, within decent reason
  • Minimise potential attack surface

First step - I evaluated the risk profile. If I opened up SSH what’s the potential risk? Given that the instances I deploy use SSH key pairs an attacker would need MY SSH keys I have in AWS. Second - if I am using a specific IP address they would need MY IP or somehow spoof, route, and advertise that IP in conjunction with my keypair. Is it possible? Sure, anything is, but I deemed the attack surface very small.

Updating a static entry with dynamic values

My Internet connection at home (where most of the magic happens) has a dynamic IP. I’d rather pay for speed and bandwidth over a static IP so I work with what I have got.

I want to ensure the Security Group has a /32 entry for my home network to ensure that only devices at home with the source address defined gain access to this environment.

Terraform Cheekiness

I am using the http provider for Terraform to perform a GET request against a website. This website outputs the value of the current IP assigned to the network.

data "http" "myip" {
  url = "https://ipv4bot.whatismyipaddress.com"
  request_headers = {
    Accept = "application/json"
  }
}

output "myip" {
  value = data.http.myip.body
}

This will ensure the value of myip is placed into the state file. I can now read the state file from the another Terraform manifest, or leveraging the ‘remote state’ functions of Terraform Cloud / Enterprise.

My nomad-cloud content which deploys an active and working Nomad topology reads the details out of myip for the values of it’s SecurityGroup. See below for the example of reading state from another workspace.

First required is the reference to where the state and remote backend is by using the data type terraform_remote_state.

data "terraform_remote_state" "cloud-nomad-myip" {
  backend = "remote"

  config = {
    organization = "burkey"
    workspaces = {
      name = "cloud-nomad-myip"
    }
  }
}

Then once defined it can be referenced like so:

module "consul_server_sg" {
  source = "burkey/aws-sg"
  vpc_id = module.vpc.vpc_id
  ingress_rules = [
    {
      port        = 22
      cidr_blocks = ["10.0.0.0/16", "${data.terraform_remote_state.cloud-nomad-myip.outputs.myip}/32"]
    },

The value of the cross workspace state is “${data.terraform_remote_state.cloud-nomad-myip.outputs.myip}“. Breaking it down:

  • data - object type
  • terraform_remote_state - object
  • cloud-nomad-ip - workspace name
  • outputs - the output from the original snippet listed above
  • myip the specific output if there were more than one (say 2-3 IPs)

Cool beans, right?

Here is my 4G IP Updated IP from 4G device Here is todays ISP provided address Updated IP from ISP

Improvements from here

There are other methods that solve the requirement of secure access to this environment and that would absolve the approach I have taken here.

  • VPN - I could deploy a VPN to connect to the inside of this environment eliminating the need for this
  • Bastion Host - Similar to the VPN - I could be running a host that becomes an administration box for the environment
  • Cron Job I could cron job what I have now and wrap up an API call to do the terraform plan/apply and speculative plan against the target workspace. This may be the path of success for myself

Closing

So here is a method I hacked together based on my requirements. It’s most likely the most straight forward approach as all I need to do is run a terraform apply on the device (on behalf of the network) that needs access and then run a speculative plan against my cloud-nomad workspace.

What are your thoughts below?