seansummers
5/22/2017 - 6:01 PM

EC2 instance verifier

EC2 instance verifier

"""
ssh_key=$(cut -f2 -d\  /etc/ssh/ssh_host_ed25519_key.pub)
document=$(curl -s http://169.254.169.254:/latest/dynamic/instance-identity/document |base64 -w 0)
signature=$(curl -s http://169.254.169.254:/latest/dynamic/instance-identity/signature |tr -d '\n')
curl -s http://169.254.169.254/latest/dynamic/instance-identity/signature |base64 -d |openssl rsautl -verify -inkey AWS.rsa -certin

"""
import json

from os import environ
from base64 import b64decode

import boto3
import rsa
import six

BUCKET = environ.get('BUCKET', 'libnd-global')

ec2 = boto3.resource('ec2')
s3 = boto3.resource('s3')
key = rsa.PublicKey(
    95318929170905151888329665240401444091282161020462124768285033014806370951275071516877911971246545424860101188830039891779094845649876855959262057141427470998542416206797397568522766060103937903652527298892685356856855778317104811739620406608569714766104002527470216783278061734986045788816288050922892785917,
    65537)


def ec2_resource(id, region):
    global ec2
    if region not in ec2.meta.client._endpoint.host:
        ec2 = boto3.resource('ec2', region_name=region)
    instance = ec2.Instance(id)
    return {
        'vpcId': instance.vpc_id,
        'subnetId': instance.subnet_id,
        'tags':
        {tag['Key']: tag['Value']
         for tag in getattr(instance, 'tags', ())},
    }


def resource(identity):
    if isinstance(identity, six.string_types):
        identity = json.loads(identity)
    id, region = identity['instanceId'], identity['region']

    data = ec2_resource(id, region)
    data.update(identity)

    return {k: v for k, v in six.iteritems(data) if v}


def save_host_data(identity, ssh_key):
    path = '/'.join(identity[k]
                    for k in ('accountId', 'vpcId', 'availabilityZone',
                              'subnetId', 'privateIp'))
    key = '/'.join((path, ssh_key))
    identity_json = json.dumps(identity, separators=(',', ':'), sort_keys=True)
    s3_obj = s3.Object(BUCKET, key).put(
        Body=identity_json,
        ContentType='application/json', )
    return s3_obj


def handler(event=None, context=None):
    data = event['data'].split('.')
    ssh_key, document, signature = data[0], b64decode(data[1]), b64decode(
        data[2])
    if rsa.verify(document, signature, key):
        host_data = resource(document)
        return save_host_data(host_data, ssh_key)


if __name__ == '__main__':

    event = {
        'data':
        ('AAAAC3NzaC1lZDI1NTE5AAAAILMHqWpOWppfAQ6XI1xjcLhuVWUvV7OzbLjP5kfanQ6j'
         '.'
         'ewogICJwcml2YXRlSXAiIDogIjE3Mi4yMi4xMC4yNDEiLAogICJkZXZwYXlQcm9kdWN0Q29kZXMiIDogbnVsbCwKICAiYXZhaWxhYmlsaXR5Wm9uZSIgOiAidXMtZWFzdC0xZCIsCiAgInZlcnNpb24iIDogIjIwMTAtMDgtMzEiLAogICJpbnN0YW5jZUlkIiA6ICJpLTBmNGFlNmMzNmNlNmNjNzhhIiwKICAiYmlsbGluZ1Byb2R1Y3RzIiA6IG51bGwsCiAgInBlbmRpbmdUaW1lIiA6ICIyMDE3LTAzLTMwVDE4OjM2OjA3WiIsCiAgImluc3RhbmNlVHlwZSIgOiAicjQubGFyZ2UiLAogICJhY2NvdW50SWQiIDogIjIzMDM5MTg0MDEwMiIsCiAgImFyY2hpdGVjdHVyZSIgOiAieDg2XzY0IiwKICAia2VybmVsSWQiIDogbnVsbCwKICAicmFtZGlza0lkIiA6IG51bGwsCiAgImltYWdlSWQiIDogImFtaS0wYjMzZDkxZCIsCiAgInJlZ2lvbiIgOiAidXMtZWFzdC0xIgp9'
         '.'
         'VkNmisiw50bXAi2CczD1ROnfFvSR+QQbtwfa+Bm3hr9hNGsqazL9lP9CIHEVJOKDH+UTPSsYeGAfWbB8NAdy2f9BskIdW+rBYZgHEP39einhHnTj+C0TasGi1WcC5jR1EspJwpL+7FnFdZLaTYnIRDHJ+VOXSFd9JF9j9HRqkeM='
         )
    }
    print(handler(event))