Example #1
0
def list(api, xrn, origin_hrn=None):
    hrn, type = urn_to_hrn(xrn)
    # load all know registry names into a prefix tree and attempt to find
    # the longest matching prefix
    records = []
    registries = api.registries
    registry_hrns = registries.keys()
    tree = prefixTree()
    tree.load(registry_hrns)
    registry_hrn = tree.best_match(hrn)
   
    #if there was no match then this record belongs to an unknow registry
    if not registry_hrn:
        raise MissingAuthority(xrn)
    
    # if the best match (longest matching hrn) is not the local registry,
    # forward the request
    records = []    
    if registry_hrn != api.hrn:
        credential = api.getCredential()
        record_list = registries[registry_hrn].List(xrn, credential)
        records = [SfaRecord(dict=record).as_dict() for record in record_list]
    
    # if we still have not found the record yet, try the local registry
    if not records:
        if not api.auth.hierarchy.auth_exists(hrn):
            raise MissingAuthority(hrn)

        table = SfaTable()
        records = table.find({'authority': hrn})

    return records
Example #2
0
    def call(self, cred, record_dict, origin_hrn=None):
        user_cred = Credential(string=cred)

        #log the call
        if not origin_hrn:
            origin_hrn = user_cred.get_gid_caller().get_hrn()    
        self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, None, self.name))

        # validate the cred
        self.api.auth.check(cred, "register")

        # make sure this is a peer record
        if 'peer_authority' not in record_dict or \
           not record_dict['peer_authority']: 
            raise SfaInvalidArgument, "peer_authority must be specified" 

        record = SfaRecord(dict = record_dict)
        type, hrn, peer_authority = record['type'], record['hrn'], record['peer_authority']
        record['authority'] = get_authority(record['hrn'])
        # verify permissions
        self.api.auth.verify_cred_is_me(cred)

        # check if record already exists
        table = SfaTable()
        existing_records = table.find({'type': type, 'hrn': hrn, 'peer_authority': peer_authority})
        if existing_records:
            for existing_record in existing_records:
                if existing_record['pointer'] != record['pointer']:
                    record['record_id'] = existing_record['record_id']
                    table.update(record)
        else:
            record_id = table.insert(record)
 
        return 1
Example #3
0
    def create_top_level_auth_records(self, hrn):
        """
        Create top level records (includes root and sub authorities (local/remote)
        """
        urn = hrn_to_urn(hrn, 'authority')
        # make sure parent exists
        parent_hrn = get_authority(hrn)
        if not parent_hrn:
            parent_hrn = hrn
        if not parent_hrn == hrn:
            self.create_top_level_auth_records(parent_hrn)

        # create the authority if it doesnt already exist 
        if not self.AuthHierarchy.auth_exists(urn):
            self.logger.info("Import: creating top level authorities")
            self.AuthHierarchy.create_auth(urn)
        
        # create the db record if it doesnt already exist    
        auth_info = self.AuthHierarchy.get_auth_info(hrn)
        table = SfaTable()
        auth_record = table.find({'type': 'authority', 'hrn': hrn})

        if not auth_record:
            auth_record = SfaRecord(hrn=hrn, gid=auth_info.get_gid_object(), type="authority", pointer=-1)
            auth_record['authority'] = get_authority(auth_record['hrn'])
            self.logger.info("Import: inserting authority record for %s"%hrn)
            table.insert(auth_record)
Example #4
0
def export_gid(options):
    from sfa.util.table import SfaTable
    # lookup the record for the specified hrn 
    hrn = options.export
    type = options.type
    # check sfa table first
    filter = {'hrn': hrn}
    if type:
        filter['type'] = type                    
    table = SfaTable()
    records = table.find(filter)
    if not records:
        # check the authorities hierarchy 
        hierarchy = Hierarchy()
        try:
            auth_info = hierarchy.get_auth_info()
            gid = auth_info.gid_object 
        except:
            print "Record: %s not found" % hrn
            sys.exit(1)
    else:
        record = records[0]
        gid = GID(string=record['gid'])
        
    # get the outfile
    outfile = options.outfile
    if not outfile:
        outfile = os.path.abspath('./%s.gid' % gid.get_hrn())

    # save it
    if options.verbose:
        print "Writing %s gid to %s" % (gid.get_hrn(), outfile)
    gid.save_to_file(outfile, save_parents=True)
Example #5
0
 def delete_record(self, hrn, type):
     # delete the record
     table = SfaTable()
     record_list = table.find({'type': type, 'hrn': hrn})
     for record in record_list:
         self.logger.info("Import: removing record %s %s" % (type, hrn))
         table.remove(record)        
Example #6
0
def main():
    config = Config()
    if not config.SFA_REGISTRY_ENABLED:
        sys.exit(0)

    # Get the path to the sfa server key/cert files from 
    # the sfa hierarchy object
    sfa_hierarchy = Hierarchy()
    sfa_key_path = sfa_hierarchy.basedir
    key_file = os.path.join(sfa_key_path, "server.key")
    cert_file = os.path.join(sfa_key_path, "server.cert")
    key = Keypair(filename=key_file) 

    # get a connection to our local sfa registry
    # and a valid credential
    authority = config.SFA_INTERFACE_HRN
    url = 'http://%s:%s/' %(config.SFA_REGISTRY_HOST, config.SFA_REGISTRY_PORT)
    registry = xmlrpcprotocol.get_server(url, key_file, cert_file)
    sfa_api = SfaAPI(key_file = key_file, cert_file = cert_file, interface='registry')
    credential = sfa_api.getCredential()

    # get peer registries
    registries = Registries(sfa_api)
    tree = prefixTree()
    tree.load(registries.keys())
    
    # get local peer records
    table = SfaTable()
    peer_records = table.find({'~peer_authority': None})
    found_records = []
    hrn_dict = {}
    for record in peer_records:
        registry_hrn = tree.best_match(record['hrn'])
        if registry_hrn not in hrn_dict:
            hrn_dict[registry_hrn] = []
        hrn_dict[registry_hrn].append(record['hrn'])

    # attempt to resolve the record at the authoritative interface 
    for registry_hrn in hrn_dict:
        if registry_hrn in registries:
            records = []
            target_hrns = hrn_dict[registry_hrn]    
            try:
                records = registries[registry_hrn].Resolve(target_hrns, credential)
                found_records.extend([record['hrn'] for record in records])
            except ServerException:
                # an exception will be thrown if the record doenst exist
                # if so remove the record from the local registry
                continue
            except:
                # this deosnt necessarily mean the records dont exist
                # lets give them the benefit of the doubt here (for now)
                found_records.extend(target_hrns)
                traceback.print_exc()

    # remove what wasnt found 
    for peer_record in peer_records:
        if peer_record['hrn'] not in found_records:
            registries[sfa_api.hrn].Remove(peer_record['hrn'], credential, peer_record['type'])
Example #7
0
def get_credential(api, xrn, type, is_self=False):
    # convert xrn to hrn     
    if type:
        hrn = urn_to_hrn(xrn)[0]
    else:
        hrn, type = urn_to_hrn(xrn)
        
    # Is this a root or sub authority
    auth_hrn = api.auth.get_authority(hrn)
    if not auth_hrn or hrn == api.config.SFA_INTERFACE_HRN:
        auth_hrn = hrn
    # get record info
    auth_info = api.auth.get_auth_info(auth_hrn)
    table = SfaTable()
    records = table.findObjects({'type': type, 'hrn': hrn})
    if not records:
        raise RecordNotFound(hrn)
    record = records[0]

    # verify_cancreate_credential requires that the member lists
    # (researchers, pis, etc) be filled in
    api.fill_record_info(record)
    if record['type']=='user':
       if not record['enabled']:
          raise AccountNotEnabled(": PlanetLab account %s is not enabled. Please contact your site PI" %(record['email']))

    # get the callers gid
    # if this is a self cred the record's gid is the caller's gid
    if is_self:
        caller_hrn = hrn
        caller_gid = record.get_gid_object()
    else:
        caller_gid = api.auth.client_cred.get_gid_caller() 
        caller_hrn = caller_gid.get_hrn()
    
    object_hrn = record.get_gid_object().get_hrn()
    rights = api.auth.determine_user_rights(caller_hrn, record)
    # make sure caller has rights to this object
    if rights.is_empty():
        raise PermissionError(caller_hrn + " has no rights to " + record['name'])

    object_gid = GID(string=record['gid'])
    new_cred = Credential(subject = object_gid.get_subject())
    new_cred.set_gid_caller(caller_gid)
    new_cred.set_gid_object(object_gid)
    new_cred.set_issuer_keys(auth_info.get_privkey_filename(), auth_info.get_gid_filename())
    #new_cred.set_pubkey(object_gid.get_pubkey())
    new_cred.set_privileges(rights)
    new_cred.get_privileges().delegate_all_privileges(True)
    if 'expires' in record:
        new_cred.set_expiration(int(record['expires']))
    auth_kind = "authority,ma,sa"
    # Parent not necessary, verify with certs
    #new_cred.set_parent(api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind))
    new_cred.encode()
    new_cred.sign()

    return new_cred.save_to_string(save_parents=True)
Example #8
0
def resolve(api, xrns, type=None, full=True):

    # load all known registry names into a prefix tree and attempt to find
    # the longest matching prefix
    if not isinstance(xrns, types.ListType):
        if not type:
            type = Xrn(xrns).get_type()
        xrns = [xrns]
    hrns = [urn_to_hrn(xrn)[0] for xrn in xrns] 
    # create a dict where key is a registry hrn and its value is a
    # hrns at that registry (determined by the known prefix tree).  
    xrn_dict = {}
    registries = api.registries
    tree = prefixTree()
    registry_hrns = registries.keys()
    tree.load(registry_hrns)
    for xrn in xrns:
        registry_hrn = tree.best_match(urn_to_hrn(xrn)[0])
        if registry_hrn not in xrn_dict:
            xrn_dict[registry_hrn] = []
        xrn_dict[registry_hrn].append(xrn)
        
    records = [] 
    for registry_hrn in xrn_dict:
        # skip the hrn without a registry hrn
        # XX should we let the user know the authority is unknown?       
        if not registry_hrn:
            continue

        # if the best match (longest matching hrn) is not the local registry,
        # forward the request
        xrns = xrn_dict[registry_hrn]
        if registry_hrn != api.hrn:
            credential = api.getCredential()
            peer_records = registries[registry_hrn].Resolve(xrns, credential)
            records.extend([SfaRecord(dict=record).as_dict() for record in peer_records])

    # try resolving the remaining unfound records at the local registry
    remaining_hrns = set(hrns).difference([record['hrn'] for record in records])
    # convert set to list
    remaining_hrns = [hrn for hrn in remaining_hrns] 
    table = SfaTable()
    local_records = table.findObjects({'hrn': remaining_hrns})
    if full:
        api.fill_record_info(local_records)
    
    # convert local record objects to dicts
    records.extend([dict(record) for record in local_records])
    if not records:
        raise RecordNotFound(str(hrns))

    if type:
        records = filter(lambda rec: rec['type'] in [type], records)

    return records
Example #9
0
def remove(api, xrn, origin_hrn=None):

    table = SfaTable()
    filter = {'hrn': xrn.get_hrn()}
    hrn=xrn.get_hrn()
    type=xrn.get_type()
    if type and type not in ['all', '*']:
        filter['type'] = type

    records = table.find(filter)
    if not records: raise RecordNotFound(hrn)
    record = records[0]
    type = record['type']

    credential = api.getCredential()
    registries = api.registries

    # Try to remove the object from the PLCDB of federated agg.
    # This is attempted before removing the object from the local agg's PLCDB and sfa table
    if hrn.startswith(api.hrn) and type in ['user', 'slice', 'authority']:
        for registry in registries:
            if registry not in [api.hrn]:
                try:
                    result=registries[registry].remove_peer_object(credential, record, origin_hrn)
                except:
                    pass
    if type == "user":
        persons = api.plshell.GetPersons(api.plauth, record['pointer'])
        # only delete this person if he has site ids. if he doesnt, it probably means
        # he was just removed from a site, not actually deleted
        if persons and persons[0]['site_ids']:
            api.plshell.DeletePerson(api.plauth, record['pointer'])
    elif type == "slice":
        if api.plshell.GetSlices(api.plauth, record['pointer']):
            api.plshell.DeleteSlice(api.plauth, record['pointer'])
    elif type == "node":
        if api.plshell.GetNodes(api.plauth, record['pointer']):
            api.plshell.DeleteNode(api.plauth, record['pointer'])
    elif type == "authority":
        if api.plshell.GetSites(api.plauth, record['pointer']):
            api.plshell.DeleteSite(api.plauth, record['pointer'])
    else:
        raise UnknownSfaType(type)

    table.remove(record)

    return 1
Example #10
0
    def create_sm_client_record(self):
        """
        Create a user record for the Slicemanager service.
        """
        hrn = self.config.SFA_INTERFACE_HRN + '.slicemanager'
        urn = hrn_to_urn(hrn, 'user')
        if not self.AuthHierarchy.auth_exists(urn):
            self.logger.info("Import: creating Slice Manager user")
            self.AuthHierarchy.create_auth(urn)

        auth_info = self.AuthHierarchy.get_auth_info(hrn)
        table = SfaTable()
        sm_user_record = table.find({'type': 'user', 'hrn': hrn})
        if not sm_user_record:
            record = SfaRecord(hrn=hrn, gid=auth_info.get_gid_object(), type="user", pointer=-1)
            record['authority'] = get_authority(record['hrn'])
            table.insert(record)    
Example #11
0
def import_gid(options):
    """
    Import the specified gid into the registry (db and authorities 
    hierarchy) overwriting any previous gid.
    """
    from sfa.util.table import SfaTable
    from sfa.util.record import SfaRecord
    # load the gid
    gidfile = os.path.abspath(options.importgid)
    if not gidfile or not os.path.isfile(gidfile):
        print "No such gid: %s" % gidfile
        sys.exit(1)
    gid = GID(filename=gidfile)
    
    # check if it exists within the hierarchy
    hierarchy = Hierarchy()
    if not hierarchy.auth_exists(gid.get_hrn()):
        print "%s not found in hierarchy" % gid.get_hrn()
        sys.exit(1)

    # check if record exists in db
    table = SfaTable()
    records = table.find({'hrn': gid.get_hrn(), 'type': 'authority'})
    if not records:
        print "%s not found in record database" % get.get_hrn()  
        sys.exit(1)

    # update the database record
    record = records[0]
    record['gid'] = gid.save_to_string(save_parents=True)
    table.update(record)
    if options.verbose:
        print "Imported %s gid into db" % record['hrn']

    # update the hierarchy
    auth_info = hierarchy.get_auth_info(gid.get_hrn())  
    filename = auth_info.gid_filename
    gid.save_to_file(filename, save_parents=True)
    if options.verbose:
        print "Writing %s gid to %s" % (gid.get_hrn(), filename)

    # ending here
    return
Example #12
0
 def create_interface_records(self):
     """
     Create a record for each SFA interface
     """
     # just create certs for all sfa interfaces even if they
     # arent enabled
     interface_hrn = self.config.SFA_INTERFACE_HRN
     interfaces = ['authority+sa', 'authority+am', 'authority+sm']
     table = SfaTable()
     auth_info = self.AuthHierarchy.get_auth_info(interface_hrn)
     pkey = auth_info.get_pkey_object()
     for interface in interfaces:
         interface_record = table.find({'type': interface, 'hrn': interface_hrn})
         if not interface_record:
             self.logger.info("Import: interface %s %s " % (interface_hrn, interface))
             urn = hrn_to_urn(interface_hrn, interface)
             gid = self.AuthHierarchy.create_gid(urn, create_uuid(), pkey)
             record = SfaRecord(hrn=interface_hrn, gid=gid, type=interface, pointer=-1)  
             record['authority'] = get_authority(interface_hrn)
             table.insert(record) 
Example #13
0
def main():
   usage="%prog: trash the registry DB (the 'sfa' table in the 'planetlab5' database)"
   parser = OptionParser(usage=usage)
   parser.add_option('-f','--file-system',dest='clean_fs',action='store_true',default=False,
                     help='Clean up the /var/lib/sfa/authorities area as well')
   parser.add_option('-c','--certs',dest='clean_certs',action='store_true',default=False,
                     help='Remove all cached certs/gids found in /var/lib/sfa/authorities area as well')
   (options,args)=parser.parse_args()
   if args:
      parser.print_help()
      sys.exit(1)
   logger.info("Purging SFA records from database")
   table = SfaTable()
   table.sfa_records_purge()

   if options.clean_certs:
      # remove the server certificate and all gids found in /var/lib/sfa/authorities
      logger.info("Purging cached certificates")
      for (dir, _, files) in os.walk('/var/lib/sfa/authorities'):
         for file in files:
            if file.endswith('.gid') or file == 'server.cert':
               path=dir+os.sep+file
               os.unlink(path)
               if not os.path.exists(path):
                  logger.info("Unlinked file %s"%path)
               else:
                  logger.error("Could not unlink file %s"%path)

   if options.clean_fs:
      # just remove all files that do not match 'server.key' or 'server.cert'
      logger.info("Purging registry filesystem cache")
      preserved_files = [ 'server.key', 'server.cert']
      for (dir,_,files) in os.walk('/var/lib/sfa/authorities'):
         for file in files:
            if file in preserved_files: continue
            path=dir+os.sep+file
            os.unlink(path)
            if not os.path.exists(path):
               logger.info("Unlinked file %s"%path)
            else:
               logger.error("Could not unlink file %s"%path)
Example #14
0
    def import_slice(self, parent_hrn, slice):
        slicename = slice['name'].split("_",1)[-1]
        slicename = _cleanup_string(slicename)

        if not slicename:
            self.logger.error("Import: failed to parse slice name %s" %slice['name'])
            return

        hrn = parent_hrn + "." + slicename
        self.logger.info("Import: slice %s"%hrn)

        pkey = Keypair(create=True)
        urn = hrn_to_urn(hrn, 'slice')
        slice_gid = self.AuthHierarchy.create_gid(urn, create_uuid(), pkey)
        slice_record = SfaRecord(hrn=hrn, gid=slice_gid, type="slice", pointer=slice['slice_id'])
        slice_record['authority'] = get_authority(slice_record['hrn'])
        table = SfaTable()
        existing_records = table.find({'hrn': hrn, 'type': 'slice', 'pointer': slice['slice_id']})
        if not existing_records:
            table.insert(slice_record)
        else:
            self.logger.info("Import: %s exists, updating " % hrn)
            existing_record = existing_records[0]
            slice_record['record_id'] = existing_record['record_id']
            table.update(slice_record)
Example #15
0
    def import_site(self, hrn, site):
        shell = self.shell
        plc_auth = self.plc_auth
        urn = hrn_to_urn(hrn, 'authority')
        self.logger.info("Import: site %s"%hrn)

        # create the authority
        if not self.AuthHierarchy.auth_exists(urn):
            self.AuthHierarchy.create_auth(urn)

        auth_info = self.AuthHierarchy.get_auth_info(urn)

        table = SfaTable()
        auth_record = SfaRecord(hrn=hrn, gid=auth_info.get_gid_object(), type="authority", pointer=site['site_id'])
        auth_record['authority'] = get_authority(auth_record['hrn'])
        existing_records = table.find({'hrn': hrn, 'type': 'authority', 'pointer': site['site_id']})
        if not existing_records:
            table.insert(auth_record)
        else:
            self.logger.info("Import: %s exists, updating " % hrn)
            existing_record = existing_records[0]
            auth_record['record_id'] = existing_record['record_id']
            table.update(auth_record)

        return hrn
Example #16
0
    def call(self, cred, record, origin_hrn=None):
        user_cred = Credential(string=cred)

        #log the call
        if not origin_hrn:
            origin_hrn = user_cred.get_gid_caller().get_hrn()
        self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, record['hrn'], self.name))

        self.api.auth.check(cred, "remove")

        # Only allow the local interface or record owner to delete peer_records 
        try: self.api.auth.verify_object_permission(record['hrn'])
        except: self.api.auth.verify_cred_is_me(cred)
        
        table = SfaTable()
        hrn, type = record['hrn'], record['type']
        records = table.find({'hrn': hrn, 'type': type })
        for record in records:
            if record['peer_authority']:
                self.remove_plc_record(record)
                table.remove(record)
            
        return 1
Example #17
0
    def import_person(self, parent_hrn, person):
        """
        Register a user record 
        """
        hrn = email_to_hrn(parent_hrn, person['email'])

        # ASN.1 will have problems with hrn's longer than 64 characters
        if len(hrn) > 64:
            hrn = hrn[:64]

        self.logger.info("Import: person %s"%hrn)
        key_ids = []
        if 'key_ids' in person and person['key_ids']:
            key_ids = person["key_ids"]
            # get the user's private key from the SSH keys they have uploaded
            # to planetlab
            keys = self.shell.GetKeys(self.plc_auth, key_ids)
            key = keys[0]['key']
            pkey = None
            try:
                pkey = convert_public_key(key)
            except:
                self.logger.warn('unable to convert public key for %s' % hrn) 
            if not pkey:
                pkey = Keypair(create=True)
        else:
            # the user has no keys
            self.logger.warn("Import: person %s does not have a PL public key"%hrn)
            # if a key is unavailable, then we still need to put something in the
            # user's GID. So make one up.
            pkey = Keypair(create=True)

        # create the gid
        urn = hrn_to_urn(hrn, 'user')
        person_gid = self.AuthHierarchy.create_gid(urn, create_uuid(), pkey)
        table = SfaTable()
        person_record = SfaRecord(hrn=hrn, gid=person_gid, type="user", pointer=person['person_id'])
        person_record['authority'] = get_authority(person_record['hrn'])
        existing_records = table.find({'hrn': hrn, 'type': 'user', 'pointer': person['person_id']})
        if not existing_records:
            table.insert(person_record)
        else:
            self.logger.info("Import: %s exists, updating " % hrn)
            existing_record = existing_records[0]
            person_record['record_id'] = existing_record['record_id']
            table.update(person_record)
Example #18
0
    def import_node(self, hrn, node):
        self.logger.info("Import: node %s" % hrn)
        # ASN.1 will have problems with hrn's longer than 64 characters
        if len(hrn) > 64:
            hrn = hrn[:64]

        table = SfaTable()
        node_record = table.find({'type': 'node', 'hrn': hrn})
        pkey = Keypair(create=True)
        urn = hrn_to_urn(hrn, 'node')
        node_gid = self.AuthHierarchy.create_gid(urn, create_uuid(), pkey)
        node_record = SfaRecord(hrn=hrn, gid=node_gid, type="node", pointer=node['node_id'])
        node_record['authority'] = get_authority(node_record['hrn'])
        existing_records = table.find({'hrn': hrn, 'type': 'node', 'pointer': node['node_id']})
        if not existing_records:
            table.insert(node_record)
        else:
            self.logger.info("Import: %s exists, updating " % hrn)
            existing_record = existing_records[0]
            node_record['record_id'] = existing_record['record_id']
            table.update(node_record)
Example #19
0
def update_cert_records(gids):
    """
    Make sure there is a record in the registry for the specified gids. 
    Removes old records from the db.
    """
    # import SfaTable here so this module can be loaded by ComponentAPI
    from sfa.util.table import SfaTable
    from sfa.util.record import SfaRecord

    if not gids:
        return
    table = SfaTable()
    # get records that actually exist in the db
    gid_urns = [gid.get_urn() for gid in gids]
    hrns_expected = [gid.get_hrn() for gid in gids]
    records_found = table.find({"hrn": hrns_expected, "pointer": -1})

    # remove old records
    for record in records_found:
        if record["hrn"] not in hrns_expected and record["hrn"] != self.api.config.SFA_INTERFACE_HRN:
            table.remove(record)

    # TODO: store urn in the db so we do this in 1 query
    for gid in gids:
        hrn, type = gid.get_hrn(), gid.get_type()
        record = table.find({"hrn": hrn, "type": type, "pointer": -1})
        if not record:
            record = {
                "hrn": hrn,
                "type": type,
                "pointer": -1,
                "authority": get_authority(hrn),
                "gid": gid.save_to_string(save_parents=True),
            }
            record = SfaRecord(dict=record)
            table.insert(record)
Example #20
0
def register(api, record):

    hrn, type = record['hrn'], record['type']
    urn = hrn_to_urn(hrn,type)
    # validate the type
    if type not in ['authority', 'slice', 'node', 'user']:
        raise UnknownSfaType(type) 
    
    # check if record already exists
    table = SfaTable()
    existing_records = table.find({'type': type, 'hrn': hrn})
    if existing_records:
        raise ExistingRecord(hrn)
       
    record = SfaRecord(dict = record)
    record['authority'] = get_authority(record['hrn'])
    type = record['type']
    hrn = record['hrn']
    auth_info = api.auth.get_auth_info(record['authority'])
    pub_key = None
    # make sure record has a gid
    if 'gid' not in record:
        uuid = create_uuid()
        pkey = Keypair(create=True)
        if 'key' in record and record['key']:
            if isinstance(record['key'], types.ListType):
                pub_key = record['key'][0]
            else:
                pub_key = record['key']
            pkey = convert_public_key(pub_key)

        gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
        gid = gid_object.save_to_string(save_parents=True)
        record['gid'] = gid
        record.set_gid(gid)

    if type in ["authority"]:
        # update the tree
        if not api.auth.hierarchy.auth_exists(hrn):
            api.auth.hierarchy.create_auth(hrn_to_urn(hrn,'authority'))

        # get the GID from the newly created authority
        gid = auth_info.get_gid_object()
        record.set_gid(gid.save_to_string(save_parents=True))
        pl_record = api.sfa_fields_to_pl_fields(type, hrn, record)
        sites = api.plshell.GetSites(api.plauth, [pl_record['login_base']])
        if not sites:
            pointer = api.plshell.AddSite(api.plauth, pl_record)
        else:
            pointer = sites[0]['site_id']

        record.set_pointer(pointer)
        record['pointer'] = pointer

    elif (type == "slice"):
        acceptable_fields=['url', 'instantiation', 'name', 'description']
        pl_record = api.sfa_fields_to_pl_fields(type, hrn, record)
        for key in pl_record.keys():
            if key not in acceptable_fields:
                pl_record.pop(key)
        slices = api.plshell.GetSlices(api.plauth, [pl_record['name']])
        if not slices:
             pointer = api.plshell.AddSlice(api.plauth, pl_record)
        else:
             pointer = slices[0]['slice_id']
        record.set_pointer(pointer)
        record['pointer'] = pointer

    elif  (type == "user"):
        persons = api.plshell.GetPersons(api.plauth, [record['email']])
        if not persons:
            pointer = api.plshell.AddPerson(api.plauth, dict(record))
        else:
            pointer = persons[0]['person_id']

        if 'enabled' in record and record['enabled']:
            api.plshell.UpdatePerson(api.plauth, pointer, {'enabled': record['enabled']})
        # add this persons to the site only if he is being added for the first
        # time by sfa and doesont already exist in plc
        if not persons or not persons[0]['site_ids']:
            login_base = get_leaf(record['authority'])
            api.plshell.AddPersonToSite(api.plauth, pointer, login_base)

        # What roles should this user have?
        api.plshell.AddRoleToPerson(api.plauth, 'user', pointer)
        # Add the user's key
        if pub_key:
            api.plshell.AddPersonKey(api.plauth, pointer, {'key_type' : 'ssh', 'key' : pub_key})

    elif (type == "node"):
        pl_record = api.sfa_fields_to_pl_fields(type, hrn, record)
        login_base = hrn_to_pl_login_base(record['authority'])
        nodes = api.plshell.GetNodes(api.plauth, [pl_record['hostname']])
        if not nodes:
            pointer = api.plshell.AddNode(api.plauth, login_base, pl_record)
        else:
            pointer = nodes[0]['node_id']

    record['pointer'] = pointer
    record.set_pointer(pointer)
    record_id = table.insert(record)
    record['record_id'] = record_id

    # update membership for researchers, pis, owners, operators
    api.update_membership(None, record)

    return record.get_gid_object().save_to_string(save_parents=True)
Example #21
0
def update(api, record_dict):
    new_record = SfaRecord(dict = record_dict)
    type = new_record['type']
    hrn = new_record['hrn']
    urn = hrn_to_urn(hrn,type)
    table = SfaTable()
    # make sure the record exists
    records = table.findObjects({'type': type, 'hrn': hrn})
    if not records:
        raise RecordNotFound(hrn)
    record = records[0]
    record['last_updated'] = time.gmtime()

    # Update_membership needs the membership lists in the existing record
    # filled in, so it can see if members were added or removed
    api.fill_record_info(record)

    # Use the pointer from the existing record, not the one that the user
    # gave us. This prevents the user from inserting a forged pointer
    pointer = record['pointer']
    # update the PLC information that was specified with the record

    if (type == "authority"):
        api.plshell.UpdateSite(api.plauth, pointer, new_record)

    elif type == "slice":
        pl_record=api.sfa_fields_to_pl_fields(type, hrn, new_record)
        if 'name' in pl_record:
            pl_record.pop('name')
            api.plshell.UpdateSlice(api.plauth, pointer, pl_record)

    elif type == "user":
        # SMBAKER: UpdatePerson only allows a limited set of fields to be
        #    updated. Ideally we should have a more generic way of doing
        #    this. I copied the field names from UpdatePerson.py...
        update_fields = {}
        all_fields = new_record
        for key in all_fields.keys():
            if key in ['first_name', 'last_name', 'title', 'email',
                       'password', 'phone', 'url', 'bio', 'accepted_aup',
                       'enabled']:
                update_fields[key] = all_fields[key]
        api.plshell.UpdatePerson(api.plauth, pointer, update_fields)

        if 'key' in new_record and new_record['key']:
            # must check this key against the previous one if it exists
            persons = api.plshell.GetPersons(api.plauth, [pointer], ['key_ids'])
            person = persons[0]
            keys = person['key_ids']
            keys = api.plshell.GetKeys(api.plauth, person['key_ids'])
            key_exists = False
            if isinstance(new_record['key'], types.ListType):
                new_key = new_record['key'][0]
            else:
                new_key = new_record['key']
            
            # Delete all stale keys
            for key in keys:
                if new_record['key'] != key['key']:
                    api.plshell.DeleteKey(api.plauth, key['key_id'])
                else:
                    key_exists = True
            if not key_exists:
                api.plshell.AddPersonKey(api.plauth, pointer, {'key_type': 'ssh', 'key': new_key})

            # update the openssl key and gid
            pkey = convert_public_key(new_key)
            uuid = create_uuid()
            gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
            gid = gid_object.save_to_string(save_parents=True)
            record['gid'] = gid
            record = SfaRecord(dict=record)
            table.update(record)

    elif type == "node":
        api.plshell.UpdateNode(api.plauth, pointer, new_record)

    else:
        raise UnknownSfaType(type)

    # update membership for researchers, pis, owners, operators
    api.update_membership(record, new_record)
    
    return 1 
Example #22
0
    def call(self):
        # verify that the callers's ip address exist in the db and is an inteface
        # for a node in the db
        (ip, port) = self.api.remote_addr
        interfaces = self.api.plshell.GetInterfaces(self.api.plauth, {'ip': ip}, ['node_id'])
        if not interfaces:
            raise NonExistingRecord("no such ip %(ip)s" % locals())
        nodes = self.api.plshell.GetNodes(self.api.plauth, [interfaces[0]['node_id']], ['node_id', 'hostname'])
        if not nodes:
            raise NonExistingRecord("no such node using ip %(ip)s" % locals())
        node = nodes[0]
       
        # look up the sfa record
        table = SfaTable()
        records = table.findObjects({'type': 'node', 'pointer': node['node_id']})
        if not records:
            raise RecordNotFound("pointer:" + str(node['node_id']))  
        record = records[0]
        
        # generate a new keypair and gid
        uuid = create_uuid()
        pkey = Keypair(create=True)
        urn = hrn_to_urn(record['hrn'], record['type'])
        gid_object = self.api.auth.hierarchy.create_gid(urn, uuid, pkey)
        gid = gid_object.save_to_string(save_parents=True)
        record['gid'] = gid
        record.set_gid(gid)

        # update the record
        table.update(record)
  
        # attempt the scp the key
        # and gid onto the node
        # this will only work for planetlab based components
        (kfd, key_filename) = tempfile.mkstemp() 
        (gfd, gid_filename) = tempfile.mkstemp() 
        pkey.save_to_file(key_filename)
        gid_object.save_to_file(gid_filename, save_parents=True)
        host = node['hostname']
        key_dest="/etc/sfa/node.key"
        gid_dest="/etc/sfa/node.gid" 
        scp = "/usr/bin/scp" 
        #identity = "/etc/planetlab/root_ssh_key.rsa"
        identity = "/etc/sfa/root_ssh_key"
        scp_options=" -i %(identity)s " % locals()
        scp_options+="-o StrictHostKeyChecking=no " % locals()
        scp_key_command="%(scp)s %(scp_options)s %(key_filename)s root@%(host)s:%(key_dest)s" %\
                         locals()
        scp_gid_command="%(scp)s %(scp_options)s %(gid_filename)s root@%(host)s:%(gid_dest)s" %\
                         locals()    

        all_commands = [scp_key_command, scp_gid_command]
        
        for command in all_commands:
            (status, output) = commands.getstatusoutput(command)
            if status:
                raise Exception, output

        for filename in [key_filename, gid_filename]:
            os.unlink(filename)

        return 1 
Example #23
0
def main():

    process_options()
    config = Config()
    if not config.SFA_REGISTRY_ENABLED:
        sys.exit(0)
    root_auth = config.SFA_REGISTRY_ROOT_AUTH
    interface_hrn = config.SFA_INTERFACE_HRN
    keys_filename = config.config_path + os.sep + 'person_keys.py' 
    sfaImporter = sfaImport()
    if config.SFA_API_DEBUG: sfaImporter.logger.setLevelDebug()
    shell = sfaImporter.shell
    plc_auth = sfaImporter.plc_auth 
    
    # initialize registry db table
    table = SfaTable()
    if not table.exists():
       table.create()

    # create root authority 
    sfaImporter.create_top_level_auth_records(root_auth)
    if not root_auth == interface_hrn:
        sfaImporter.create_top_level_auth_records(interface_hrn)

    # create s user record for the slice manager
    sfaImporter.create_sm_client_record()

    # create interface records
    sfaImporter.logger.info("Import: creating interface records")
    sfaImporter.create_interface_records()

    # add local root authority's cert  to trusted list
    sfaImporter.logger.info("Import: adding " + interface_hrn + " to trusted list")
    authority = sfaImporter.AuthHierarchy.get_auth_info(interface_hrn)
    sfaImporter.TrustedRoots.add_gid(authority.get_gid_object())

    # special case for vini
    if ".vini" in interface_hrn and interface_hrn.endswith('vini'):
        # create a fake internet2 site first
        i2site = {'name': 'Internet2', 'abbreviated_name': 'I2',
                    'login_base': 'internet2', 'site_id': -1}
        sfaImporter.import_site(interface_hrn, i2site)
   
    # create dict of all existing sfa records
    existing_records = {}
    existing_hrns = []
    key_ids = []
    person_keys = {} 
    results = table.find()
    for result in results:
        existing_records[(result['hrn'], result['type'])] = result
        existing_hrns.append(result['hrn']) 
            
    # Get all plc sites
    sites = shell.GetSites(plc_auth, {'peer_id': None})
    sites_dict = {}
    for site in sites:
        sites_dict[site['login_base']] = site 
    
    # Get all plc users
    persons = shell.GetPersons(plc_auth, {'peer_id': None, 'enabled': True}, ['person_id', 'email', 'key_ids', 'site_ids'])
    persons_dict = {}
    for person in persons:
        persons_dict[person['person_id']] = person
        key_ids.extend(person['key_ids'])

    # Get all public keys
    keys = shell.GetKeys(plc_auth, {'peer_id': None, 'key_id': key_ids})
    keys_dict = {}
    for key in keys:
        keys_dict[key['key_id']] = key['key']

    # create a dict of person keys keyed on key_id 
    old_person_keys = load_keys(keys_filename)
    for person in persons:
        pubkeys = []
        for key_id in person['key_ids']:
            pubkeys.append(keys_dict[key_id])
        person_keys[person['person_id']] = pubkeys

    # Get all plc nodes  
    nodes = shell.GetNodes(plc_auth, {'peer_id': None}, ['node_id', 'hostname', 'site_id'])
    nodes_dict = {}
    for node in nodes:
        nodes_dict[node['node_id']] = node

    # Get all plc slices
    slices = shell.GetSlices(plc_auth, {'peer_id': None}, ['slice_id', 'name'])
    slices_dict = {}
    for slice in slices:
        slices_dict[slice['slice_id']] = slice
    # start importing 
    for site in sites:
        site_hrn = _get_site_hrn(interface_hrn, site)
        sfaImporter.logger.info("Importing site: %s" % site_hrn)

        # import if hrn is not in list of existing hrns or if the hrn exists
        # but its not a site record
        if site_hrn not in existing_hrns or \
           (site_hrn, 'authority') not in existing_records:
            sfaImporter.import_site(site_hrn, site)
             
        # import node records
        for node_id in site['node_ids']:
            if node_id not in nodes_dict:
                continue 
            node = nodes_dict[node_id]
            site_auth = get_authority(site_hrn)
            site_name = get_leaf(site_hrn)
            hrn =  hostname_to_hrn(site_auth, site_name, node['hostname'])
            if hrn not in existing_hrns or \
               (hrn, 'node') not in existing_records:
                sfaImporter.import_node(hrn, node)

        # import slices
        for slice_id in site['slice_ids']:
            if slice_id not in slices_dict:
                continue 
            slice = slices_dict[slice_id]
            hrn = slicename_to_hrn(interface_hrn, slice['name'])
            if hrn not in existing_hrns or \
               (hrn, 'slice') not in existing_records:
                sfaImporter.import_slice(site_hrn, slice)      

        # import persons
        for person_id in site['person_ids']:
            if person_id not in persons_dict:
                continue 
            person = persons_dict[person_id]
            hrn = email_to_hrn(site_hrn, person['email'])
            old_keys = []
            new_keys = []
            if person_id in old_person_keys:
                old_keys = old_person_keys[person_id]
            if person_id in person_keys:
                new_keys = person_keys[person_id]
            update_record = False
            for key in new_keys:
                if key not in old_keys:
                    update_record = True 

            if hrn not in existing_hrns or \
               (hrn, 'user') not in existing_records or update_record:
                sfaImporter.import_person(site_hrn, person)

    
    # remove stale records    
    system_records = [interface_hrn, root_auth, interface_hrn + '.slicemanager']
    for (record_hrn, type) in existing_records.keys():
        if record_hrn in system_records:
            continue
        
        record = existing_records[(record_hrn, type)]
        if record['peer_authority']:
            continue

        # dont delete vini's internet2 placeholdder record
        # normally this would be deleted becuase it does not have a plc record 
        if ".vini" in interface_hrn and interface_hrn.endswith('vini') and \
           record_hrn.endswith("internet2"):     
            continue

        found = False
        
        if type == 'authority':    
            for site in sites:
                site_hrn = interface_hrn + "." + site['login_base']
                if site_hrn == record_hrn and site['site_id'] == record['pointer']:
                    found = True
                    break

        elif type == 'user':
            login_base = get_leaf(get_authority(record_hrn))
            username = get_leaf(record_hrn)
            if login_base in sites_dict:
                site = sites_dict[login_base]
                for person in persons:
                    tmp_username = person['email'].split("@")[0]
                    alt_username = person['email'].split("@")[0].replace(".", "_").replace("+", "_")
                    if username in [tmp_username, alt_username] and \
                       site['site_id'] in person['site_ids'] and \
                       person['person_id'] == record['pointer']:
                        found = True
                        break
        
        elif type == 'slice':
            slicename = hrn_to_pl_slicename(record_hrn)
            for slice in slices:
                if slicename == slice['name'] and \
                   slice['slice_id'] == record['pointer']:
                    found = True
                    break    
 
        elif type == 'node':
            login_base = get_leaf(get_authority(record_hrn))
            nodename = Xrn.unescape(get_leaf(record_hrn))
            if login_base in sites_dict:
                site = sites_dict[login_base]
                for node in nodes:
                    tmp_nodename = node['hostname']
                    if tmp_nodename == nodename and \
                       node['site_id'] == site['site_id'] and \
                       node['node_id'] == record['pointer']:
                        found = True
                        break  
        else:
            continue 
        
        if not found:
            record_object = existing_records[(record_hrn, type)]
            sfaImporter.delete_record(record_hrn, type) 
                                   
    # save pub keys
    sfaImporter.logger.info('Import: saving current pub keys')
    save_keys(keys_filename, person_keys)