Home | History | Annotate | Download | only in setools
      1 # Copyright 2014-2015, Tresys Technology, LLC
      2 #
      3 # This file is part of SETools.
      4 #
      5 # SETools is free software: you can redistribute it and/or modify
      6 # it under the terms of the GNU Lesser General Public License as
      7 # published by the Free Software Foundation, either version 2.1 of
      8 # the License, or (at your option) any later version.
      9 #
     10 # SETools is distributed in the hope that it will be useful,
     11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 # GNU Lesser General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU Lesser General Public
     16 # License along with SETools.  If not, see
     17 # <http://www.gnu.org/licenses/>.
     18 #
     19 import logging
     20 import re
     21 
     22 from . import mixins, query
     23 from .descriptors import CriteriaDescriptor, CriteriaSetDescriptor, RuletypeDescriptor
     24 from .policyrep.exception import InvalidType, RuleUseError
     25 
     26 
     27 class RBACRuleQuery(mixins.MatchObjClass, query.PolicyQuery):
     28 
     29     """
     30     Query the RBAC rules.
     31 
     32     Parameter:
     33     policy            The policy to query.
     34 
     35     Keyword Parameters/Class attributes:
     36     ruletype        The list of rule type(s) to match.
     37     source          The name of the source role/attribute to match.
     38     source_indirect If true, members of an attribute will be
     39                     matched rather than the attribute itself.
     40     source_regex    If true, regular expression matching will
     41                     be used on the source role/attribute.
     42                     Obeys the source_indirect option.
     43     target          The name of the target role/attribute to match.
     44     target_indirect If true, members of an attribute will be
     45                     matched rather than the attribute itself.
     46     target_regex    If true, regular expression matching will
     47                     be used on the target role/attribute.
     48                     Obeys target_indirect option.
     49     tclass          The object class(es) to match.
     50     tclass_regex    If true, use a regular expression for
     51                     matching the rule's object class.
     52     default         The name of the default role to match.
     53     default_regex   If true, regular expression matching will
     54                     be used on the default role.
     55     """
     56 
     57     ruletype = RuletypeDescriptor("validate_rbac_ruletype")
     58     source = CriteriaDescriptor("source_regex", "lookup_role")
     59     source_regex = False
     60     source_indirect = True
     61     _target = None
     62     target_regex = False
     63     target_indirect = True
     64     tclass = CriteriaSetDescriptor("tclass_regex", "lookup_class")
     65     tclass_regex = False
     66     default = CriteriaDescriptor("default_regex", "lookup_role")
     67     default_regex = False
     68 
     69     @property
     70     def target(self):
     71         return self._target
     72 
     73     @target.setter
     74     def target(self, value):
     75         if not value:
     76             self._target = None
     77         elif self.target_regex:
     78             self._target = re.compile(value)
     79         else:
     80             try:
     81                 self._target = self.policy.lookup_type_or_attr(value)
     82             except InvalidType:
     83                 self._target = self.policy.lookup_role(value)
     84 
     85     def results(self):
     86         """Generator which yields all matching RBAC rules."""
     87         self.log.info("Generating results from {0.policy}".format(self))
     88         self.log.debug("Ruletypes: {0.ruletype}".format(self))
     89         self.log.debug("Source: {0.source!r}, indirect: {0.source_indirect}, "
     90                        "regex: {0.source_regex}".format(self))
     91         self.log.debug("Target: {0.target!r}, indirect: {0.target_indirect}, "
     92                        "regex: {0.target_regex}".format(self))
     93         self.log.debug("Class: {0.tclass!r}, regex: {0.tclass_regex}".format(self))
     94         self.log.debug("Default: {0.default!r}, regex: {0.default_regex}".format(self))
     95 
     96         for rule in self.policy.rbacrules():
     97             #
     98             # Matching on rule type
     99             #
    100             if self.ruletype:
    101                 if rule.ruletype not in self.ruletype:
    102                     continue
    103 
    104             #
    105             # Matching on source role
    106             #
    107             if self.source and not self._match_indirect_regex(
    108                     rule.source,
    109                     self.source,
    110                     self.source_indirect,
    111                     self.source_regex):
    112                 continue
    113 
    114             #
    115             # Matching on target type (role_transition)/role(allow)
    116             #
    117             if self.target and not self._match_indirect_regex(
    118                     rule.target,
    119                     self.target,
    120                     self.target_indirect,
    121                     self.target_regex):
    122                 continue
    123 
    124             #
    125             # Matching on object class
    126             #
    127             try:
    128                 if not self._match_object_class(rule):
    129                     continue
    130             except RuleUseError:
    131                 continue
    132 
    133             #
    134             # Matching on default role
    135             #
    136             if self.default:
    137                 try:
    138                     if not self._match_regex(
    139                             rule.default,
    140                             self.default,
    141                             self.default_regex):
    142                         continue
    143                 except RuleUseError:
    144                     continue
    145 
    146             # if we get here, we have matched all available criteria
    147             yield rule
    148