aboutsummaryrefslogtreecommitdiff
path: root/ddns/ddns.py
diff options
context:
space:
mode:
Diffstat (limited to 'ddns/ddns.py')
-rwxr-xr-xddns/ddns.py122
1 files changed, 0 insertions, 122 deletions
diff --git a/ddns/ddns.py b/ddns/ddns.py
deleted file mode 100755
index 0bde4f7..0000000
--- a/ddns/ddns.py
+++ /dev/null
@@ -1,122 +0,0 @@
1#!/usr/bin/env python
2
3import os
4import json
5import boto3
6import flask
7import hashlib
8import functools
9
10# pip install flask boto3
11
12# This is purely for documentation purposes
13__REQUIRED_IAM_POLICY__ = """
14{
15 "Version": "2012-10-17",
16 "Statement": [
17 {
18 "Effect": "Allow",
19 "Action": "ssm:GetParameter",
20 "Resource": "arn:aws:ssm:us-west-2::parameter/DDNS_CLIENTS"
21 },
22 {
23 "Effect": "Allow",
24 "Action": [
25 "route53:ListHostedZones",
26 "route53:ChangeResourceRecordSets"
27 ],
28 "Resource": "*"
29 }
30 ]
31}
32"""
33
34
35app = flask.Flask(__name__)
36
37
38def returns_plain_text(f):
39 @functools.wraps(f)
40 def wrapper(*args, **kwargs):
41 return flask.Response(f(*args, **kwargs), content_type="text/plain")
42
43 return wrapper
44
45
46def get_ip():
47 if "X-Forwarded-For" in flask.request.headers:
48 return flask.request.headers["X-Forwarded-For"]
49 else:
50 return flask.request.remote_addr
51
52
53def update_record(zone, record, ip):
54 client = boto3.client("route53")
55 zones = client.list_hosted_zones()["HostedZones"]
56
57 client.change_resource_record_sets(
58 HostedZoneId=[z["Id"] for z in zones if z["Name"] == zone][0],
59 ChangeBatch={
60 "Changes": [{
61 "Action": "UPSERT",
62 "ResourceRecordSet": {
63 "Name": ".".join((record, zone)),
64 "Type": "A",
65 "TTL": 60,
66 "ResourceRecords": [{
67 "Value": ip,
68 }]
69 }
70 }]
71 }
72 )
73
74
75@app.errorhandler(404)
76@app.errorhandler(405)
77@app.errorhandler(500)
78def handle_error(ex):
79 response = flask.Response("Error", content_type="text/plain")
80 response.status_code = getattr(ex, "code", 500)
81 return response
82
83
84@app.route("/new-secret", methods=["GET"])
85@returns_plain_text
86def new_secret():
87 return hashlib.sha256(os.urandom(100)).hexdigest()
88
89
90def get_client_config(client):
91 ssm = boto3.client("ssm")
92 clients = ssm.get_parameter(Name="DDNS_CLIENTS", WithDecryption=True)
93 config = json.loads(clients["Parameter"]["Value"])
94 return config.get(client)
95
96
97@app.route("/update", methods=["POST"])
98def update_ip():
99 key = flask.request.form.get("key")
100 config = get_client_config(key)
101
102 if not config:
103 flask.abort(404)
104
105 resource, zone = config.split(".", 1)
106
107 try:
108 update_record(zone, resource, get_ip())
109 return "OK"
110 except:
111 flask.abort(500)
112
113
114@app.route("/", methods=["GET"])
115@returns_plain_text
116def handle_home():
117 return get_ip()
118
119
120if __name__ == "__main__":
121 app.debug = True
122 app.run()