Changeset 78f2668


Ignore:
Timestamp:
Nov 30, 2010 10:48:51 AM (14 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

Location:
fedd/federation
Files:
1 added
2 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:
  • fedd/federation/emulab_access.py

    r027b87b r78f2668  
    1616
    1717from access import access_base
     18from legacy_access import legacy_access
    1819
    1920from util import *
     
    4142fl.addHandler(nullHandler())
    4243
    43 class access(access_base):
     44class access(access_base, legacy_access):
    4445    """
    4546    The implementation of access control based on mapping users to projects.
     
    119120        if self.auth_type == 'legacy':
    120121            if accessdb:
    121                 self.read_access(accessdb, self.make_access_project)
     122                self.legacy_read_access(accessdb, self.legacy_access_tuple)
    122123        elif self.auth_type == 'abac':
    123124            self.auth = abac_authorizer(load=self.auth_dir)
    124125            if accessdb:
    125                 self.read_abac_access(accessdb, self.make_abac_access_project)
     126                self.read_access(accessdb, self.access_tuple)
    126127        else:
    127128            raise service_error(service_error.internal,
     
    205206
    206207    @staticmethod
    207     def make_access_project(str):
     208    def legacy_access_tuple(str):
    208209        """
    209210        Convert a string of the form (id[:resources:resouces], id, id) into a
     
    235236
    236237    @staticmethod
    237     def make_abac_access_project(str):
     238    def access_tuple(str):
    238239        """
    239240        Convert a string of the form (id, id) into an access_project.  This is
    240         called by read_abac_access to convert to local attributes.  It returns
     241        called by read_access to convert to local attributes.  It returns
    241242        a tuple of the form (project, user, user) where the two users are
    242243        always the same.
     
    255256    # RequestAccess support routines
    256257
    257     def lookup_access(self, req, fid):
     258    def legacy_lookup_access(self, req, fid):
    258259        """
    259260        Look up the local access control information mapped to this fedid and
     
    270271        ru = None
    271272        # This maps a valid user to the Emulab projects and users to use
    272         found, match = self.lookup_access_base(req, fid)
     273        found, match = self.legacy_lookup_access_base(req, fid)
    273274        tb, project, user = match
    274275       
     
    326327                [ fid ]
    327328
    328     def lookup_abac_access(self, req, fid):
     329    def lookup_access(self, req, fid):
     330        """
     331        Check all the attributes that this controller knows how to map and see
     332        if the requester is allowed to use any of them.  If so return one.
     333        """
    329334        # Import request credentials into this (clone later??)
    330         if self.auth.import_credentials(data_list=req.get('abac_credential', [])):
     335        if self.auth.import_credentials(
     336                data_list=req.get('abac_credential', [])):
    331337            self.auth.save()
    332338
    333339        # Check every attribute that we know how to map and take the first
    334340        # success.
    335         print "%s" %self.auth
    336341        for attr in (self.access.keys()):
    337342            if self.auth.check_attribute(fid, attr):
     
    491496
    492497        if self.auth_type == "legacy":
     498            found, dyn, owners = self.legacy_lookup_access(req, fid)
     499        elif self.auth_type == 'abac':
    493500            found, dyn, owners = self.lookup_access(req, fid)
    494         elif self.auth_type == 'abac':
    495             found, dyn, owners = self.lookup_abac_access(req, fid)
    496501        else:
    497502            raise service_error(service_error.internal,
Note: See TracChangeset for help on using the changeset viewer.