Ignore:
Timestamp:
Nov 30, 2010 10:48:51 AM (13 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master
Children:
822d31b
Parents:
027b87b
Message:

Move some functions from access to legacy_access. Rename functions so abac is the default

File:
1 edited

Legend:

Unmodified
Added
Removed
  • fedd/federation/access.py

    r027b87b r78f2668  
    124124
    125125
    126     def read_access(self, config, access_obj=None):
    127         """
    128         Read an access DB with filename config  of the form:
    129             (id, id, id) -> attribute, something
    130         where the ids can be fedids, strings, or <any> or <none>, attribute is
    131         the attribute to assign , and something is any set of charcters.  The
    132         hash self.access is populated with mappings from those triples to the
    133         results of access_obj being called on the remainder of the line (if
    134         present).  If access_obj is not given, the string itself is entered in
    135         the hash.  Additionally, a triple with <any> and <none> mapped to None
    136         is entered in self.auth with the attribute given.
    137 
    138         Parsing errors result in a self.parse_error exception being raised.
    139         access_obj should throw that as well.
    140         """
    141         lineno=0
    142         name_expr = "["+string.ascii_letters + string.digits + "\.\-_]+"
    143         fedid_expr = "fedid:[" + string.hexdigits + "]+"
    144         key_name = "(<ANY>|<NONE>|"+fedid_expr + "|"+ name_expr + ")"
    145         access_re = re.compile('\('+key_name+'\s*,\s*'+key_name+'\s*,\s*'+
    146                 key_name+'\s*\)\s*->\s*([^,]+)\s*(.*)', re.IGNORECASE)
    147 
    148         def parse_name(n):
    149             if n.startswith('fedid:'): return fedid(hexstr=n[len('fedid:'):])
    150             else: return n
    151        
    152         def auth_name(n):
    153             if isinstance(n, basestring):
    154                 if n =='<any>' or n =='<none>': return None
    155                 else: return unicode(n)
    156             else:
    157                 return n
    158         def strip_comma(s):
    159             s = s.strip()
    160             if s.startswith(','):
    161                 s = s[1:].strip()
    162             return s
    163 
    164         if access_obj is None:
    165             access_obj = lambda(x): "%s" % x
    166 
    167         f = open(config, "r");
    168         try:
    169             for line in f:
    170                 lineno += 1
    171                 line = line.strip();
    172                 if len(line) == 0 or line.startswith('#'):
    173                     continue
    174 
    175                 # Access line (t, p, u) -> anything
    176                 m = access_re.match(line)
    177                 if m != None:
    178                     access_key = tuple([ parse_name(x) \
    179                             for x in m.group(1,2,3)])
    180                     attribute = m.group(4)
    181                     auth_key = tuple([ auth_name(x) for x in access_key])
    182                     self.auth.set_attribute(auth_key, attribute)
    183                     if len(m.group(5)) > 0:
    184                         access_val = access_obj(strip_comma(m.group(5)))
    185                         self.access[access_key] = access_val
    186                     continue
    187 
    188                 # Nothing matched to here: unknown line - raise exception
    189                 f.close()
    190                 raise self.parse_error(
    191                         "Unknown statement at line %d of %s" % \
    192                         (lineno, config))
    193         finally:
    194             if f: f.close()
    195 
    196     def read_abac_access(self, fn, access_obj=None):
     126    def read_access(self, fn, access_obj=None):
    197127        """
    198128        Read an access DB of the form
     
    228158        finally:
    229159            if f: f.close()
    230 
    231 
    232     def get_users(self, obj):
    233         """
    234         Return a list of the IDs of the users in dict
    235         """
    236         if obj.has_key('user'):
    237             return [ unpack_id(u['userID']) \
    238                     for u in obj['user'] if u.has_key('userID') ]
    239         else:
    240             return None
    241160
    242161    def write_state(self):
     
    279198
    280199
    281 
    282     def permute_wildcards(self, a, p):
    283         """Return a copy of a with various fields wildcarded.
    284 
    285         The bits of p control the wildcards.  A set bit is a wildcard
    286         replacement with the lowest bit being user then project then testbed.
    287         """
    288         if p & 1: user = ["<any>"]
    289         else: user = a[2]
    290         if p & 2: proj = "<any>"
    291         else: proj = a[1]
    292         if p & 4: tb = "<any>"
    293         else: tb = a[0]
    294 
    295         return (tb, proj, user)
    296 
    297     def find_access(self, search):
    298         """
    299         Search the access DB for a match on this tuple.  Return the matching
    300         access tuple and the user that matched.
    301        
    302         NB, if the initial tuple fails to match we start inserting wildcards in
    303         an order determined by self.project_priority.  Try the list of users in
    304         order (when wildcarded, there's only one user in the list).
    305         """
    306         if self.project_priority: perm = (0, 1, 2, 3, 4, 5, 6, 7)
    307         else: perm = (0, 2, 1, 3, 4, 6, 5, 7)
    308 
    309         for p in perm:
    310             s = self.permute_wildcards(search, p)
    311             # s[2] is None on an anonymous, unwildcarded request
    312             if s[2] != None:
    313                 for u in s[2]:
    314                     if self.access.has_key((s[0], s[1], u)):
    315                         return (self.access[(s[0], s[1], u)], u)
    316             else:
    317                 if self.access.has_key(s):
    318                     return (self.access[s], None)
    319         return None, None
    320 
    321     def lookup_access_base(self, req, fid):
    322         """
    323         Determine the allowed access for this request.  Return the access and
    324         which fields are dynamic.
    325 
    326         The fedid is needed to construct the request
    327         """
    328         user_re = re.compile("user:\s(.*)")
    329         project_re = re.compile("project:\s(.*)")
    330 
    331         # Search keys
    332         tb = fid
    333         user = [ user_re.findall(x)[0] for x in req.get('credential', []) \
    334                 if user_re.match(x)]
    335         project = [ project_re.findall(x)[0] \
    336                 for x in req.get('credential', []) \
    337                     if project_re.match(x)]
    338 
    339         if len(project) == 1: project = project[0]
    340         elif len(project) == 0: project = None
    341         else:
    342             raise service_error(service_error.req,
    343                     "More than one project credential")
    344 
    345         # Confirm authorization
    346         for u in user:
    347             self.log.debug("[lookup_access] Checking access for %s" % \
    348                     ((tb, project, u),))
    349             if self.auth.check_attribute((tb, project, u), 'access'):
    350                 self.log.debug("[lookup_access] Access granted")
    351                 break
    352             else:
    353                 self.log.debug("[lookup_access] Access Denied")
    354         else:
    355             raise service_error(service_error.access, "Access denied")
    356 
    357         # This maps a valid user to the Emulab projects and users to use
    358         found, user_match = self.find_access((tb, project, user))
    359 
    360         return (found, (tb, project, user_match))
    361        
    362 
    363200    def get_handler(self, path, fid):
     201        """
     202        This function is somewhat oddly named.  It doesn't get a handler, it
     203        handles GETs.  Specifically, it handls https GETs for retrieving data
     204        from the repository exported by the access server.
     205        """
    364206        self.log.info("Get handler %s %s" % (path, fid))
    365207        if self.auth.check_attribute(fid, path) and self.userconfdir:
Note: See TracChangeset for help on using the changeset viewer.