AWS Setting Hostname by Tag

From Federal Burro of Information
Jump to navigationJump to search

From Scalar Managed Services Wiki

Overview

This page outlines a way in which you can make sure that the hostname on a instance matches the "Name" tag that you tagged it with when you lit it up.

This does not update DNS internal or external.

This process uses an IAM instance profile to give an instance the permission to see it's own tags.

This process depends on the instance using cloud-init to do the work on first boot.

This process is persistent; If you reboot the machine, it keep the same hostname as the "Name" tag that it had when it first booted.

This process updated /etc/hosts and /etc/sysconfig/

If you later change the tag, simple run /root/sethostnmae.sh again to update everything.

This process required that the pythin aws cli is installed.

This process works on and was test with a centos 7 instance YMMV.

This was my starting place: https://www.mind-it.info/2014/03/09/setting-ec2-hostname-via-tags/

Parts

In user data ( cloud-init ):

runcmd:
 - [ /usr/bin/pip2.7, install, --upgrade, awscli ]
 - [ /root/sethostname.sh ]

packages:
 - python27-pip
 - python-pip

write_files:
  - content: |
      SERVER=$(/usr/bin/aws ec2 describe-tags --region ca-central-1 --filters "Name=resource-id,Values=$(wget -q -O - http://169.254.169.254/latest/meta-data/instance-id)" "Name=key,Values=Name" --query 'Tags[*].Value' --output text)
      PRIVATE_IP=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)
      sed -i "s/^\(HOSTNAME\s*=\s*\).*$/\1$SERVER/" /etc/sysconfig/network
      echo "$PRIVATE_IP $SERVER" >> /etc/hosts
      hostname $SERVER
    path: /root/sethostname.sh
    permissions: '0755'
    owner: root:root


You must give the instance an "instance profile" with the "describe tags" permission. ( http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeTags.html )

Here's how that's done with terraform, in this case a "render" instance.

data "template_file" "render_instance_policy_file" {
  template = "${file("templates/render_instance_policy.json.tpl")}"

  vars = {
    customer = "${var.customer}"
    project  = "${var.customer}"
  }
}

resource "aws_iam_instance_profile" "render_iam_profile" {
  name  = "render_iam_profile"
  roles = ["${aws_iam_role.render_instance_role.name}"]
}

resource "aws_iam_role_policy" "render_instance_policy" {
  name   = "render_instance_policy"
  role   = "${aws_iam_role.render_instance_role.id}"
  policy = "${data.template_file.render_instance_policy_file.rendered}"
}

resource "aws_iam_role" "render_instance_role" {
  name               = "render_instance_role"
  path               = "/"
  assume_role_policy = "${file("templates/assume_role_policy.json.tpl")}"
}

resource "aws_instance" "node" {
  ...
  iam_instance_profile   = "${aws_iam_instance_profile.render_iam_profile.id}"
  ...
}​


render_instance_policy.json.tpl is :

{
   "Version": "2012-10-17",
   "Statement": [{
      "Effect": "Allow",
      "Action": "ec2:DescribeTags",
      "Resource": "*"
    }
   ]
}

The dependencies are organized like this:

aws_instance -> aws_iam_instance_profile -> aws_iam_role -> aws_iam_role_policy -> policy_file