Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    def test_hostname_in_domain(self):
        record = Record()

        domain = "foobar.com"
        bad = "wwwfoobar.com"
        good = "www.foobar.com"

        self.assertTrue(record.hostname_in_domain(domain, domain))
        self.assertFalse(record.hostname_in_domain(bad, domain))
        self.assertTrue(record.hostname_in_domain(good, domain))
Example #5
0
    def test_hostname_in_domain(self):
        record = Record()

        domain = "foobar.com"
        bad = "wwwfoobar.com"
        good = "www.foobar.com"

        self.assertTrue(record.hostname_in_domain(domain, domain))
        self.assertFalse(record.hostname_in_domain(bad, domain))
        self.assertTrue(record.hostname_in_domain(good, domain))
Example #6
0
    def test_spf_record(self):
        model = Record()

        model.type = 'F'
        model.host = 'example.com'
        model.val = 'v=spf1 mx -all'
        model.ttl = '3600'

        self.assertEquals(
            self.export.data_line_from_model(model),
            ":example.com:99:" r"\016" "v=spf1 mx -all:3600\n"
        )
Example #7
0
    def test_ptr_record(self):
        model = Record()

        model.type = 'T'
        model.host = 'vegadns.ubuntu'
        model.val = 'v=spf1 mx a ip4:1.2.3.0/24'
        model.ttl = '3600'

        self.assertEquals(
            self.export.data_line_from_model(model),
            "'vegadns.ubuntu:v=spf1 mx a ip4" r"\072" + "1.2.3.0/24:3600\n"
        )
Example #8
0
    def test_mx_record(self):
        model = Record()

        model.type = 'P'
        model.host = '4.3.2.1.in-addr.arpa'
        model.val = 'www.vegadns.ubuntu'
        model.ttl = '3600'

        self.assertEquals(
            self.export.data_line_from_model(model),
            '^4.3.2.1.in-addr.arpa:www.vegadns.ubuntu:3600\n'
        )
Example #9
0
    def test_a_record(self):
        model = Record()

        model.type = 'A'
        model.host = 'foo.vegadns.ubuntu'
        model.val = '1.2.3.4'
        model.ttl = '3600'

        self.assertEquals(
            self.export.data_line_from_model(model),
            '+foo.vegadns.ubuntu:1.2.3.4:3600\n'
        )
Example #10
0
    def test_ns_record(self):
        model = Record()

        model.type = 'N'
        model.host = 'example.com'
        model.val = 'ns1.example.com'
        model.ttl = 3600

        expected = "&example.com::ns1.example.com:3600\n"

        self.assertEquals(
            self.export.data_line_from_model(model),
            expected
        )
Example #11
0
 def get_records(self):
     return (ModelRecord.select(ModelDomain, ModelRecord).join(
         ModelDomain,
         on=ModelDomain.domain_id == ModelRecord.domain_id).where(
             ModelDomain.status == 'active').order_by(
                 ModelDomain.domain.asc(), ModelRecord.type.asc(),
                 ModelRecord.host.asc(), ModelRecord.val.asc()))
Example #12
0
 def check_domain_suffix(self, domain):
     # make sure hostname ends in domain name
     name = request.form.get("name")
     if not name or not ModelRecord.hostname_in_domain(name, domain):
         abort(
             400,
             message="Name does not end in domain name: " + str(name)
         )
Example #13
0
 def check_domain_suffix(self, domain):
     # make sure hostname ends in domain name
     name = request.form.get("name")
     if not name or not ModelRecord.hostname_in_domain(name, domain):
         abort(
             400,
             message="Name does not end in domain name: " + str(name)
         )
Example #14
0
    def test_aaaa_record(self):
        model = Record()

        model.type = '3'
        model.host = 'example.com'
        model.val = '0000:0000:0000:0000:0000:ffff:169.254.123.231'
        model.ttl = '3600'

        expected = (
            ":example.com:28:"
            r"\000\000\000\000\000\000\000\000\000\000\377\377\251\376\173\347"
            ":3600\n"
        )

        self.assertEquals(
            self.export.data_line_from_model(model),
            expected
        )
Example #15
0
    def test_cname_validation_fail(self):
        record = Record()
        record.type = 'C'
        record.domain_id = 1
        record.host = 'foobar.com'
        record.val = 'www.example.com  '

        with self.assertRaises(RecordValueException) as cm:
            record.validate()
        self.assertEquals('Invalid cname value: www.example.com  ',
                          cm.exception.message)
Example #16
0
    def test_cname_validation_success(self):
        record = Record()
        record.type = 'C'
        record.domain_id = 1
        record.host = 'foobar.com'
        record.val = 'www.example.com'

        self.assertIsNone(record.validate())
    def test_srv_record(self):
        model = Record()

        model.type = 'V'
        model.host = '_xmpp-client._tcp.example.com.'
        model.val = 'xmpp.example.com'
        model.ttl = '3600'
        model.distance = 0
        model.weight = 10
        model.port = 5222

        expected = (":_xmpp-client._tcp.example.com."
                    ":33"
                    r":\000\000\000\012\024\146\004xmpp\007example\003com\000"
                    ":3600\n")

        self.assertEquals(self.export.data_line_from_model(model), expected)
Example #18
0
    def test_soa_record(self):
        domain = Domain()
        domain.domain = 'example.com'
        model = Record()

        # joined domain on domain_id
        model.domain_id = domain
        model.type = 'S'
        model.host = 'hostmaster.example.com:ns1.example.com'
        model.val = '16384:2048:1048576:2560:'
        model.ttl = '86400'

        expected = (
            "Zexample.com"
            ":ns1.example.com"
            ":hostmaster.example.com"
            ":"
            ":16384"
            ":2048"
            ":1048576"
            ":2560"
            ":86400\n"
        )

        self.assertEquals(
            self.export.data_line_from_model(model),
            expected
        )
    def test_mx_record(self):
        model = Record()

        model.type = 'M'
        model.host = 'vegadns.ubuntu'
        model.val = 'mail.vegadns.ubuntu'
        model.distance = 10
        model.ttl = '3600'

        self.assertEquals(self.export.data_line_from_model(model),
                          '@vegadns.ubuntu::mail.vegadns.ubuntu:10:3600\n')
Example #20
0
    def test_cname_validation_success(self):
        record = Record()
        record.type = 'C'
        record.domain_id = 1
        record.host = 'foobar.com'
        record.val = 'www.example.com'

        self.assertIsNone(record.validate())
Example #21
0
    def test_cname_validation_fail(self):
        record = Record()
        record.type = 'C'
        record.domain_id = 1
        record.host = 'foobar.com'
        record.val = 'www.example.com  '

        with self.assertRaises(RecordValueException) as cm:
            record.validate()
        self.assertEquals(
            'Invalid cname value: www.example.com  ',
            cm.exception.message
        )
Example #22
0
    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()
Example #23
0
 def get_records(self):
     return (
         ModelRecord.select(ModelDomain, ModelRecord)
         .join(
             ModelDomain,
             on=ModelDomain.domain_id == ModelRecord.domain_id
         )
         .where(ModelDomain.status == 'active')
         .order_by(
             ModelDomain.domain.asc(),
             ModelRecord.type.asc(),
             ModelRecord.host.asc(),
             ModelRecord.val.asc()
         )
     )
    def test_a_record(self):
        model = Record()

        model.type = 'A'
        model.host = 'foo.vegadns.ubuntu'
        model.val = '1.2.3.4'
        model.ttl = '3600'

        self.assertEquals(self.export.data_line_from_model(model),
                          '+foo.vegadns.ubuntu:1.2.3.4:3600\n')
    def test_mx_record(self):
        model = Record()

        model.type = 'P'
        model.host = '4.3.2.1.in-addr.arpa'
        model.val = 'www.vegadns.ubuntu'
        model.ttl = '3600'

        self.assertEquals(self.export.data_line_from_model(model),
                          '^4.3.2.1.in-addr.arpa:www.vegadns.ubuntu:3600\n')
    def test_ns_record(self):
        model = Record()

        model.type = 'N'
        model.host = 'example.com'
        model.val = 'ns1.example.com'
        model.ttl = 3600

        expected = "&example.com::ns1.example.com:3600\n"

        self.assertEquals(self.export.data_line_from_model(model), expected)
    def test_ptr_record(self):
        model = Record()

        model.type = 'T'
        model.host = 'vegadns.ubuntu'
        model.val = 'v=spf1 mx a ip4:1.2.3.0/24'
        model.ttl = '3600'

        self.assertEquals(
            self.export.data_line_from_model(model),
            "'vegadns.ubuntu:v=spf1 mx a ip4"
            r"\072" + "1.2.3.0/24:3600\n")
    def test_spf_record(self):
        model = Record()

        model.type = 'F'
        model.host = 'example.com'
        model.val = 'v=spf1 mx -all'
        model.ttl = '3600'

        self.assertEquals(self.export.data_line_from_model(model),
                          ":example.com:99:"
                          r"\016"
                          "v=spf1 mx -all:3600\n")
Example #29
0
    def delete(self, location_id):
        if self.auth.account.account_type != "senior_admin":
            abort(403, message="Insufficient privileges to delete a location")

        try:
            locationdb = ModelLocation.get(
                ModelLocation.location_id == location_id)
        except peewee.DoesNotExist:
            abort(404, message="location not found")

        locationdb.delete_prefixes()
        # update records that have this id to null (public)
        query = ModelRecord.update(location_id=None).where(
            ModelRecord.location_id == location_id)
        query.execute()
        locationdb.delete_instance()

        return {'status': 'ok'}
Example #30
0
    def test_mx_record(self):
        model = Record()

        model.type = 'M'
        model.host = 'vegadns.ubuntu'
        model.val = 'mail.vegadns.ubuntu'
        model.distance = 10
        model.ttl = '3600'

        self.assertEquals(
            self.export.data_line_from_model(model),
            '@vegadns.ubuntu::mail.vegadns.ubuntu:10:3600\n'
        )
Example #31
0
    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 test_aaaaptr_record(self):
        model = Record()

        model.type = '3'
        model.host = 'example.com'
        model.val = '0000:0000:0000:0000:0000:ffff:169.254.123.231'
        model.ttl = '3600'

        expected = (
            ":example.com:28:"
            r"\000\000\000\000\000\000\000\000\000\000\377\377\251\376\173\347"
            ":3600\n")

        self.assertEquals(self.export.data_line_from_model(model), expected)
Example #33
0
    def test_srv_record(self):
        model = Record()

        model.type = 'V'
        model.host = '_xmpp-client._tcp.example.com.'
        model.val = 'xmpp.example.com'
        model.ttl = '3600'
        model.distance = 0
        model.weight = 10
        model.port = 5222

        expected = (
            ":_xmpp-client._tcp.example.com."
            ":33"
            r":\000\000\000\012\024\146\004xmpp\007example\003com\000"
            ":3600\n"
        )

        self.assertEquals(
            self.export.data_line_from_model(model),
            expected
        )
Example #34
0
    def delete(self, location_id):
        if self.auth.account.account_type != "senior_admin":
            abort(403, message="Insufficient privileges to delete a location")

        try:
            locationdb = ModelLocation.get(
                ModelLocation.location_id == location_id
            )
        except peewee.DoesNotExist:
            abort(404, message="location not found")

        locationdb.delete_prefixes()
        # update records that have this id to null (public)
        query = ModelRecord.update(location_id=None).where(
            ModelRecord.location_id == location_id
        )
        query.execute()
        locationdb.delete_instance()

        return {'status': 'ok'}
    def test_soa_record(self):
        domain = Domain()
        domain.domain = 'example.com'
        model = Record()

        # joined domain on domain_id
        model.domain_id = domain
        model.type = 'S'
        model.host = 'hostmaster.example.com:ns1.example.com'
        model.val = '16384:2048:1048576:2560:'
        model.ttl = '86400'

        expected = ("Zexample.com"
                    ":ns1.example.com"
                    ":hostmaster.example.com"
                    ":"
                    ":16384"
                    ":2048"
                    ":1048576"
                    ":2560"
                    ":86400\n")

        self.assertEquals(self.export.data_line_from_model(model), expected)
Example #36
0
    def get_records(self):
        if not self.domain_id:
            raise Exception("Cannot get records, domain_id is not set")

        return Record.select(Record).where(Record.domain_id == self.domain_id)
Example #37
0
 def get_record(self, record_id):
     return ModelRecord.get(ModelRecord.record_id == record_id)
Example #38
0
    def get_records(self):
        if not self.domain_id:
            raise Exception("Cannot get records, domain_id is not set")

        return Record.select(Record).where(Record.domain_id == self.domain_id)
Example #39
0
    def add_default_records(self, endpoint=None):
        # 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"))
        except DoesNotExist:
            # create SOA record
            try:
                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")
            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),
                )
Example #40
0
    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))
Example #41
0
    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
Example #42
0
    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