Initial commit
commit
93081cd6fc
Binary file not shown.
|
@ -0,0 +1,142 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# Dynamically update DNS records when the EC2 instance boots.
|
||||
# Requires boto3 installed on the instance.
|
||||
# Requries an IAM policy attached to an instance role.
|
||||
#
|
||||
|
||||
import urllib2
|
||||
from boto3.session import Session
|
||||
import boto3
|
||||
import datetime
|
||||
|
||||
def getRegion():
|
||||
url = "http://169.254.169.254/2009-04-04/meta-data/placement/availability-zone"
|
||||
try:
|
||||
resp = urllib2.urlopen(urllib2.Request(url))
|
||||
# Region will be a string like eu-central-1a. This chops the last character off.
|
||||
region = resp.read()[:-1]
|
||||
except urllib2.HTTPError as e:
|
||||
if e.code == 404:
|
||||
return None
|
||||
if e.code == 500:
|
||||
return None
|
||||
raise
|
||||
|
||||
return region
|
||||
|
||||
def getInstanceId():
|
||||
url = "http://169.254.169.254/2009-04-04/meta-data/instance-id"
|
||||
try:
|
||||
resp = urllib2.urlopen(urllib2.Request(url))
|
||||
instanceid = resp.read()
|
||||
except urllib2.HTTPError as e:
|
||||
if e.code == 404:
|
||||
return None
|
||||
if e.code == 500:
|
||||
return None
|
||||
raise
|
||||
|
||||
return instanceid
|
||||
|
||||
def getPublicIP():
|
||||
url = "http://169.254.169.254/2009-04-04/meta-data/public-ipv4"
|
||||
try:
|
||||
resp = urllib2.urlopen(urllib2.Request(url))
|
||||
value = resp.read()
|
||||
except urllib2.HTTPError as e:
|
||||
if e.code == 404:
|
||||
return None
|
||||
if e.code == 500:
|
||||
return None
|
||||
raise
|
||||
|
||||
return value
|
||||
|
||||
# Get region and instance ID
|
||||
myregion = getRegion()
|
||||
myinstance = getInstanceId()
|
||||
myipv4 = getPublicIP()
|
||||
|
||||
if( myregion == None or myinstance == None or myipv4 == None):
|
||||
print "ERROR: Could not get instance metadata. Abort."
|
||||
exit( -1 )
|
||||
|
||||
# Connect to EC2 and get the instance handle for this instance
|
||||
ec2 = boto3.resource('ec2', region_name=myregion)
|
||||
instance = ec2.Instance(myinstance)
|
||||
|
||||
# Grab the tags associated with this instance
|
||||
mytags = instance.tags
|
||||
dnsname = None
|
||||
|
||||
# Get host tag or bail
|
||||
for tag in instance.tags:
|
||||
if( tag['Key'] == 'dnsname'):
|
||||
dnsname = tag['Value']
|
||||
|
||||
if (dnsname == None):
|
||||
print "Did not find dnsname tag. "
|
||||
exit( -1 )
|
||||
|
||||
# Get just the domain part of dnsname
|
||||
myzone = dnsname.partition(".")[2]
|
||||
|
||||
# Get zoneid for zone or bail
|
||||
session = Session(region_name=myregion)
|
||||
client = session.client('route53')
|
||||
# Note: if you have more than 100 hosted zones, there's a chance that
|
||||
# the zone you need won't be returned in response to the first call
|
||||
# to list_hosted_zones(). The next loop will fail to find your zone.
|
||||
#
|
||||
# If this applies to you, you have to rewrite this section to use
|
||||
# pagination to iterate over the collection of returned domains,
|
||||
# looking for the one you want. That extension is left as an
|
||||
# exercise for the reader.
|
||||
myzoneid = None
|
||||
zones = client.list_hosted_zones()
|
||||
|
||||
# Route53 will return zones in canonical form with the trailing dot.
|
||||
# e.g.: "ec2.example.com."
|
||||
# It's likely that people will enter dnsnames in the tags without the
|
||||
# trailing dot, so this helps make the match either way.
|
||||
for zone in zones['HostedZones']:
|
||||
if( (zone['Name'] == myzone) or (zone['Name'] == myzone + ".")):
|
||||
myzoneid = zone['Id']
|
||||
|
||||
if( myzoneid == '' ):
|
||||
# didn't find the zone
|
||||
print "ERROR: Did not find " + myzone + " among the hosted zones."
|
||||
exit( -1 )
|
||||
|
||||
# Create record set update
|
||||
print "setting " + dnsname + " to " + myipv4
|
||||
now = datetime.datetime.now()
|
||||
|
||||
response = client.change_resource_record_sets(
|
||||
HostedZoneId=myzoneid,
|
||||
ChangeBatch={
|
||||
'Comment': 'Instance ' + myinstance + ' boot at ' + now.strftime("%Y-%m-%d %H:%M"),
|
||||
'Changes': [
|
||||
{
|
||||
'Action': 'UPSERT',
|
||||
'ResourceRecordSet': {
|
||||
'TTL': 300,
|
||||
'Name': dnsname,
|
||||
'Type': 'A',
|
||||
'ResourceRecords': [
|
||||
{
|
||||
'Value': myipv4
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# Check for error.
|
||||
if( response['ResponseMetadata']['HTTPStatusCode'] != 200 ):
|
||||
print "ERROR updating Route53"
|
||||
print response
|
||||
exit( -1 )
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"route53:ChangeResourceRecordSets",
|
||||
"route53:GetHostedZone",
|
||||
"route53:ListResourceRecordSets"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": [
|
||||
"arn:aws:route53:::hostedzone/[ZONEID]",
|
||||
]
|
||||
},
|
||||
{
|
||||
"Action": [
|
||||
"route53:ListHostedZones",
|
||||
"ec2:DescribeInstances"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue