def add_default_soa_record(self, endpoint=None): """Returns None if already exists, DoesNotExist bubbles up when no default soa exists""" # sanity check if not self.domain_id: raise Exception( "Cannot add default records when domain_id is not set") # don't duplicate SOA record try: existing_soa = Record.get(Record.domain_id == self.domain_id, Record.type == RecordType().set("SOA")) return None except DoesNotExist: # create SOA record, let DoesNotExist bubble up default_soa = DefaultRecord.get( DefaultRecord.type == RecordType().set("SOA")) soa = Record() soa.domain_id = self.domain_id soa.host = default_soa.host.replace("DOMAIN", self.domain) soa.val = default_soa.val soa.ttl = default_soa.ttl soa.type = default_soa.type # replace uses of DOMAIN soa.save() if endpoint is not None: endpoint.dns_log(soa.domain_id, "added soa") return soa
def post(self): domain_id = request.form.get('domain_id') if domain_id is None: abort(400, message="domain_id parameter is required") domain_id = int(domain_id) # check if the domain exists try: self.get_domain(domain_id) except peewee.DoesNotExist: abort(404, message="domain_id does not exist: " + domain_id) # get domain and check authorization self.auth.account.load_domains() domain = self.get_write_domain(domain_id) record_type = request.form.get('record_type') try: readable_type = RecordType().set(record_type) except RecordTypeException: abort(400, message="Invalid record_type: " + str(record_type)) # If SOA, make sure a record doesn't yet exist if record_type == "SOA": try: ModelRecord.get( ModelRecord.type == RecordType().set(record_type), ModelRecord.domain_id == domain_id ) abort(400, message="SOA record already exists for this domain") except peewee.DoesNotExist: pass TypeModel = RecordType().get_class(RecordType().set(record_type))() self.request_form_to_type_model(request.form, TypeModel, domain) TypeModel.values["domain_id"] = domain.domain_id model = TypeModel.to_model() try: model.save() except RecordValueException as e: abort(400, message=e.message) self.dns_log( domain.domain_id, ( "added " + record_type + " with host " + model.host + " and value " + model.val ) ) return {'status': 'ok', 'record': model.to_recordtype().to_dict()}, 201
def test_set_success(self): record_type = RecordType() self.assertEquals(record_type.set('SOA'), 'S') self.assertEquals(record_type.set('NS'), 'N') self.assertEquals(record_type.set('A'), 'A') self.assertEquals(record_type.set('AAAA'), '3') self.assertEquals(record_type.set('AAAA+PTR'), '6') self.assertEquals(record_type.set('MX'), 'M') self.assertEquals(record_type.set('PTR'), 'P') self.assertEquals(record_type.set('TXT'), 'T') self.assertEquals(record_type.set('CNAME'), 'C') self.assertEquals(record_type.set('SRV'), 'V') self.assertEquals(record_type.set('SPF'), 'F')
def put(self, record_id): try: record = self.get_record(record_id) except peewee.DoesNotExist: abort(404, message="record does not exist") # get domain and check authorization self.auth.account.load_domains() domain = self.get_write_domain(record.domain_id) TypeModel = record.to_recordtype() self.request_form_to_type_model(request.form, TypeModel, domain) try: model = TypeModel.to_model() model.save() except RecordValueException as e: abort(400, message=str(e)) self.dns_log(domain.domain_id, ("updated record " + str(model.record_id) + " of type " + RecordType().get(model.type) + " with host " + model.host + " and value " + model.val)) return {'status': 'ok', 'record': model.to_recordtype().to_dict()}
def delete(self, record_id): try: record = self.get_record(record_id) except Exception: abort(404, message="record does not exist") TypeModel = record.to_recordtype() # load domain and check authorization domain = self.auth.account.get_domain_by_record_acl( record.domain_id, record.host, TypeModel.record_type) if domain is False: self.auth.account.load_domains() domain = self.get_delete_domain(record.domain_id) record.delete_instance() self.dns_log( domain.domain_id, ("deleted " + RecordType().get(record.type) + " with host " + record.host + " and value " + record.val)) # notify listeners of dns data change self.send_update_notification() return {'status': 'ok'}
def post(self): domain_id = request.form.get('domain_id') if domain_id is None: abort(400, message="domain_id parameter is required") domain_id = int(domain_id) # check if the domain exists try: domain = self.get_domain(domain_id) except peewee.DoesNotExist: abort(404, message="domain_id does not exist: " + str(domain_id)) record_type = request.form.get('record_type') try: readable_type = RecordType().set(record_type) except RecordTypeException: abort(400, message="Invalid record_type: " + str(record_type)) # If SOA, make sure a record doesn't yet exist if record_type == "SOA": try: ModelRecord.get( ModelRecord.type == RecordType().set(record_type), ModelRecord.domain_id == domain_id) abort(400, message="SOA record already exists for this domain") except peewee.DoesNotExist: pass TypeModel = RecordType().get_class(RecordType().set(record_type))() self.request_form_to_type_model(request.form, TypeModel, domain) TypeModel.values["domain_id"] = domain.domain_id model = TypeModel.to_model() # get domain and check authorization domain = self.auth.account.get_domain_by_record_acl( domain_id, model.host, record_type) if domain is False: self.auth.account.load_domains() domain = self.get_write_domain(domain_id) try: model.save() except RecordValueException as e: abort(400, message=e.message) self.dns_log(domain.domain_id, ("added " + record_type + " with host " + model.host + " and value " + model.val)) # notify listeners of dns data change self.send_update_notification() return {'status': 'ok', 'record': model.to_recordtype().to_dict()}, 201
def test_get_success(self): record_type = RecordType() self.assertEquals(record_type.get('S'), 'SOA') self.assertEquals(record_type.get('N'), 'NS') self.assertEquals(record_type.get('A'), 'A') self.assertEquals(record_type.get('3'), 'AAAA') self.assertEquals(record_type.get('6'), 'AAAA+PTR') self.assertEquals(record_type.get('M'), 'MX') self.assertEquals(record_type.get('P'), 'PTR') self.assertEquals(record_type.get('T'), 'TXT') self.assertEquals(record_type.get('C'), 'CNAME') self.assertEquals(record_type.get('V'), 'SRV') self.assertEquals(record_type.get('F'), 'SPF')
def post(self): # only open to senior_admin for now if self.auth.account.account_type != 'senior_admin': abort(403) record_type = request.form.get('record_type') try: record_type_in_db = RecordType().set(record_type) except RecordTypeException: abort(400, message="Invalid record_type: " + record_type) if record_type in ["AAAA+PTR", "PTR"]: abort( 400, message="Sorry, record_type " + record_type + " is not supported for default records" ) # If SOA, make sure a record doesn't yet exist if record_type == "SOA": try: ModelDefaultRecord.get( ModelDefaultRecord.type == record_type_in_db ) abort(400, message="A default SOA record already exists") except peewee.DoesNotExist: pass TypeModel = RecordType().get_class(RecordType().set(record_type))() self.request_form_to_type_model(request.form, TypeModel, None) model = TypeModel.to_model(default_record=True) model.default_type = "system" model.save() return { 'status': 'ok', 'default_record': model.to_recordtype().to_dict() }, 201
def put(self, record_id): try: record = self.get_record(record_id) except peewee.DoesNotExist: abort(404, message="record does not exist") TypeModel = record.to_recordtype() # get domain and check authorization domain = self.auth.account.get_domain_by_record_acl( record.domain_id, record.host, TypeModel.record_type ) if domain is False: self.auth.account.load_domains() domain = self.get_write_domain(record.domain_id) self.request_form_to_type_model(request.form, TypeModel, domain) try: model = TypeModel.to_model() # recheck auth in case host changed if record.host != model.host: domain = self.auth.account.get_domain_by_record_acl( record.domain_id, model.host, TypeModel.record_type ) if domain is False: self.auth.account.load_domains() domain = self.get_read_domain(record.domain_id) model.save() except RecordValueException as e: abort(400, message=str(e)) self.dns_log( domain.domain_id, ( "updated record " + str(model.record_id) + " of type " + RecordType().get(model.type) + " with host " + model.host + " and value " + model.val ) ) # notify listeners of dns data change self.send_update_notification() return {'status': 'ok', 'record': model.to_recordtype().to_dict()}
def post(self): # only open to senior_admin for now if self.auth.account.account_type != 'senior_admin': abort(403) record_type = request.form.get('record_type') try: record_type_in_db = RecordType().set(record_type) except RecordTypeException: abort(400, message="Invalid record_type: " + record_type) if record_type in ["AAAA+PTR", "PTR"]: abort(400, message="Sorry, record_type " + record_type + " is not supported for default records") # If SOA, make sure a record doesn't yet exist if record_type == "SOA": try: ModelDefaultRecord.get( ModelDefaultRecord.type == record_type_in_db) abort(400, message="A default SOA record already exists") except peewee.DoesNotExist: pass TypeModel = RecordType().get_class(RecordType().set(record_type))() self.request_form_to_type_model(request.form, TypeModel, None) model = TypeModel.to_model(default_record=True) model.default_type = "system" model.save() return { 'status': 'ok', 'default_record': model.to_recordtype().to_dict() }, 201
def add_default_records(self, endpoint=None, skipSoa=False): # sanity check if not self.domain_id: raise Exception( "Cannot add default records when domain_id is not set") if not skipSoa: try: soa = self.add_default_soa_record(endpoint) except DoesNotExist: # no default SOA record set! pass # create all other records default_records = DefaultRecord.select().where( DefaultRecord.type != RecordType().set("SOA")) for record in default_records: new = Record() new.domain_id = self.domain_id new.distance = record.distance new.host = record.host.replace("DOMAIN", self.domain) new.val = record.val.replace("DOMAIN", self.domain) new.distance = record.distance new.port = record.port new.ttl = record.ttl new.type = record.type new.weight = record.weight new.save() if endpoint is not None: endpoint.dns_log( new.domain_id, ("added " + RecordType().get(new.type) + " with host " + new.host + " and value " + new.val))
def delete(self, record_id): try: record = self.get_record(record_id) except: abort(404, message="record does not exist") # check authorization self.auth.account.load_domains() domain = self.get_delete_domain(record.domain_id) record.delete_instance() self.dns_log( domain.domain_id, ("deleted " + RecordType().get(record.type) + " with host " + record.host + " and value " + record.val)) return {'status': 'ok'}
def count_records(self, filter_record_type, search_name=None, search_value=None): if not self.domain_id: raise Exception("Cannot get records, domain_id is not set") query = Record.select(Record).where(Record.domain_id == self.domain_id) if filter_record_type is not None: query = query.where( Record.type == RecordType().set(filter_record_type)) if search_name is not None: query = query.where((Record.host**('%' + search_name + '%'))) if search_value is not None: query = query.where((Record.val**('%' + search_value + '%'))) return query.count()
def get(self): # only open to senior_admin for now if self.auth.account.account_type != 'senior_admin': abort(403) record_collection = self.get_default_records() filter_record_type = request.args.get('filter_record_type') if (filter_record_type is not None): try: query_record_type = RecordType().set(filter_record_type) record_collection = record_collection.where( ModelDefaultRecord.type == query_record_type) except RecordTypeException: abort(400, message="Invalid filter_record_type: " + filter_record_type) records = [] for record in record_collection: recordtype = record.to_recordtype() records.append(recordtype.to_dict()) return {'status': 'ok', 'default_records': records}
def test_get_failure(self): record_type = RecordType() with self.assertRaises(RecordTypeException) as cm: record_type.get('nonexistant') self.assertEquals('Invalid record type', str(cm.exception))
def get(self): domain_id = request.args.get('domain_id') if domain_id is None: abort(400, message="domain_id parameter is required") domain_id = int(domain_id) # check if the domain exists try: domain = self.get_domain(domain_id) except peewee.DoesNotExist: abort(404, message="domain_id does not exist: " + domain_id) # get domain and check authorization self.auth.account.load_domains() in_acl = self.auth.account.in_global_acl_emails( self.auth.account.email) if not in_acl: domain = self.get_read_domain(domain_id) record_collection = self.paginate_query(domain.get_records(), request.args) record_collection = self.sort_query(record_collection, request.args) # Optional search of record name, value, or both search_name = request.args.get('search_name') if search_name is not None: search_name = search_name.replace('*', '%') record_collection = record_collection.where( (ModelRecord.host**('%' + search_name + '%'))) search_value = request.args.get('search_value') if search_value is not None: search_value = search_value.replace('*', '%') record_collection = record_collection.where( (ModelRecord.val**('%' + search_value + '%'))) filter_record_type = request.args.get('filter_record_type') if (filter_record_type is not None): try: query_record_type = RecordType().set(filter_record_type) record_collection = record_collection.where( ModelRecord.type == query_record_type) except RecordTypeException: abort(400, message="Invalid filter_record_type: " + filter_record_type) total_records = domain.count_records(filter_record_type, search_name, search_value) records = [] for record in record_collection: recordtype = record.to_recordtype() records.append(recordtype.to_dict()) clean_domain = domain.to_clean_dict() if request.args.get('include_permissions', None): if in_acl: clean_domain["permissions"] = { "can_read": True, "can_write": True, "can_delete": True } else: clean_domain["permissions"] = self.get_permissions( domain.domain_id) return { 'status': 'ok', 'total_records': total_records, 'records': records, 'domain': clean_domain }
def get(self, format): if format != 'tinydns': abort(400, message="invalid format: " + format) records = self.get_records() domains = {} for record in records: if record.domain_id.domain not in domains: domains[record.domain_id.domain] = [] domains[record.domain_id.domain].append(record) organized = [] for key, val in sorted(domains.items()): organized.append({'domain_name': key, 'records': val}) locations = self.get_locations() prefixes = self.get_prefixes() locationdata = "# locations\n" # need to build this manually since peewee join results are limiting for location in locations: temp_list = [] for prefix in prefixes: if prefix.location_id != location.location_id: continue else: if prefix.prefix_type == "ipv4": temp_list.append(prefix.prefix) else: temp_list.append("s" + str(prefix.prefix).replace(":", "")) if len(temp_list) == 0: locationdata += "%" + location.location + "\n" else: for i in temp_list: locationdata += "%" + location.location + ":" + i + "\n" datafile = locationdata + "\n" tinydns = ExportTinydnsData() datafile += tinydns.export_domains(organized, locations) generation_record_host = config.get('monitoring', 'vegadns_generation_txt_record') if generation_record_host \ and Validate().record_hostname(generation_record_host): timestamp = self.get_latest_log_timestamp() md5 = hashlib.md5(datafile + "\n").hexdigest() model = ModelRecord() model.type = RecordType().set('TXT') model.host = generation_record_host model.val = str(timestamp) + "-" + md5 model.ttl = 3600 generation_record_line = tinydns.data_line_from_model(model) datafile += "\n\n# VegaDNS Generation TXT Record\n" datafile += generation_record_line.rstrip("\n") response = make_response(datafile) response.headers['content-type'] = 'text/plain' return response
def test_set_failure(self): record_type = RecordType() with self.assertRaises(RecordTypeException) as cm: record_type.get('CNAME') self.assertEquals('Invalid record type', cm.exception.message)