Changeset 3f6bc5f


Ignore:
Timestamp:
Nov 21, 2008 4:39:47 PM (15 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
Children:
ac54ef3
Parents:
c971895
Message:

Initial move to general authorization framework. Currently integrated with Access stuff fully.

Location:
fedd
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • fedd/fedd_access.py

    rc971895 r3f6bc5f  
    1515from fedd_access_project import access_project
    1616from fedid import fedid, generate_fedid
     17from authorizer import authorizer
    1718import parse_detail
    1819from service_error import *
     
    5051                    'RequestAccessRequestBody')
    5152
    52     def __init__(self, config=None):
     53    def __init__(self, config=None, auth=None):
    5354        """
    5455        Initializer.  Pulls parameters out of the ConfigParser's access section.
     
    6364        else:
    6465            raise RunTimeError("No config to fedd_access")
    65 
    6666
    6767        # Create instance attributes from the static lists
     
    9090            'keys' : self.keys
    9191        }
     92        self.log = logging.getLogger("fedd.access")
     93        set_log_level(config, "access", self.log)
    9294        self.state_lock = Lock()
     95
     96        if auth: self.auth = auth
     97        else:
     98            self.log.error(\
     99                    "[access]: No authorizer initialized, creating local one.")
     100            auth = authorizer()
     101
    93102        self.fedid_default = "testbed"
    94103        if config.has_option("access", "accessdb"):
    95104            self.read_access(config.get("access", "accessdb"))
    96         if config.has_option("access", "trustdb"):
    97             self.read_trust(config.get("access", "trustdb"))
    98105
    99106        self.state_filename = config.get("access", "access_state", "")
    100         self.log = logging.getLogger("fedd.access")
    101         set_log_level(config, "access", self.log)
    102107        self.read_state()
    103 
    104 
    105108        # Certs are promoted from the generic to the specific, so without a
    106109        # specific proxy certificate, the main certificates are used for
     
    166169        if not config.has_option("access", "dynamic_projects_url"):
    167170            self.allocate_project = \
    168                 fedd_allocate_project_local(config)
     171                fedd_allocate_project_local(config, auth)
    169172        else:
    170173            self.allocate_project = \
    171                 fedd_allocate_project_remote(config)
     174                fedd_allocate_project_remote(config, auth)
    172175
    173176        # If the project allocator exports services, put them in this object's
     
    176179        self.xmlrpc_services.update(self.allocate_project.xmlrpc_services)
    177180
    178     def read_trust(self, trust):
    179         """
    180         Read a trust file that splits fedids into testbeds, users or projects
    181 
    182         Format is:
    183 
    184         [type]
    185         fedid
    186         fedid
    187         default: type
    188         """
    189         lineno = 0;
    190         cat = None
    191         cat_re = re.compile("\[(user|testbed|project)\]$", re.IGNORECASE)
    192         fedid_re = re.compile("[" + string.hexdigits + "]+$")
    193         default_re = re.compile("default:\s*(user|testbed|project)$",
    194                 re.IGNORECASE)
    195 
    196         f = open(trust, "r")
    197         for line in f:
    198             lineno += 1
    199             line = line.strip()
    200             if len(line) == 0 or line.startswith("#"):
    201                 continue
    202             # Category line
    203             m = cat_re.match(line)
    204             if m != None:
    205                 cat = m.group(1).lower()
    206                 continue
    207             # Fedid line
    208             m = fedid_re.match(line)
    209             if m != None:
    210                 if cat != None:
    211                     self.fedid_category[fedid(hexstr=m.string)] = cat
    212                 else:
    213                     raise self.parse_error(\
    214                             "Bad fedid in trust file (%s) line: %d" % \
    215                             (trust, lineno))
    216                 continue
    217             # default line
    218             m = default_re.match(line)
    219             if m != None:
    220                 self.fedid_default = m.group(1).lower()
    221                 continue
    222             # Nothing matched - bad line, raise exception
    223             f.close()
    224             raise self.parse_error(\
    225                     "Unparsable line in trustfile %s line %d" % (trust, lineno))
    226         f.close()
    227181
    228182    def read_access(self, config):
     
    270224
    271225        def parse_name(n):
    272             if n.startswith('fedid:'): return fedid(n[len('fedid:'):])
     226            if n.startswith('fedid:'): return fedid(hexstr=n[len('fedid:'):])
    273227            else: return n
     228       
     229        def auth_name(n):
     230            if isinstance(n, basestring):
     231                if n =='<any>' or n =='<none>': return None
     232                else: return unicode(n)
     233            else:
     234                return n
    274235
    275236        f = open(config, "r");
     
    298259            if m != None:
    299260                access_key = tuple([ parse_name(x) for x in m.group(1,2,3)])
     261                auth_key = tuple([ auth_name(x) for x in access_key])
    300262                aps = m.group(4).split(":");
    301263                if aps[0] == 'fedid:':
     
    310272
    311273                self.access[access_key] = access_val
     274                self.auth.set_attribute(auth_key, "access")
    312275                continue
    313276
     
    386349                    "Unpickling failed: %s") % e)
    387350
     351        for k in self.allocation.keys():
     352            for o in self.allocation[k].get('owners', []):
     353                self.auth.set_attribute(o, fedid(hexstr=k))
     354
     355
    388356    def permute_wildcards(self, a, p):
    389357        """Return a copy of a with various fields wildcarded.
     
    440408        ru = None
    441409
    442 
    443         principal_type = self.fedid_category.get(fid, self.fedid_default)
    444 
    445         if principal_type == "testbed": tb = fid
    446 
    447410        if req.has_key('project'):
    448411            p = req['project']
     
    453416            user = self.get_users(req)
    454417
    455         # Now filter by prinicpal type
    456         if principal_type == "user":
    457             if user != None:
    458                 fedids = [ u for u in user if isinstance(u, type(fid))]
     418        user_fedids = [ u for u in user if isinstance(u, fedid)]
     419        # Determine how the caller is representing itself.  If its fedid shows
     420        # up as a project or a singleton user, let that stand.  If neither the
     421        # usernames nor the project name is a fedid, the caller is a testbed.
     422        if project and isinstance(project, fedid):
     423            if project == fid:
     424                # The caller is the project (which is already in the tuple
     425                # passed in to the authorizer)
     426                owners = user_fedids
     427                owners.append(project)
     428            else:
     429                raise service_error(service_error.req,
     430                        "Project asserting different fedid")
     431        else:
     432            if fid not in user_fedids:
     433                tb = fid
     434                owners = user_fedids
     435                owners.append(fid)
     436            else:
    459437                if len(fedids) > 1:
    460438                    raise service_error(service_error.req,
    461                             "User asserting multiple fedids")
    462                 elif len(fedids) == 1 and fedids[0] != fid:
    463                     raise service_error(service_error.req,
    464439                            "User asserting different fedid")
    465             project = None
    466             tb = None
    467         elif principal_type == "project":
    468             if isinstance(project, type(fid)) and fid != project:
    469                 raise service_error(service_error.req,
    470                         "Project asserting different fedid")
    471             tb = None
    472 
    473         # Ready to look up access
     440                else:
     441                    # Which is a singleton
     442                    owners = user_fedids
     443        # Confirm authorization
     444        for u in user:
     445            if self.auth.check_attribute((tb, project, u), 'access'):
     446                print "Access OK"
     447                break
     448        else:
     449            print "Access failed"
     450            raise service_error(service_error.access, "Access denied")
     451
     452        # This maps a valid user to the Emulab projects and users to use
    474453        found, user_match = self.find_access((tb, project, user))
    475454       
    476455        if found == None:
    477456            raise service_error(service_error.access,
    478                     "Access denied")
     457                    "Access denied - cannot map access")
    479458
    480459        # resolve <dynamic> and <same> in found
     
    521500            dyn_service_user = True
    522501
    523         return (rp, rcu, rsu), (dyn_create_user, dyn_service_user, dyn_proj)
     502        return (rp, rcu, rsu), (dyn_create_user, dyn_service_user, dyn_proj),\
     503                owners
    524504
    525505    def build_response(self, alloc_id, ap):
     
    571551        if dt == None or dt == self.testbed:
    572552            # Request for this fedd
    573             found, dyn = self.lookup_access(req, fid)
     553            found, dyn, owners = self.lookup_access(req, fid)
    574554            restricted = None
    575555            ap = None
     
    687667                        "Misformed allocation response?")
    688668
     669            self.allocation[aid]['owners'] = owners
    689670            self.write_state()
    690671            self.state_lock.release()
     672            for o in owners:
     673                self.auth.set_attribute(o, allocID)
    691674            resp = self.build_response({ 'fedid': allocID } , ap)
    692675            return resp
     
    709692        try:
    710693            if req['allocID'].has_key('localname'):
    711                 aid = req['allocID']['localname']
     694                auth_attr = aid = req['allocID']['localname']
    712695            elif req['allocID'].has_key('fedid'):
    713696                aid = unicode(req['allocID']['fedid'])
     697                auth_attr = req['allocID']['fedid']
    714698            else:
    715699                raise service_error(service_error.req,
     
    717701        except KeyError:
    718702            raise service_error(service_error.req, "Badly formed request")
     703
     704        print "Checking for %s %s" % (fid, auth_attr)
     705        if not self.auth.check_attribute(fid, auth_attr):
     706            raise service_error(service_error.access, "Access Denied")
    719707
    720708        # If we know this allocation, reduce the reference counts and remove
     
    724712        # duplicates.  del_project is just the name of any dynamic project to
    725713        # delete.
     714        # We're somewhat lazy about deleting authorization attributes.  Having
     715        # access to something that doesn't exist isn't harmful.
    726716        del_users = { }
    727717        del_project = None
  • fedd/fedd_allocate_project.py

    rc971895 r3f6bc5f  
    3333    Allocate projects on this machine in response to an access request.
    3434    """
    35     def __init__(self, config):
     35    def __init__(self, config, auth=None):
    3636        """
    3737        Initializer.  Parses a configuration if one is given.
     
    387387
    388388    # back to defining the fedd_allocate_project_remote class
    389     def __init__(self, config):
     389    def __init__(self, config, auth=None):
    390390        """
    391391        Initializer.  Parses a configuration if one is given.
  • fedd/fedd_deter_impl.py

    rc971895 r3f6bc5f  
    44from fedd_experiment_control import fedd_experiment_control_local
    55from fedd_split import fedd_split_local
     6
     7from authorizer import authorizer
    68
    79class fedd_deter_impl:
     
    2224        self.soap_services = { }
    2325        self.xmlrpc_services = { }
     26        self.auth = authorizer()
    2427
    2528        if config:
     
    2932
    3033            if config.has_section("access"):
    31                 self.access = fedd_access(config)
     34                self.access = fedd_access(config, self.auth)
    3235                self.soap_services.update(self.access.soap_services)
    3336                self.xmlrpc_services.update(self.access.xmlrpc_services)
    3437
    3538            if config.has_section("experiment_control"):
    36                 self.experiment = fedd_experiment_control_local(config)
     39                self.experiment = \
     40                        fedd_experiment_control_local(config, self.auth)
    3741                self.soap_services.update(self.experiment.soap_services)
    3842                self.xmlrpc_services.update(self.experiment.xmlrpc_services)
    3943
    4044            if config.has_section("splitter"):
    41                 self.splitter = fedd_split_local(config)
     45                self.splitter = fedd_split_local(config, self.auth)
    4246                self.soap_services.update(self.splitter.soap_services)
    4347                self.xmlrpc_services.update(self.splitter.xmlrpc_services)
  • fedd/fedd_experiment_control.py

    rc971895 r3f6bc5f  
    154154            Ns2SplitRequestMessage, 'Ns2SplitRequestBody')
    155155
    156     def __init__(self, config=None):
     156    def __init__(self, config=None, auth=None):
    157157        """
    158158        Intialize the various attributes, most from the config object
  • fedd/fedd_split.py

    rc971895 r3f6bc5f  
    2222
    2323class fedd_split_local:
    24     def __init__(self, config=None):
     24    def __init__(self, config=None, auth=None):
    2525        """
    2626        Intialize the various attributes, most from the config object
Note: See TracChangeset for help on using the changeset viewer.