def test_is_literal(): assert is_literal(True) is True assert is_literal(False) is True assert is_literal(A) is True assert is_literal(~A) is True assert is_literal(Or(A, B)) is False assert is_literal(Q.zero(A)) is True assert is_literal(Not(Q.zero(A))) is True assert is_literal(Or(A, B)) is False assert is_literal(And(Q.zero(A), Q.zero(B))) is False
def test_is_literal(): assert is_literal(True) is True assert is_literal(False) is True assert is_literal(A) is True assert is_literal(~A) is True assert is_literal(Or(A, B)) is False assert is_literal(Q.zero(A)) is True assert is_literal(Not(Q.zero(A))) is True assert is_literal(Or(A, B)) is False assert is_literal(And(Q.zero(A), Q.zero(B))) is False
def convert_disjunction_try_split(self, expr): try: return self.convert_disjunction(expr) except CannotRepresentRule: access_rules = [self.convert_literal(e) if boolalg.is_literal(e) else self.convert_conjunction(e) for e in expr.args] access_rules_flat = [r for rules in access_rules for r in rules] return access_rules_flat
def convert_disjunction_try_split(self, expr): try: return self.convert_disjunction(expr) except CannotRepresentRule: access_rules = [ self.convert_literal(e) if boolalg.is_literal(e) else self.convert_conjunction(e) for e in expr.args ] access_rules_flat = [r for rules in access_rules for r in rules] return access_rules_flat
def convert_conjunction(self, expr): group_ids = None invert_group = False dateranges = None invert_date = False subnets = None invert_subnet = False if expr.is_Not: expr = ~expr invert = True else: invert = False for arg in expr.args: if not boolalg.is_literal(arg): raise CannotRepresentRule(expr, "conjunction can only contain literals") acl_cond, invert = self.get_acl_cond_for_literal(arg) if isinstance(acl_cond, ACLGroupCondition): if group_ids: raise CannotRepresentRule(expr, "conjunction can only contain one group / user rule") group_ids = [self.get_group_id_from_cond(acl_cond)] invert_group = invert elif isinstance(acl_cond, ACLUserCondition): if group_ids: raise CannotRepresentRule(expr, "conjunction can only contain one group / user rule") group_ids = [self.get_private_user_group_id_from_cond(acl_cond)] invert_group = invert elif isinstance(acl_cond, (ACLDateBeforeClause, ACLDateAfterClause)): if dateranges: raise CannotRepresentRule(expr, "conjunction can only contain one date rule") dateranges = [make_open_daterange_from_rule(acl_cond)] invert_date = invert elif isinstance(acl_cond, ACLIPCondition): if subnets and not invert: raise CannotRepresentRule(expr, "conjunction can only contain one ip / iplist rule") subnets = [make_ipnetwork_from_rule(acl_cond)] invert_subnet = invert elif isinstance(acl_cond, ACLIPListCondition): if subnets and not invert: raise CannotRepresentRule(expr, "conjunction can only contain one ip / iplist rule") subnets = get_iplist_from_cond(acl_cond) invert_subnet = invert return ((AccessRule(group_ids=group_ids, subnets=subnets, dateranges=dateranges, invert_date=invert_date, invert_subnet=invert_subnet, invert_group=invert_group), invert), )
def convert_symbolic_rule(self, expr): # cached value? boolalg.true and boolalg.false are always returned from here if expr in self.symbolic_rule_to_access_rules: logg.info("convert: known rule: %s", expr) return self.symbolic_rule_to_access_rules[expr] elif boolalg.is_literal(expr): return self.convert_literal(expr) elif expr.func is And: return self.convert_conjunction_try_flip(expr) elif expr.func is Or: return self.convert_disjunction_try_split(expr) else: raise CannotRepresentRule(expr, "unknown")
def convert_symbolic_rule(self, expr): # cached value? boolalg.true and boolalg.false are always returned from here if expr in self.symbolic_rule_to_access_rules: logg.info("convert: known rule: %s", expr) return self.symbolic_rule_to_access_rules[expr] elif boolalg.is_literal(expr): return self.convert_literal(expr) elif expr.func is And: return self.convert_conjunction_try_flip(expr) elif expr.func is Or: return self.convert_disjunction_try_split(expr) else: raise CannotRepresentRule(expr, "unknown")
def convert_disjunction(self, expr): access_rules = [] group_ids = set() subnets = set() dateranges = set() invert_group = False invert_subnet = False invert_date = False def check_inversion(invert_flag, inversion_state, already_found): if not invert_flag and inversion_state: raise CannotRepresentRule(expr) # only one negated element allowed if already_found and (invert_flag or inversion_state): raise CannotRepresentRule(expr, "negated subrules can only contain a single element") return invert_flag for arg in expr.args: if arg.func is And: access_rules.extend(self.convert_conjunction_try_flip(arg)) else: if not boolalg.is_literal(arg): raise CannotRepresentRule(expr, "illegal nesting in disjunction") acl_cond, invert = self.get_acl_cond_for_literal(arg) if isinstance(acl_cond, ACLGroupCondition): invert_group = check_inversion(invert, invert_group, group_ids) group_id = self.get_group_id_from_cond(acl_cond) group_ids.add(group_id) if isinstance(acl_cond, ACLUserCondition): invert_group = check_inversion(invert, invert_group, group_ids) group_id = self.get_private_user_group_id_from_cond(acl_cond) group_ids.add(group_id) elif isinstance(acl_cond, ACLIPCondition): invert_subnet = check_inversion(invert, invert_subnet, subnets) subnet = make_ipnetwork_from_rule(acl_cond) subnets.add(subnet) elif isinstance(acl_cond, ACLIPListCondition): invert_subnet = check_inversion(invert, invert_subnet, subnets) rule_subnets = get_iplist_from_cond(acl_cond) subnets.update(rule_subnets) elif isinstance(acl_cond, (ACLDateAfterClause, ACLDateBeforeClause)): invert_date = check_inversion(invert, invert_date, dateranges) daterange = make_open_daterange_from_rule(acl_cond) dateranges.add(daterange) # some after conversion check for disjunctions that cannot be represented properly if (group_ids and (subnets or dateranges) or subnets and (group_ids or dateranges) or dateranges and (group_ids or subnets)): raise CannotRepresentRule(expr) access_rules.append((AccessRule( group_ids=group_ids or None, dateranges=dateranges or None, subnets=subnets or None, invert_group=invert_group, invert_subnet=invert_subnet, invert_date=invert_date), False)) return tuple(access_rules)
def convert_disjunction(self, expr): access_rules = [] group_ids = set() subnets = set() dateranges = set() invert_group = False invert_subnet = False invert_date = False def check_inversion(invert_flag, inversion_state, already_found): if not invert_flag and inversion_state: raise CannotRepresentRule(expr) # only one negated element allowed if already_found and (invert_flag or inversion_state): raise CannotRepresentRule( expr, "negated subrules can only contain a single element") return invert_flag for arg in expr.args: if arg.func is And: access_rules.extend(self.convert_conjunction_try_flip(arg)) else: if not boolalg.is_literal(arg): raise CannotRepresentRule( expr, "illegal nesting in disjunction") acl_cond, invert = self.get_acl_cond_for_literal(arg) if isinstance(acl_cond, ACLGroupCondition): invert_group = check_inversion(invert, invert_group, group_ids) group_id = self.get_group_id_from_cond(acl_cond) group_ids.add(group_id) if isinstance(acl_cond, ACLUserCondition): invert_group = check_inversion(invert, invert_group, group_ids) group_id = self.get_private_user_group_id_from_cond( acl_cond) group_ids.add(group_id) elif isinstance(acl_cond, ACLIPCondition): invert_subnet = check_inversion(invert, invert_subnet, subnets) subnet = make_ipnetwork_from_rule(acl_cond) subnets.add(subnet) elif isinstance(acl_cond, ACLIPListCondition): invert_subnet = check_inversion(invert, invert_subnet, subnets) rule_subnets = get_iplist_from_cond(acl_cond) subnets.update(rule_subnets) elif isinstance(acl_cond, (ACLDateAfterClause, ACLDateBeforeClause)): invert_date = check_inversion(invert, invert_date, dateranges) daterange = make_open_daterange_from_rule(acl_cond) dateranges.add(daterange) # some after conversion check for disjunctions that cannot be represented properly if (group_ids and (subnets or dateranges) or subnets and (group_ids or dateranges) or dateranges and (group_ids or subnets)): raise CannotRepresentRule(expr) access_rules.append((AccessRule(group_ids=group_ids or None, dateranges=dateranges or None, subnets=subnets or None, invert_group=invert_group, invert_subnet=invert_subnet, invert_date=invert_date), False)) return tuple(access_rules)
def convert_conjunction(self, expr): group_ids = None invert_group = False dateranges = None invert_date = False subnets = None invert_subnet = False if expr.is_Not: expr = ~expr invert = True else: invert = False for arg in expr.args: if not boolalg.is_literal(arg): raise CannotRepresentRule( expr, "conjunction can only contain literals") acl_cond, invert = self.get_acl_cond_for_literal(arg) if isinstance(acl_cond, ACLGroupCondition): if group_ids: raise CannotRepresentRule( expr, "conjunction can only contain one group / user rule") group_ids = [self.get_group_id_from_cond(acl_cond)] invert_group = invert elif isinstance(acl_cond, ACLUserCondition): if group_ids: raise CannotRepresentRule( expr, "conjunction can only contain one group / user rule") group_ids = [ self.get_private_user_group_id_from_cond(acl_cond) ] invert_group = invert elif isinstance(acl_cond, (ACLDateBeforeClause, ACLDateAfterClause)): if dateranges: raise CannotRepresentRule( expr, "conjunction can only contain one date rule") dateranges = [make_open_daterange_from_rule(acl_cond)] invert_date = invert elif isinstance(acl_cond, ACLIPCondition): if subnets and not invert: raise CannotRepresentRule( expr, "conjunction can only contain one ip / iplist rule") subnets = [make_ipnetwork_from_rule(acl_cond)] invert_subnet = invert elif isinstance(acl_cond, ACLIPListCondition): if subnets and not invert: raise CannotRepresentRule( expr, "conjunction can only contain one ip / iplist rule") subnets = get_iplist_from_cond(acl_cond) invert_subnet = invert return ((AccessRule(group_ids=group_ids, subnets=subnets, dateranges=dateranges, invert_date=invert_date, invert_subnet=invert_subnet, invert_group=invert_group), invert), )