示例#1
0
文件: rules.py 项目: w796933/RESTKnot
def is_allowed_cname(zone_id, type_id, owner, rdata, ttl_id):
    """Check is given CNAME record is allowed.

    1. Check for duplicate record
    2. Check for the same owner
    3. Check for the same A owner
    """
    #  duplicate record NOT allowed
    is_allowed(zone_id, type_id, owner, rdata, ttl_id)

    # 1. same owner NOT allowed
    query = '"type_id"=%(type_id)s AND "owner"=%(owner)s'
    value = {"zone_id": zone_id, "type_id": type_id, "owner": owner}
    rules = rules_model.Rules(query, value)

    is_unique = rules.is_unique()
    if not is_unique:
        raise ValueError("A CNAME record already exist with that owner")

    # 2. owner CAN'T coexist with the same A owner
    a_type_id = type_model.get_typeid_by_rtype("A")
    query = '"type_id" IN (%(type1)s,%(type2)s) AND "owner"=%(owner)s'
    value = {"zone_id": zone_id, "type1": type_id, "type2": a_type_id, "owner": owner}
    rules = rules_model.Rules(query, value)

    is_coexist = rules.is_coexist()
    if is_coexist:
        raise ValueError("An A record already exist with that owner")
示例#2
0
文件: rules.py 项目: azzamsa/RESTKnot
def is_allowed_cname_edit(zone_id,
                          type_id,
                          owner,
                          rdata,
                          ttl_id,
                          record_id=None):
    """Check is given CNAME record is allowed.

    This function separated from `cname_add` because it needs to exclude its id
    while searching for other records.
    """
    #  duplicate record NOT allowed
    is_allowed(zone_id, type_id, owner, rdata, ttl_id)

    # 1. same owner NOT allowed
    query = '"type_id"=%(type_id)s AND "owner"=%(owner)s AND "id"<>%(record_id)s'
    value = {
        "zone_id": zone_id,
        "type_id": type_id,
        "owner": owner,
        "record_id": record_id,
    }
    rules = rules_model.Rules(query, value)

    is_unique = rules.is_unique()
    if not is_unique:
        raise ValueError("A CNAME record already exist with that owner")

    # 2. owner CAN'T coexist with the same A owner
    a_type_id = type_model.get_typeid_by_rtype("A")
    query = '"type_id" IN (%(type1)s,%(type2)s) AND "owner"=%(owner)s AND "id"<>%(record_id)s'
    value = {
        "zone_id": zone_id,
        "type1": type_id,
        "type2": a_type_id,
        "owner": owner,
        "record_id": record_id,
    }
    rules = rules_model.Rules(query, value)

    is_coexist = rules.is_coexist()
    if is_coexist:
        raise ValueError("An A record already exist with that owner")

    # 3. owner can't be root
    zone = zone_model.get_zone(zone_id)
    if owner == f"{zone}." or owner == "@":
        raise ValueError("A CNAME owner can't be root")
示例#3
0
文件: rules.py 项目: w796933/RESTKnot
def is_allowed_a(zone_id, type_id, owner, rdata, ttl_id, record_id=None):
    """Check is given A record is allowed.

    1. Check for duplicate record
    2. Check for the same CNAME owner
    """
    #  duplicate record NOT allowed
    is_allowed(zone_id, type_id, owner, rdata, ttl_id)

    # 2. owner CAN'T coexist with the same CNAME owner
    cname_type_id = type_model.get_typeid_by_rtype("CNAME")
    query = '"type_id"=%(type_id)s AND "owner"=%(owner)s'
    value = {"zone_id": zone_id, "type_id": cname_type_id, "owner": owner}
    rules = rules_model.Rules(query, value)

    is_coexist = rules.is_coexist()
    if is_coexist:
        raise ValueError("A CNAME record already exist with that owner")
示例#4
0
    def post(self):
        """Add new record.

        note:
        Adding any record with other record is allowed. IETF best practice
        is not handled automatically.  Knot didn't handle this too, and let the
        user know the standards themselves.
        See https://tools.ietf.org/html/rfc1912
        """
        parser = reqparse.RequestParser()
        parser.add_argument("zone", type=str, required=True)
        parser.add_argument("owner", type=str, required=True)
        parser.add_argument("rtype", type=str, required=True)
        parser.add_argument("rdata", type=str, required=True)
        parser.add_argument("ttl", type=str, required=True)
        args = parser.parse_args()
        owner = args["owner"].lower()
        rtype = args["rtype"].lower()
        rdata = args["rdata"]
        zone = args["zone"]
        ttl = args["ttl"]

        try:
            ttl_id = ttl_model.get_ttlid_by_ttl(ttl)

            type_id = type_model.get_typeid_by_rtype(rtype)
            zone_id = zone_model.get_zone_id(zone)
        except Exception as e:
            return response(404, message=f"{e}")

        try:
            rules.check_add(rtype, zone_id, type_id, owner, rdata, ttl_id)
        except Exception as e:
            return response(409, message=f"{e}")

        try:
            # rtype no need to be validated & no need to check its length
            # `get_typeid` will raise error for non existing rtype
            validator.validate(rtype, rdata)
            validator.validate("owner", owner)
        except Exception as e:
            return response(422, message=f"{e}")

        try:
            serial_resource = get_serial_resource(zone)
            check_serial_limit(serial_resource)
        except Exception as e:
            return response(429, message=f"{e}")

        try:
            data = {
                "owner": owner,
                "zone_id": zone_id,
                "type_id": type_id,
                "ttl_id": ttl_id,
            }
            record_id = model.insert(table="record", data=data)

            content_data = {"rdata": rdata, "record_id": record_id}
            model.insert(table="rdata", data=content_data)

            command.set_zone(record_id, "zone-set")

            # increment serial after adding new record
            rtype = type_model.get_type_by_recordid(record_id)
            if rtype != "SOA":
                update_serial(serial_resource)

            record = model.get_one(table="record", field="id", value=record_id)
            data = record_model.get_other_data(record)
            return response(201, data=data)
        except Exception as e:
            current_app.logger.error(f"{e}")
            return response(500)
示例#5
0
    def put(self, record_id):
        parser = reqparse.RequestParser()
        parser.add_argument("zone", type=str, required=True)
        parser.add_argument("owner", type=str, required=True)
        parser.add_argument("rtype", type=str, required=True)
        parser.add_argument("rdata", type=str, required=True)
        parser.add_argument("ttl", type=str, required=True)
        args = parser.parse_args()
        owner = args["owner"].lower()
        rtype = args["rtype"].lower()
        rdata = args["rdata"]
        zone = args["zone"]
        ttl = args["ttl"]

        try:
            ttl_id = ttl_model.get_ttlid_by_ttl(ttl)
            record_model.is_exists(record_id)

            type_id = type_model.get_typeid_by_rtype(rtype)
            zone_id = zone_model.get_zone_id(zone)
        except Exception as e:
            return response(404, message=f"{e}")

        try:
            rules.check_edit(rtype, zone_id, type_id, owner, rdata, ttl_id, record_id)
        except Exception as e:
            return response(409, message=f"{e}")

        try:
            validator.validate(rtype, rdata)
            validator.validate("owner", owner)
        except Exception as e:
            return response(422, message=f"{e}")

        try:
            serial_resource = get_serial_resource(zone)
            check_serial_limit(serial_resource)
        except Exception as e:
            return response(429, message=f"{e}")

        try:
            data = {
                "where": {"id": record_id},
                "data": {
                    "owner": owner,
                    "zone_id": zone_id,
                    "type_id": type_id,
                    "ttl_id": ttl_id,
                },
            }
            content_data = {
                "where": {"record_id": record_id},
                "data": {"rdata": rdata, "record_id": record_id},
            }

            command.set_zone(record_id, "zone-unset")

            model.update("rdata", data=content_data)
            model.update("record", data=data)

            command.set_zone(record_id, "zone-set")

            # increment serial after adding new record
            rtype = type_model.get_type_by_recordid(record_id)
            if rtype != "SOA":
                update_serial(serial_resource, "02")

            record = model.get_one(table="record", field="id", value=record_id)
            data_ = record_model.get_other_data(record)
            return response(200, data=data_)
        except Exception as e:
            current_app.logger.error(f"{e}")
            return response(500)