91 lines
3.2 KiB
Python
Executable File
91 lines
3.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
from flask import Flask, Response, request, jsonify
|
|
from flask_httpauth import HTTPBasicAuth
|
|
from base64 import b64encode
|
|
from requests import get, put, delete
|
|
from os import getenv
|
|
|
|
# Define global variables for MIAB host and auth header, to be set during authentication
|
|
MIAB_HOST = getenv('MIAB_HOST', 'localhost')
|
|
MIAB_AUTH_HEADER = ''
|
|
|
|
app = Flask('dns-updater')
|
|
auth = HTTPBasicAuth()
|
|
|
|
# Verify username and password by attempting to access a dummy DNS record
|
|
@auth.verify_password
|
|
def verify(username, password):
|
|
global MIAB_AUTH_HEADER, MIAB_HOST
|
|
MIAB_AUTH_HEADER = "Basic " + b64encode(f"{username}:{password}".encode()).decode()
|
|
result = get(f'https://{MIAB_HOST}/admin/dns/custom/test/A', headers={'Authorization': MIAB_AUTH_HEADER})
|
|
if result.status_code != 200:
|
|
return False
|
|
|
|
return True
|
|
|
|
@app.route('/api/setrecord/<qname>/<value>', methods=['GET'], defaults={'rtype': 'A'})
|
|
@app.route('/api/setrecord/<qname>/<rtype>/<value>', methods=['GET'])
|
|
@app.route('/api/setrecord/<qname>', methods=['PUT'], defaults={'rtype': 'A'})
|
|
@app.route('/api/setrecord/<qname>/<rtype>', methods=['PUT'])
|
|
@auth.login_required
|
|
def set_record(qname, rtype, value = None):
|
|
global MIAB_HOST, MIAB_AUTH_HEADER
|
|
|
|
# Use request data as value for PUT method
|
|
if request.method == 'PUT':
|
|
value = request.data.decode()
|
|
|
|
url = f'https://{MIAB_HOST}/admin/dns/custom/{qname}/{rtype}'
|
|
resp = put(url, headers={'Authorization': MIAB_AUTH_HEADER, 'Content-Type': 'text/plain'}, data=value)
|
|
|
|
# Propagate 400-499 as is, 500+ as 502
|
|
if resp.status_code != 200:
|
|
if 400 <= resp.status_code < 500:
|
|
status = resp.status_code
|
|
elif resp.status_code >= 500:
|
|
status = 502
|
|
else:
|
|
status = 500
|
|
return Response(f'ERROR\n', status=status)
|
|
|
|
# Success
|
|
return f'OK\n'
|
|
|
|
@app.route('/api/deleterecord/<qname>/<rtype>', methods=['GET', 'DELETE'])
|
|
@auth.login_required
|
|
def delete_record(qname, rtype):
|
|
global MIAB_HOST, MIAB_AUTH_HEADER
|
|
url = f'https://{MIAB_HOST}/admin/dns/custom/{qname}/{rtype}'
|
|
resp = delete(url, headers={'Authorization': MIAB_AUTH_HEADER, 'Content-Type': 'text/plain'}, data='')
|
|
|
|
# Propagate 400-499 as is, 500+ as 502
|
|
if resp.status_code != 200:
|
|
if 400 <= resp.status_code < 500:
|
|
status = resp.status_code
|
|
elif resp.status_code >= 500:
|
|
status = 502
|
|
else:
|
|
status = 500
|
|
return Response(f'ERROR\n', status=status)
|
|
|
|
# Success
|
|
return f'OK\n'
|
|
|
|
@app.route('/api/listrecords', methods=['GET'], defaults={'qname': None, 'rtype': None})
|
|
@app.route('/api/listrecords/<qname>', methods=['GET'], defaults={'rtype': None})
|
|
@app.route('/api/listrecords/<qname>/<rtype>', methods=['GET'])
|
|
@auth.login_required
|
|
def list_records(qname, rtype):
|
|
global MIAB_HOST, MIAB_AUTH_HEADER
|
|
url = f'https://{MIAB_HOST}/admin/dns/custom'
|
|
if qname:
|
|
url += f'/{qname}'
|
|
if rtype:
|
|
url += f'/{rtype}'
|
|
resp = get(url, headers={'Authorization': MIAB_AUTH_HEADER})
|
|
return jsonify(resp.json())
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True, host='0.0.0.0', port=8080)
|