# SFA XML-RPC and SOAP interfaces
#
-import sys
import os
-import traceback
-import string
+import tempfile
+import datetime
import xmlrpclib
-from sfa.util.faults import *
-from sfa.util.api import *
-from sfa.util.config import *
-from sfa.util.sfalogging import sfa_logger
+from sfa.util.faults import RecordNotFound, MissingSfaInfo
+from sfa.util.api import BaseAPI
+from sfa.util.config import Config
+from sfa.util.sfalogging import logger
import sfa.util.xmlrpcprotocol as xmlrpcprotocol
-from sfa.trust.auth import Auth
-from sfa.trust.rights import Right, Rights
-from sfa.trust.credential import Credential,Keypair
-from sfa.trust.certificate import Certificate
-from sfa.util.namespace import get_authority, hrn_to_pl_slicename, hrn_to_pl_slicename, hrn_to_urn, slicename_to_hrn, hostname_to_hrn
+from sfa.util.xrn import hrn_to_urn
+from sfa.util.plxrn import hostname_to_hrn, hrn_to_pl_slicename, \
+ hrn_to_pl_slicename, slicename_to_hrn, hrn_to_pl_login_base
from sfa.util.nodemanager import NodeManager
+
+from sfa.trust.auth import Auth
+from sfa.trust.rights import determine_rights
+from sfa.trust.credential import Credential
+from sfa.trust.certificate import Certificate, Keypair
+from sfa.trust.gid import GID
try:
from collections import defaultdict
except:
self.credential = None
# Initialize the PLC shell only if SFA wraps a myPLC
rspec_type = self.config.get_aggregate_type()
- if (rspec_type == 'pl' or rspec_type == 'vini' or rspec_type == 'eucalyptus'):
+ if (rspec_type == 'pl' or rspec_type == 'vini' or \
+ rspec_type == 'eucalyptus' or rspec_type == 'max'):
self.plshell = self.getPLCShell()
self.plshell_version = "4.3"
self.hrn = self.config.SFA_INTERFACE_HRN
self.time_format = "%Y-%m-%d %H:%M:%S"
- self.logger=sfa_logger()
+
def getPLCShell(self):
self.plauth = {'Username': self.config.SFA_PLC_USER,
'AuthMethod': 'password',
'AuthString': self.config.SFA_PLC_PASSWORD}
- try:
- sys.path.append(os.path.dirname(os.path.realpath("/usr/bin/plcsh")))
- self.plshell_type = 'direct'
- import PLC.Shell
- shell = PLC.Shell.Shell(globals = globals())
- except:
- self.plshell_type = 'xmlrpc'
- url = self.config.SFA_PLC_URL
- shell = xmlrpclib.Server(url, verbose = 0, allow_none = True)
+
+ # The native shell (PLC.Shell.Shell) is more efficient than xmlrpc,
+ # but it leaves idle db connections open. use xmlrpc until we can figure
+ # out why PLC.Shell.Shell doesn't close db connection properly
+ #try:
+ # sys.path.append(os.path.dirname(os.path.realpath("/usr/bin/plcsh")))
+ # self.plshell_type = 'direct'
+ # import PLC.Shell
+ # shell = PLC.Shell.Shell(globals = globals())
+ #except:
+ self.plshell_type = 'xmlrpc'
+ url = self.config.SFA_PLC_URL
+ shell = xmlrpclib.Server(url, verbose = 0, allow_none = True)
return shell
+ def get_server(self, interface, cred, timeout=30):
+ """
+ Returns a connection to the specified interface. Use the specified
+ credential to determine the caller and look for the caller's key/cert
+ in the registry hierarchy cache.
+ """
+ from sfa.trust.hierarchy import Hierarchy
+ if not isinstance(cred, Credential):
+ cred_obj = Credential(string=cred)
+ else:
+ cred_obj = cred
+ caller_gid = cred_obj.get_gid_caller()
+ hierarchy = Hierarchy()
+ auth_info = hierarchy.get_auth_info(caller_gid.get_hrn())
+ key_file = auth_info.get_privkey_filename()
+ cert_file = auth_info.get_gid_filename()
+ server = interface.get_server(key_file, cert_file, timeout)
+ return server
+
+
def getCredential(self):
"""
Return a valid credential for this interface.
"""
+ type = 'authority'
+ path = self.config.SFA_DATA_DIR
+ filename = ".".join([self.interface, self.hrn, type, "cred"])
+ cred_filename = path + os.sep + filename
+ cred = None
+ if os.path.isfile(cred_filename):
+ cred = Credential(filename = cred_filename)
+ # make sure cred isnt expired
+ if not cred.get_expiration or \
+ datetime.datetime.utcnow() < cred.get_expiration():
+ return cred.save_to_string(save_parents=True)
+
+ # get a new credential
if self.interface in ['registry']:
- return self.getCredentialFromLocalRegistry()
+ cred = self.__getCredentialRaw()
else:
- return self.getCredentialFromRegistry()
+ cred = self.__getCredential()
+ cred.save_to_file(cred_filename, save_parents=True)
+
+ return cred.save_to_string(save_parents=True)
+
def getDelegatedCredential(self, creds):
"""
Attempt to find a credential delegated to us in
the specified list of creds.
"""
+ from sfa.trust.hierarchy import Hierarchy
if creds and not isinstance(creds, list):
creds = [creds]
- delegated_creds = filter_creds_by_caller(creds,self.hrn)
- if not delegated_creds:
- return None
- return delegated_creds[0]
+ hierarchy = Hierarchy()
+
+ delegated_cred = None
+ for cred in creds:
+ if hierarchy.auth_exists(Credential(string=cred).get_gid_caller().get_hrn()):
+ delegated_cred = cred
+ break
+ return delegated_cred
- def getCredentialFromRegistry(self):
+ def __getCredential(self):
"""
Get our credential from a remote registry
"""
- type = 'authority'
- path = self.config.SFA_DATA_DIR
- filename = ".".join([self.interface, self.hrn, type, "cred"])
- cred_filename = path + os.sep + filename
- try:
- credential = Credential(filename = cred_filename)
- return credential.save_to_string(save_parents=True)
- except IOError:
- from sfa.server.registry import Registries
- registries = Registries(self)
- registry = registries[self.hrn]
- cert_string=self.cert.save_to_string(save_parents=True)
- # get self credential
- self_cred = registry.GetSelfCredential(cert_string, self.hrn, type)
- # get credential
- cred = registry.GetCredential(self_cred, self.hrn, type)
-
- # save cred to file
- Credential(string=cred).save_to_file(cred_filename, save_parents=True)
- return cred
-
- def getCredentialFromLocalRegistry(self):
+ from sfa.server.registry import Registries
+ registries = Registries()
+ registry = registries.get_server(self.hrn, self.key_file, self.cert_file)
+ cert_string=self.cert.save_to_string(save_parents=True)
+ # get self credential
+ self_cred = registry.GetSelfCredential(cert_string, self.hrn, 'authority')
+ # get credential
+ cred = registry.GetCredential(self_cred, self.hrn, 'authority')
+ return Credential(string=cred)
+
+ def __getCredentialRaw(self):
"""
Get our current credential directly from the local registry.
"""
auth_hrn = hrn
auth_info = self.auth.get_auth_info(auth_hrn)
table = self.SfaTable()
- records = table.findObjects(hrn)
+ records = table.findObjects({'hrn': hrn, 'type': 'authority+sa'})
if not records:
raise RecordNotFound
record = records[0]
r1 = determine_rights(type, hrn)
new_cred.set_privileges(r1)
-
- auth_kind = "authority,ma,sa"
-
- new_cred.set_parent(self.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)
+ return new_cred
def loadCredential (self):
except IOError:
self.credential = self.getCredentialFromRegistry()
+
+
##
# Convert SFA fields to PLC fields for use when registering up updating
# registry record in the PLC database
break
# fill in key info
if record['type'] == 'user':
- pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
- record['keys'] = pubkeys
+ if 'key_ids' not in record:
+ logger.info("user record has no 'key_ids' - need to import from myplc ?")
+ else:
+ pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
+ record['keys'] = pubkeys
# fill in record hrns
records = self.fill_record_hrns(records)
# convert ids to hrns
for record in records:
-
# get all relevant data
type = record['type']
pointer = record['pointer']
if site_id in sites]
site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
record['sites'] = site_hrns
-
+
return records
def fill_record_sfa_info(self, records):
# fill sfa info
for record in records:
# skip records with no pl info (top level authorities)
- if record['pointer'] == -1:
- continue
+ #if record['pointer'] == -1:
+ # continue
sfa_info = {}
type = record['type']
if (type == "slice"):
# all slice users are researchers
+ record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
record['PI'] = []
record['researcher'] = []
- for person_id in record['person_ids']:
+ for person_id in record.get('person_ids', []):
hrns = [person['hrn'] for person in persons[person_id]]
record['researcher'].extend(hrns)
# pis at the slice's site
- pl_pis = site_pis[record['site_id']]
- pi_ids = [pi['person_id'] for pi in pl_pis]
- for person_id in pi_ids:
- hrns = [person['hrn'] for person in persons[person_id]]
- record['PI'].extend(hrns)
- record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
- record['geni_creator'] = record['PI']
-
- elif (type == "authority"):
- record['PI'] = []
- record['operator'] = []
- record['owner'] = []
- for pointer in record['person_ids']:
- if pointer not in persons or pointer not in pl_persons:
- # this means there is not sfa or pl record for this user
- continue
- hrns = [person['hrn'] for person in persons[pointer]]
- roles = pl_persons[pointer]['roles']
- if 'pi' in roles:
+ if 'site_id' in record and record['site_id'] in site_pis:
+ pl_pis = site_pis[record['site_id']]
+ pi_ids = [pi['person_id'] for pi in pl_pis]
+ for person_id in pi_ids:
+ hrns = [person['hrn'] for person in persons[person_id]]
record['PI'].extend(hrns)
- if 'tech' in roles:
- record['operator'].extend(hrns)
- if 'admin' in roles:
- record['owner'].extend(hrns)
- # xxx TODO: OrganizationName
+ record['geni_creator'] = record['PI']
+
+ elif (type.startswith("authority")):
+ record['url'] = None
+ if record['hrn'] in self.aggregates:
+
+ record['url'] = self.aggregates[record['hrn']].get_url()
+
+ if record['pointer'] != -1:
+ record['PI'] = []
+ record['operator'] = []
+ record['owner'] = []
+ for pointer in record.get('person_ids', []):
+ if pointer not in persons or pointer not in pl_persons:
+ # this means there is not sfa or pl record for this user
+ continue
+ hrns = [person['hrn'] for person in persons[pointer]]
+ roles = pl_persons[pointer]['roles']
+ if 'pi' in roles:
+ record['PI'].extend(hrns)
+ if 'tech' in roles:
+ record['operator'].extend(hrns)
+ if 'admin' in roles:
+ record['owner'].extend(hrns)
+ # xxx TODO: OrganizationName
elif (type == "node"):
sfa_info['dns'] = record.get("hostname", "")
# xxx TODO: URI, LatLong, IP, DNS
self.fill_record_sfa_info(records)
def update_membership_list(self, oldRecord, record, listName, addFunc, delFunc):
- # get a list of the HRNs tht are members of the old and new records
+ # get a list of the HRNs that are members of the old and new records
if oldRecord:
oldList = oldRecord.get(listName, [])
else:
oldList = []
newList = record.get(listName, [])
+ # xxx ugly hack - somehow we receive here a list of {'text':value}
+ # instead of an expected list of strings
+ # please remove once this is issue is cleanly fixed
+ def normalize (value):
+ from types import StringTypes
+ from sfa.util.sfalogging import logger
+ if isinstance(value,StringTypes): return value
+ elif isinstance(value,dict):
+ newvalue=value['text']
+ logger.info("Normalizing %s=>%s"%(value,newvalue))
+ return newvalue
+ newList=[normalize(v) for v in newList]
# if the lists are the same, then we don't have to update anything
if (oldList == newList):
def sliver_exists(self):
sliver_dict = self.nodemanager.GetXIDs()
+ ### xxx slicename is undefined
if slicename in sliver_dict.keys():
return True
else:
cert_str = Certificate(filename=cert_filename).save_to_string(save_parents=True)
registry = self.get_registry()
cred = registry.GetSelfCredential(cert_str, hrn, 'node')
+ # xxx credfile is undefined
Credential(string=cred).save_to_file(credfile, save_parents=True)
return cred
"""
files = ["server.key", "server.cert", "node.cred"]
for f in files:
+ # xxx KEYDIR is undefined, could be meant to be "/var/lib/sfa/" from sfa_component_setup.py
filepath = KEYDIR + os.sep + f
if os.path.isfile(filepath):
os.unlink(f)