Syncing with AWS tags

How do I get the chef server to use AWS tags on my instances so I query my machines better?

Or is there some other tact I am missing?

Many thanks!

There’s no built-in method for this, but you can easily roll this yourself.

In my case, I have a userdata script that gets the tags assigned to the
instance, parses them, and passes them to chef-client. I’d be happy to
share a snippet if needed.

Thanks,
Ameir

Do please share Ameir!

Unfortunately doing this generically is hard. For whatever reason Amazon doesn’t include the instance tags in the magic metadata service so you have to pull them from the EC2 API, which means you need to all that perm to all your IAM roles, make sure every instance has a role on it, and use the role creds to do the query. If you have the role creds set up for all machines you can probably make an Ohai plugin pretty easily for this.

I’m not sure what you mean by role creds set up.

IIUC one need to run something like aws ec2 describe-tags for each region to pick out the tags for each instance. And then push that to the chef server. A simple script could do it, if I grokked knife!

Unless I am missing something?

@hendry This would work only with a chef server, the external ‘script’ would have to wipe out the tags beforehand to handle suppressions.

This won’t do for chef-solo or chef-zero, for their case you must be able to query tags from the instance itself, which means giving a role to each machine with proper AWS rights to describe tags on ec2.

Example of what @coderanger means (I hope I didn’t miss something obvious), a policies like this one should do:

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

And using the AWS ruby sdk in a recipe with something like this should add the tags in the node object (untested):

chef_gem 'aws-sdk' do
  compile_time true
end
require 'aws-sdk'

ec2 = Aws::EC2::Client.new(region: node['ec2']['placement_availability_zone'].chop) # brittle, assume the zone is always 1 letter
resp = ec2.describe_tags({ filters: [{name: "instance", values: [ #{node['ec2']['instance_id']} ] } ] })
resp.tags.each do |t|
  node.default['aws']['tags'][t.key] = t.value
end

Obviously, all instances will be able to list tags of all instances, which could be a security risk.

@hendry, I posted a gist of what I run as the userdata script on EC2 instances:

I use chef zero in production, so not all of that will apply. In short, though, I have a tag called chef_init with params like s=s3://<s3_path>/metadata;r=role[<role_name>];e=<environment_name>. The awk is to clean up colons that ASGs put in instance tags.

I eval that line so the variables are available, and then do chef-client -z -r '$r' -E '$e'.

Like @coderanger and @Tensibai stated, you need to have an instance role assigned to your instance that allows "ec2:DescribeTags".

If you change your instance tags, they’ll be reflected in your next Chef run.

Hopefully that helps you with your problem.

-Ameir