def get(self, request, zone_origin): """GET Method handler, used to retrieve all information about a zone. This endpoint recieve no JSON data, if there's any, it will be ignored. This endpoint will return the following JSON file: { "origin" : "zone_origin", "directives" : { "directive1": "value1", ... } "records" : [ { "name" : "record_name", "rclass" : "record_rclass", "ttl" : "record_ttl", "rtype" : "record_rtype", "rdata" : { "rdata_name1" : "data", ... }, }, ... ] } """ # handle the get request try: logger.debug('FILE_LOCATION: ' + str(FILE_LOCATION)) logger.debug('ZONE_DICT: ' + str(ZONE_DICT)) logger.debug("ZONE_DIR: " + str(ZONE_DIR)) if not (zone_origin in FILE_LOCATION): raise ZoneError('Invalid Zone: ' + zone_origin) zone = DNSZone() zone.read_from_file(FILE_LOCATION[zone_origin]) return HttpResponse(zone.toJSON()) except ValueError as v_err: logger.warning(v_err.args) logger.warning(traceback.format_exc(2) + "\n\n\n") return HttpResponse('{"status" : "Invalid JSON arguments"}', status=500) except ZoneError as z_err: logger.error(z_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(z_err.args[0])+'"}', status=500) except BindError as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") backup_restore_file('restore', 'zone', zone_origin, '.bak') backup_restore_file('restore', 'named', find_server(zone_origin), '.bak') return HttpResponse('{"status" : "'+str(b_err.args[0])+'"}', status=500) except Exception as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(b_err)+'"}', status=500)
def reverse_record_delete(name, address, origin_zone): """Delete the associated reverse zone according to the address given.""" reverse_zone_origin = find_reverse_zone(address) if not (reverse_zone_origin in FILE_LOCATION): raise ZoneError("Invalid Reverse Zone: " + reverse_zone_origin) reverse_zone = DNSZone() reverse_zone.read_from_file(FILE_LOCATION[reverse_zone_origin]) record = reverse_zone.find_record(address.split('.')[3], rdata={'address': name + '.' + origin_zone + '.'}) reverse_zone.delete_record(address.split('.')[3], rdata={'address': name + '.' + origin_zone + '.'}) backup_restore_file('backup','zone',reverse_zone_origin,'.bak') reverse_zone.write_to_file(FILE_LOCATION[reverse_zone_origin]) logger.info("Deleted reverse record: " + str(record) + "\nOn zone: " + origin_zone) restart_bind(find_server(reverse_zone_origin))
def reverse_record_add(name, origin_zone, address, ttl=""): """Add the associated reverse zone according to the address given.""" reverse_zone_origin = find_reverse_zone(address) if not (reverse_zone_origin in FILE_LOCATION): raise ZoneError("Invalid Reverse Zone: " + reverse_zone_origin) reverse_zone = DNSZone() reverse_zone.read_from_file(FILE_LOCATION[reverse_zone_origin]) reverse_record = DNSResourceRecord() reverse_record.name = address.split('.')[3] reverse_record.ttl = ttl reverse_record.rclass = "IN" reverse_record.rtype = "PTR" reverse_record.rdata.address = name + '.' + origin_zone + '.' reverse_zone.add_record(reverse_record) backup_restore_file('backup','zone',reverse_zone_origin,'.bak') reverse_zone.write_to_file(FILE_LOCATION[reverse_zone_origin]) logger.info("Created reverse record: " + str(reverse_record) + "\nOn zone: " + origin_zone) restart_bind(find_server(reverse_zone_origin))
def get(self, request, zone_origin, record_name): """GET Method handler, used to retrieve all information about a record. This endpoint recieve the following JSON data as an optional search arguments { "rclass" : "record_rclass", "rtype" : "record_rtype", "rdata" : { "rdata_name1" : "data", ... }, } This endpoint will return the following JSON file: { "name" : "record_name", "rclass" : "record_rclass", "ttl" : "record_ttl", "rtype" : "record_rtype", "rdata" : { "rdata_name1" : "data", ... }, } And return {"status" : "notfound"} if the record file is not exist """ try: if request.body.decode('utf-8'): payload = json.loads(request.body.decode('utf-8')) rclass = payload.get("rclass") rtype = payload.get("rtype") rdata = payload.get("rdata") else: rclass = rtype = rdata = None if not (zone_origin in FILE_LOCATION): raise ZoneError('Invalid Zone: ' + zone_origin) zone = DNSZone() zone.read_from_file(FILE_LOCATION[zone_origin]) record = zone.find_record(record_name, rclass, rtype, rdata) logger.info("Get record: " + str(record) + "\nOn zone: " + zone_origin) return HttpResponse(record.toJSON() if record else '{"status" : "notfound"}') except ValueError as v_err: logger.warning(v_err.args) logger.warning(traceback.format_exc(2) + "\n\n\n") return HttpResponse('{"status" : "Invalid JSON arguments"}', status=500) except ZoneError as z_err: logger.error(z_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(z_err.args[0])+'"}', status=500) except BindError as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") if b_err['file_type']: backup_restore_file('restore', b_err['file_type'], b_err['origin'], '.bak') return HttpResponse('{"status" : "'+str(b_err.args['msg'])+'"}', status=500) except Exception as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(b_err)+'"}', status=500)
def post(self, request, zone_origin, record_name=""): """POST Method handler, used to create a new resource record. This endpoint recieve the following JSON file: { "name" : "new_record_name", "rclass" : "new_record_rclass", "ttl" : "new_record_ttl", "rtype" : "new_record_rtype", "rdata" : { "rdata_name1" : "data", ... }, } Note that rclass and TTL are optional. This endpoint will return { "status" : "ok" } if adding a new record is successfull and {"status" : "fail"} otherwise """ try: payload = json.loads(request.body.decode('utf-8')) if not (zone_origin in FILE_LOCATION): raise ZoneError('Invalid Zone: ' + zone_origin) zone = DNSZone() zone.read_from_file(FILE_LOCATION[zone_origin]) if (payload['rtype'] == "MX"): record_data = MXRecordData() elif (payload['rtype'] == "SOA"): record_data = SOARecordData() else: record_data = RecordData() new_record = DNSResourceRecord(rdata=record_data) new_record.fromJSON(payload) zone.add_record(new_record) backup_restore_file('backup','zone',zone_origin,'.bak') if new_record.rtype == "A" or new_record.rtype == "MX": reverse_record_add(new_record.name, zone_origin, new_record.rdata.address, new_record.ttl) zone.write_to_file(FILE_LOCATION[zone_origin]) logger.info("Created record: " + str(new_record) + "\nOn zone: " + zone_origin) # add reverse if rtype is A: restart_bind(find_server(zone_origin)) return HttpResponse('{"status" : "ok"}') except ValueError as v_err: logger.warning(v_err.args) logger.warning(traceback.format_exc(2) + "\n\n\n") return HttpResponse('{"status" : "Invalid JSON arguments"}', status=500) except ZoneError as z_err: logger.error(z_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(z_err.args[0])+'"}', status=500) except BindError as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") if b_err.args[0]['file_type']: backup_restore_file('restore', b_err.args[0]['file_type'], b_err.args[0]['origin'], '.bak') return HttpResponse('{"status" : "'+str(b_err.args[0]['msg'])+'"}', status=500) except Exception as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(b_err)+'"}', status=500)
def put(self, request, zone_origin, record_name): """GET Method handler, used to update a record. This endpoint recieve the following JSON file: { "rclass" : "record_rclass", "ttl" : "record_ttl", "rtype" : "record_rtype", "rdata" : { "rdata_name1" : "data", ... }, } Note that all field is optional. You only need to use it if you want to update the value. This endpoint will return { "status" : "ok" } if updating a record is successfull and {"status" : "fail"} otherwise """ try: payload = json.loads(request.body.decode('utf-8')) rtype = payload.get("rtype") rclass = None rdata = None if not (zone_origin in FILE_LOCATION): raise ZoneError('Invalid Zone: ' + zone_origin) zone = DNSZone() zone.read_from_file(FILE_LOCATION[zone_origin]) record = zone.find_record(record_name, rclass, rtype, rdata) # delete old reverse record if (record.rtype == "A" or record.rtype == "MX"): reverse_record_delete(record.name, record.rdata.address, zone_origin) record.fromJSON(payload) backup_restore_file('backup','zone',zone_origin,'.bak') # create new reverse record if (record.rtype == "A" or record.rtype == "MX"): reverse_record_add(record.name, zone_origin, record.rdata.address, record.ttl) zone.write_to_file(FILE_LOCATION[zone_origin]) logger.info("Updated record: " + str(record) + "\nOn zone: " + zone_origin) restart_bind(find_server(zone_origin)) return HttpResponse('{"status" : "ok"}') except ValueError as v_err: logger.warning(v_err.args) logger.warning(traceback.format_exc(2) + "\n\n\n") return HttpResponse('{"status" : "Invalid JSON arguments"}', status=500) except ZoneError as z_err: logger.error(z_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(z_err.args[0])+'"}', status=500) except BindError as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") if b_err['file_type']: backup_restore_file('restore', b_err['file_type'], b_err['origin'], '.bak') return HttpResponse('{"status" : "'+str(b_err.args['msg'])+'"}', status=500) except Exception as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(b_err)+'"}', status=500)
def delete(self, request, zone_origin, record_name): """DELETW Method handler, used to delete a record. This endpoint recieve no JSON data. If there's any, it will be ignored. { "rclass" : "record_rclass", "rtype" : "record_rtype", "rdata" : { "rdata_name1" : "data", ... }, } This endpoint will return { "status" : "ok" } if deleting a record is successfull and {"status" : "failed"} otherwise @TODO: Handle kalo ga nemu """ # handle the post request try: if request.body.decode('utf-8'): payload = json.loads(request.body.decode('utf-8')) rclass = payload.get("rclass") rtype = payload.get("rtype") rdata = payload.get("rdata") else: rclass = rtype = rdata = None if not (zone_origin in FILE_LOCATION): raise ZoneError('Invalid Zone: ' + zone_origin) zone = DNSZone() zone.read_from_file(FILE_LOCATION[zone_origin]) deleted_record = zone.find_record(record_name, rclass, rtype, rdata) zone.delete_record(record_name, rclass, rtype, rdata) backup_restore_file('backup','zone',zone_origin,'.bak') if deleted_record.rtype == "A" or deleted_record.rtype == "MX": reverse_record_delete(deleted_record.name, deleted_record.rdata.address, zone_origin) zone.write_to_file(FILE_LOCATION[zone_origin]) logger.info("Deleted record: " + str(deleted_record) + "\nOn zone: " + zone_origin) restart_bind(find_server(zone_origin)) return HttpResponse('{"status" : "ok"}') except ValueError as v_err: logger.warning(v_err.args) logger.warning(traceback.format_exc(2) + "\n\n\n") return HttpResponse('{"status" : "Invalid JSON arguments"}', status=500) except ZoneError as z_err: logger.error(z_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(z_err.args[0])+'"}', status=500) except BindError as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") if b_err['file_type']: backup_restore_file('restore', b_err['file_type'], b_err['origin'], '.bak') return HttpResponse('{"status" : "'+str(b_err.args['msg'])+'"}', status=500) except Exception as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(b_err)+'"}', status=500)
def post(self, request, dns_server): """POST Method handler, used to create a new zone record. This endpoint recieve the following JSON file: { "directives": { "directive1": "value1", ... } "soa_record": { "authoritative_server": "", "admin_email": "", "serial_no": "", "slv_refresh_period": "", "slv_retry": "", "slv_expire": "", "max_time_cache": "" } "zone": { "zone ZONENAME": { "file": "ZONE_FILE_PATH", "type": "TYPE" ... } } } Note that rclass and TTL are optional. This endpoint will return { "status" : "ok" } if adding a new record is successfull and {"status" : "fail"} otherwise """ try: # Load input parameters body = json.loads(request.body.decode('utf-8')) body_zone = body['zone'] zone = str(body_zone.keys()[0]) if "master" in body_zone[zone]['type']: body_directives = body['directives'] body_soa = body['soa_record'] # add_absolute_path(body_zone) named_file = str(LOCAL_MNT_DIR[dns_server]) + DEFAULT_CONF_FILENAME logger.debug("Write named file to directory " + named_file) # Add zone to named config file named_dict, named_keys = iscpy.ParseISCString(open(named_file).read()) new_dict = iscpy.AddZone(body_zone, named_dict) iscpy.WriteToFile(new_dict, named_keys, named_file) # Make new zone file if "master" in body_zone[zone]['type']: soa = SOARecordData() soa.fromJSON(body_soa) soa_record = DNSResourceRecord("@", "", "", "SOA", soa) resourcerecord = [] resourcerecord.append(soa_record) ns_record = DNSResourceRecord("@", "", "", "NS", RecordData(body_soa['authoritative_server'])) resourcerecord.append(ns_record) new_zone = DNSZone(body_directives, resourcerecord) zone_file = body_zone[zone]['file'].split('"')[1] zone_file = ZONE_DIR[dns_server] + zone_file local_zone_file = zone_file.replace(REMOTE_MNT_DIR, LOCAL_MNT_DIR[dns_server], 1) logger.debug("Write zone file to directory " + local_zone_file) logger.debug("Zone to write: " + new_zone.toJSON()) new_zone.write_to_file(local_zone_file) restart_bind(dns_server) init_data() return HttpResponse('{ "status" : "ok" }') except ValueError as v_err: logger.warning(v_err.args) logger.warning(traceback.format_exc(2) + "\n\n\n") return HttpResponse('{"status" : "Invalid JSON arguments"}', status=500) except ZoneError as z_err: logger.error(z_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(z_err.args[0])+'"}', status=500) except BindError as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") if b_err.args[0]['file_type']: backup_restore_file('restore', b_err.args[0]['file_type'], b_err.args[0]['origin'], '.bak') return HttpResponse('{"status" : "'+str(b_err.args[0]['msg'])+'"}', status=500) except Exception as b_err: logger.error(b_err.args) logger.error(traceback.format_exc() + "\n\n\n") return HttpResponse('{"status" : "'+str(b_err)+'"}', status=500)