Skip to content

Instantly share code, notes, and snippets.

@danielloader
Last active September 22, 2019 20:08
Show Gist options
  • Save danielloader/6dbb20dce97ae0c7a08094740608f9ce to your computer and use it in GitHub Desktop.
Save danielloader/6dbb20dce97ae0c7a08094740608f9ce to your computer and use it in GitHub Desktop.
import sys
import argparse
import urllib.request
import urllib.parse
import json
from collections.abc import Mapping
from pprint import pprint
import os.path
global dict_endpoints
dict_endpoints = {}
global base_path
base_path = "http://169.254.169.254/2016-09-02/meta-data/"
if sys.version_info <= (3, 0):
sys.stdout.write("Sorry, requires Python 3.x, not Python 2.x\n")
sys.exit(1)
parser = argparse.ArgumentParser()
parser.add_argument(
"-e,",
"--endpoint",
nargs="+",
help="Metadata endpoint, space seperated for children and grandchildren",
required=False,
)
args = parser.parse_args()
def remove_slashes(obj):
if isinstance(obj, Mapping):
return {key.replace("/", ""): remove_slashes(val) for key, val in obj.items()}
return obj
def get_data(url):
if isinstance(url, list):
url = os.path.join(*url)
url = urllib.parse.urljoin(base_path, url)
try:
with urllib.request.urlopen(url) as response:
return response.read().decode("utf-8").splitlines()
except:
pass
def list_parser(endpoint_list):
return [remove_slash(i) for i in endpoint_list]
def response_string(item_list):
if len(item_list) == 1:
return str(item_list[0])
else:
return item_list
endpoints = get_data(None)
def end_checker(endpoint):
children = get_data(endpoint)
for child in children:
grandchild = os.path.join(endpoint, child)
check = get_data(grandchild)
try:
if str(check[0]) == child:
return True
except:
return False
def list_builder(endpoints):
for endpoint in endpoints:
children = get_data(endpoint)
if endpoint == "public-keys/":
dict_endpoints[endpoint] = str(children[0])
continue
if end_checker(endpoint):
dict_endpoints[endpoint] = children[0]
else:
for x in children:
dict_endpoints[endpoint] = children
def paths_to_value(value, d, current_path=None):
if current_path is None:
current_path = []
for k, v in d.items():
if isinstance(v, list):
yield current_path + [k]
else:
if isinstance(v, dict):
path = current_path + [k]
yield from paths_to_value(value, v, path)
list_builder(endpoints)
for x in paths_to_value([], dict_endpoints):
x = str(x[0])
dict_endpoints[x] = {}
for item in get_data(x):
nested_endpoint = os.path.join(x, item)
resp = get_data(nested_endpoint)
dict_endpoints[x][item] = str(resp[0])
dict_endpoints = (remove_slashes(dict_endpoints))
if args.endpoint:
path = os.path.join(*args.endpoint)
print(json.dumps({path:get_data(path)}))
else:
print(json.dumps(dict_endpoints, sort_keys=True, indent=4))
"""
Example output:
ubuntu@ip-172-31-18-225:~/source$ python3 aws_metadata_json.py
{
"ami-id": "ami-077a5b1762a2dde35",
"ami-launch-index": "0",
"ami-manifest-path": "(unknown)",
"block-device-mapping": {
"ami": "/dev/sda1",
"root": "/dev/sda1"
},
"hostname": "ip-172-31-18-225.eu-west-2.compute.internal",
"instance-action": "none",
"instance-id": "i-0273abcf0956d27b3",
"instance-type": "t2.micro",
"local-hostname": "ip-172-31-18-225.eu-west-2.compute.internal",
"local-ipv4": "172.31.18.225",
"mac": "06:69:99:78:86:06",
"metrics": {
"vhostmd": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
},
"network": {
"interfaces": "macs/"
},
"placement": {
"availability-zone": "eu-west-2a"
},
"profile": "default-hvm",
"public-hostname": "ec2-35-177-150-174.eu-west-2.compute.amazonaws.com",
"public-ipv4": "35.177.150.174",
"public-keys": "0=test",
"reservation-id": "r-0c0a503d55aea9b4e",
"security-groups": "launch-wizard-5",
"services": {
"domain": "amazonaws.com",
"partition": "aws"
}
}
ubuntu@ip-172-31-18-225:~/source$ python3 aws_metadata_json.py -e ami-id
{"ami-id": ["ami-077a5b1762a2dde35"]}
ubuntu@ip-172-31-18-225:~/source$ python3 aws_metadata_json.py -e block-device-mapping ami
{"block-device-mapping/ami": ["/dev/sda1"]
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment