From: Josh Karlin Date: Tue, 11 May 2010 16:49:18 +0000 (+0000) Subject: updated to trunk -r 17901:17994 X-Git-Tag: geni-apiv1-totrunk~19 X-Git-Url: http://git.onelab.eu/?p=sfa.git;a=commitdiff_plain;h=e17288b4251451a2376cff24fa90b3568deb9434 updated to trunk -r 17901:17994 --- diff --git a/config/default_config.xml b/config/default_config.xml index a63b56bb..37cd6cce 100644 --- a/config/default_config.xml +++ b/config/default_config.xml @@ -76,14 +76,7 @@ $URL$ The hrn of the registry's root auth. - - Level1 Authority - - The hrn of the registry's level1 auth (sub - authority). The full name of this interface (only secify if - this interface is a sub authority). - - + diff --git a/config/sfa-config-tty b/config/sfa-config-tty index ed77fb1e..9b2c439e 100755 --- a/config/sfa-config-tty +++ b/config/sfa-config-tty @@ -15,7 +15,6 @@ def validator(validated_variables): usual_variables = [ "SFA_INTERFACE_HRN", "SFA_REGISTRY_ROOT_AUTH", - "SFA_REGISTRY_LEVEL1_AUTH", "SFA_REGISTRY_HOST", "SFA_AGGREGATE_HOST", "SFA_SM_HOST", diff --git a/setup.py b/setup.py index 8d777927..e3d6f020 100755 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ bins = [ 'config/gen-sfa-cm-config.py', 'sfa/plc/sfa-import-plc.py', 'sfa/plc/sfa-nuke-plc.py', + 'sfa/server/sfa-ca.py', 'sfa/server/sfa-server.py', 'sfa/server/sfa-clean-peer-records.py', 'sfa/server/sfa_component_setup.py', diff --git a/sfa.spec b/sfa.spec index 2e32acb8..88e7883c 100644 --- a/sfa.spec +++ b/sfa.spec @@ -34,6 +34,7 @@ Requires: libxslt-python Requires: python-ZSI # xmlbuilder depends on lxml Requires: python-lxml +Requires: python-setuptools # python 2.5 has uuid module added, for python 2.4 we still need it. # we can't really check for if we can load uuid as a python module, diff --git a/sfa/client/sfi.py b/sfa/client/sfi.py index 5b792471..a27c3ff9 100755 --- a/sfa/client/sfi.py +++ b/sfa/client/sfi.py @@ -9,6 +9,8 @@ import tempfile import traceback import socket import random +from lxml import etree +from StringIO import StringIO from types import StringTypes, ListType from optparse import OptionParser from sfa.trust.certificate import Keypair, Certificate @@ -16,36 +18,25 @@ from sfa.trust.credential import Credential from sfa.util.sfaticket import SfaTicket from sfa.util.record import * from sfa.util.namespace import * -from sfa.util.rspec import RSpec from sfa.util.xmlrpcprotocol import ServerException import sfa.util.xmlrpcprotocol as xmlrpcprotocol from sfa.util.config import Config import zlib + # utility methods here # display methods def display_rspec(rspec, format='rspec'): if format in ['dns']: - spec = RSpec() - spec.parseString(rspec) - hostnames = [] - nodespecs = spec.getDictsByTagName('NodeSpec') - for nodespec in nodespecs: - if nodespec.has_key('name') and nodespec['name']: - if isinstance(nodespec['name'], ListType): - hostnames.extend(nodespec['name']) - elif isinstance(nodespec['name'], StringTypes): - hostnames.append(nodespec['name']) - result = hostnames + tree = etree.parse(StringIO(rspec)) + root = tree.getroot() + result = root.xpath("./network/site/node/hostname/text()") elif format in ['ip']: - spec = RSpec() - spec.parseString(rspec) - ips = [] - ifspecs = spec.getDictsByTagName('IfSpec') - for ifspec in ifspecs: - if ifspec.has_key('addr') and ifspec['addr']: - ips.append(ifspec['addr']) - result = ips + # The IP address is not yet part of the new RSpec + # so this doesn't do anything yet. + tree = etree.parse(StringIO(rspec)) + root = tree.getroot() + result = root.xpath("./network/site/node/ipv4/text()") else: result = rspec @@ -867,11 +858,10 @@ class Sfi: user_cred = self.get_user_cred() slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True) - # get a list node hostnames from the nodespecs in the rspec - rspec = RSpec() - rspec.parseString(ticket.rspec) - nodespecs = rspec.getDictsByTagName('NodeSpec') - hostnames = [nodespec['name'] for nodespec in nodespecs] + # get a list of node hostnames from the RSpec + tree = etree.parse(StringIO(ticket.rspec)) + root = tree.getroot() + hostnames = root.xpath("./network/site/node/hostname/text()") # create an xmlrpc connection to the component manager at each of these # components and gall redeem_ticket diff --git a/sfa/managers/component_manager_default.py b/sfa/managers/component_manager_default.py index 800857cb..e6482d4a 100644 --- a/sfa/managers/component_manager_default.py +++ b/sfa/managers/component_manager_default.py @@ -14,7 +14,7 @@ def reset_slice(api, slicename): def get_slices(api): return -def roboot(): +def reboot(): return def redeem_ticket(api, ticket_string): diff --git a/sfa/managers/component_manager_pl.py b/sfa/managers/component_manager_pl.py index 2f795580..e9643ea6 100644 --- a/sfa/managers/component_manager_pl.py +++ b/sfa/managers/component_manager_pl.py @@ -46,7 +46,7 @@ def get_slices(api): slices = eval(xids[1]) return slices.keys() -def roboot(): +def reboot(): os.system("/sbin/reboot") def redeem_ticket(api, ticket_string): diff --git a/sfa/managers/registry_manager_pl.py b/sfa/managers/registry_manager_pl.py index 8a97a3fd..50776c0c 100644 --- a/sfa/managers/registry_manager_pl.py +++ b/sfa/managers/registry_manager_pl.py @@ -157,7 +157,7 @@ def list(api, xrn, origin_hrn=None): 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) diff --git a/sfa/plc/sfa-import-plc.py b/sfa/plc/sfa-import-plc.py index 46593c77..39cb28c0 100755 --- a/sfa/plc/sfa-import-plc.py +++ b/sfa/plc/sfa-import-plc.py @@ -74,7 +74,7 @@ def main(): if not config.SFA_REGISTRY_ENABLED: sys.exit(0) root_auth = config.SFA_REGISTRY_ROOT_AUTH - level1_auth = config.SFA_REGISTRY_LEVEL1_AUTH + interface_hrn = config.SFA_INTERFACE_HRN keys_filename = config.config_path + os.sep + 'person_keys.py' sfaImporter = sfaImport(logger) shell = sfaImporter.shell @@ -86,27 +86,20 @@ def main(): if not table.exists(): table.create() - if not level1_auth or level1_auth in ['']: - level1_auth = None - - if not level1_auth: - sfaImporter.create_top_level_auth_records(root_auth) - import_auth = root_auth - else: - if not AuthHierarchy.auth_exists(level1_auth): - AuthHierarchy.create_auth(hrn_to_urn(level1_auth,'authority')) - sfaImporter.create_top_level_auth_records(level1_auth) - import_auth = level1_auth + # 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) - trace("Import: adding " + import_auth + " to trusted list", logger) - authority = AuthHierarchy.get_auth_info(import_auth) + trace("Import: adding " + interface_hrn + " to trusted list", logger) + authority = AuthHierarchy.get_auth_info(interface_hrn) TrustedRoots.add_gid(authority.get_gid_object()) - if ".vini" in import_auth and import_auth.endswith('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(import_auth, i2site) + sfaImporter.import_site(interface_hrn, i2site) # create dict of all existing sfa records existing_records = {} @@ -158,21 +151,21 @@ def main(): slices_dict[slice['slice_id']] = slice # start importing for site in sites: - site_hrn = import_auth + "." + site['login_base'] + site_hrn = interface_hrn + "." + site['login_base'] print "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: - site_hrn = sfaImporter.import_site(import_auth, site) + site_hrn = sfaImporter.import_site(interface_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] - hrn = hostname_to_hrn(import_auth, site['login_base'], node['hostname']) + hrn = hostname_to_hrn(interface_hrn, site['login_base'], node['hostname']) if hrn not in existing_hrns or \ (hrn, 'node') not in existing_records: sfaImporter.import_node(site_hrn, node) @@ -182,7 +175,7 @@ def main(): if slice_id not in slices_dict: continue slice = slices_dict[slice_id] - hrn = slicename_to_hrn(import_auth, slice['name']) + 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) @@ -212,11 +205,13 @@ def main(): for (record_hrn, type) in existing_records.keys(): record = existing_records[(record_hrn, type)] # if this is the interface name dont do anything - if record_hrn == import_auth or record['peer_authority']: + if record_hrn == interface_hrn or \ + record_hrn == root_auth or \ + 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 import_auth and import_auth.endswith('vini') and \ + if ".vini" in interface_hrn and interface_hrn.endswith('vini') and \ record_hrn.endswith("internet2"): continue @@ -224,7 +219,7 @@ def main(): if type == 'authority': for site in sites: - site_hrn = import_auth + "." + site['login_base'] + site_hrn = interface_hrn + "." + site['login_base'] if site_hrn == record_hrn and site['site_id'] == record['pointer']: found = True break diff --git a/sfa/plc/sfaImport.py b/sfa/plc/sfaImport.py index bf68b6c6..84c00c74 100644 --- a/sfa/plc/sfaImport.py +++ b/sfa/plc/sfaImport.py @@ -56,9 +56,6 @@ class sfaImport: self.TrustedRoots = TrustedRootList(Config.get_trustedroots_dir(self.config)) self.plc_auth = self.config.get_plc_auth() self.root_auth = self.config.SFA_REGISTRY_ROOT_AUTH - self.level1_auth = self.config.SFA_REGISTRY_LEVEL1_AUTH - if not self.level1_auth or self.level1_auth in ['']: - self.level1_auth = None # connect to planetlab self.shell = None @@ -71,25 +68,18 @@ class sfaImport: def create_top_level_auth_records(self, hrn): + # create the authority if it doesnt already exist AuthHierarchy = self.AuthHierarchy urn = hrn_to_urn(hrn, 'authority') - # if auth records for this hrn dont exist, create it if not AuthHierarchy.auth_exists(urn): trace("Import: creating top level authorites", self.logger) AuthHierarchy.create_auth(urn) - - - # get the auth info of the newly created root auth (parent) - # or level1_auth if it exists - if self.level1_auth: - auth_info = AuthHierarchy.get_auth_info(hrn) + parent_hrn = get_authority(hrn) + if not parent_hrn: parent_hrn = hrn - else: - parent_hrn = get_authority(hrn) - if not parent_hrn: - parent_hrn = hrn - auth_info = AuthHierarchy.get_auth_info(parent_hrn) - + auth_info = AuthHierarchy.get_auth_info(parent_hrn) + + # create the db record if it doesnt already exist table = SfaTable() auth_record = table.find({'type': 'authority', 'hrn': hrn}) diff --git a/sfa/server/aggregate.py b/sfa/server/aggregate.py index aecc3b69..515b9e97 100644 --- a/sfa/server/aggregate.py +++ b/sfa/server/aggregate.py @@ -30,21 +30,13 @@ class Aggregates(Interfaces): default_dict = {'aggregates': {'aggregate': [Interfaces.default_fields]}} def __init__(self, api, conf_file = "/etc/sfa/aggregates.xml"): - Interfaces.__init__(self, api, conf_file, 'ma') - - def get_connections(self, interfaces): - """ - Get connection details for the trusted peer aggregates from file and - create an connection to each. - """ - connections = Interfaces.get_connections(self, interfaces) - + Interfaces.__init__(self, api, conf_file) # set up a connection to the local registry address = self.api.config.SFA_AGGREGATE_HOST port = self.api.config.SFA_AGGREGATE_PORT url = 'http://%(address)s:%(port)s' % locals() local_aggregate = {'hrn': self.api.hrn, 'addr': address, 'port': port} - self.interfaces.append(local_aggregate) - connections[self.api.hrn] = xmlrpcprotocol.get_server(url, self.api.key_file, self.api.cert_file) - return connections + self.interfaces[self.api.hrn] = local_aggregate + # get connections + self.update(self.get_connections()) diff --git a/sfa/server/interface.py b/sfa/server/interface.py index b01c87e7..bbcebb0d 100644 --- a/sfa/server/interface.py +++ b/sfa/server/interface.py @@ -3,13 +3,13 @@ ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfa/server/interface.py $ # - from sfa.util.faults import * from sfa.util.storage import * from sfa.util.namespace import * from sfa.trust.gid import GID from sfa.util.table import SfaTable from sfa.util.record import SfaRecord +import traceback import sfa.util.xmlrpcprotocol as xmlrpcprotocol import sfa.util.soapprotocol as soapprotocol @@ -46,10 +46,9 @@ class Interfaces(dict): # defined by the class default_dict = {} - # allowed types - types = ['sa', 'ma'] + types = ['authority'] - def __init__(self, api, conf_file, type): + def __init__(self, api, conf_file, type='authority'): if type not in self.types: raise SfaInfaildArgument('Invalid type %s: must be in %s' % (type, self.types)) dict.__init__(self, {}) @@ -58,11 +57,13 @@ class Interfaces(dict): # load config file self.interface_info = XmlStorage(conf_file, self.default_dict) self.interface_info.load() - self.interfaces = self.interface_info.values()[0].values()[0] - if not isinstance(self.interfaces, list): - self.interfaces = [self.interfaces] - # get connections - self.update(self.get_connections(self.interfaces)) + interfaces = self.interface_info.values()[0].values()[0] + if not isinstance(interfaces, list): + interfaces = [self.interfaces] + self.interfaces = {} + for interface in interfaces: + self.interfaces[interface['hrn']] = interface + def sync_interfaces(self): """ @@ -75,62 +76,71 @@ class Interfaces(dict): # are any missing gids, request a new one from the peer registry. gids_current = self.api.auth.trusted_cert_list hrns_current = [gid.get_hrn() for gid in gids_current] - hrns_expected = [interface['hrn'] for interface in self.interfaces] + hrns_expected = self.interfaces.keys() new_hrns = set(hrns_expected).difference(hrns_current) - self.get_peer_gids(new_hrns) - + gids = self.get_peer_gids(new_hrns) # update the local db records for these registries - self.update_db_records(self.type) + self.update_db_records(self.type, gids) def get_peer_gids(self, new_hrns): """ Install trusted gids from the specified interfaces. """ + peer_gids = [] if not new_hrns: - return + return peer_gids trusted_certs_dir = self.api.config.get_trustedroots_dir() for new_hrn in new_hrns: + if not new_hrn: + continue # the gid for this interface should already be installed if new_hrn == self.api.config.SFA_INTERFACE_HRN: continue try: # get gid from the registry - interface = self.get_connections(self.interfaces[new_hrn])[new_hrn] + interface_info = self.interfaces[new_hrn] + interface = self[new_hrn] trusted_gids = interface.get_trusted_certs() - # default message - message = "interface: %s\tunable to install trusted gid for %s" % \ - (self.api.interface, new_hrn) if trusted_gids: # the gid we want shoudl be the first one in the list, # but lets make sure for trusted_gid in trusted_gids: + # default message + message = "interface: %s\t" % (self.api.interface) + message += "unable to install trusted gid for %s" % \ + (new_hrn) gid = GID(string=trusted_gids[0]) + peer_gids.append(gid) if gid.get_hrn() == new_hrn: gid_filename = os.path.join(trusted_certs_dir, '%s.gid' % new_hrn) gid.save_to_file(gid_filename, save_parents=True) message = "interface: %s\tinstalled trusted gid for %s" % \ (self.api.interface, new_hrn) - # log the message - self.api.logger.info(message) + # log the message + self.api.logger.info(message) except: message = "interface: %s\tunable to install trusted gid for %s" % \ (self.api.interface, new_hrn) self.api.logger.info(message) + traceback.print_exc() # reload the trusted certs list self.api.auth.load_trusted_certs() + return peer_gids - def update_db_records(self, type): + def update_db_records(self, type, gids): """ Make sure there is a record in the local db for allowed registries defined in the config file (registries.xml). Removes old records from the db. """ + if not gids: + return # get hrns we expect to find # ignore records for local interfaces ignore_interfaces = [self.api.config.SFA_INTERFACE_HRN] - hrns_expected = [interface['hrn'] for interface in self.interfaces \ - if interface['hrn'] not in ignore_interfaces] + hrns_expected = [gid.get_hrn() for gid in gids \ + if gid.get_hrn() not in ignore_interfaces] # get hrns that actually exist in the db table = SfaTable() @@ -143,29 +153,27 @@ class Interfaces(dict): table.remove(record) # add new records - for hrn in hrns_expected: + for gid in gids: + hrn = gid.get_hrn() if hrn not in hrns_found: 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) - - def get_connections(self, interfaces): + def get_connections(self): """ read connection details for the trusted peer registries from file return a dictionary of connections keyed on interface hrn. """ connections = {} required_fields = self.default_fields.keys() - if not isinstance(interfaces, list): - interfaces = [interfaces] - - for interface in interfaces: + for interface in self.interfaces.values(): # make sure the required fields are present and not null if not all([interface.get(key) for key in required_fields]): continue diff --git a/sfa/server/registry.py b/sfa/server/registry.py index 5658f37d..0b92f76e 100644 --- a/sfa/server/registry.py +++ b/sfa/server/registry.py @@ -37,19 +37,12 @@ class Registries(Interfaces): default_dict = {'registries': {'registry': [Interfaces.default_fields]}} def __init__(self, api, conf_file = "/etc/sfa/registries.xml"): - Interfaces.__init__(self, api, conf_file, 'sa') - - def get_connections(self, interfaces): - """ - read connection details for the trusted peer registries from file return - a dictionary of connections keyed on interface hrn. - """ - connections = Interfaces.get_connections(self, interfaces) - - # set up a connection to the local registry + Interfaces.__init__(self, api, conf_file) address = self.api.config.SFA_REGISTRY_HOST port = self.api.config.SFA_REGISTRY_PORT url = 'http://%(address)s:%(port)s' % locals() local_registry = {'hrn': self.api.hrn, 'addr': address, 'port': port} - connections[self.api.hrn] = xmlrpcprotocol.get_server(url, self.api.key_file, self.api.cert_file) - return connections + self.interfaces[self.api.hrn] = local_registry + + # get connections + self.update(self.get_connections()) diff --git a/sfa/server/sfa-ca.py b/sfa/server/sfa-ca.py new file mode 100755 index 00000000..c76b9857 --- /dev/null +++ b/sfa/server/sfa-ca.py @@ -0,0 +1,242 @@ +#!/usr/bin/python + +# +# SFA Certificate Signing and management +# + +import os +import sys +from optparse import OptionParser +from sfa.trust.certificate import Keypair, Certificate +from sfa.trust.gid import GID, create_uuid +from sfa.trust.hierarchy import Hierarchy +from sfa.util.config import Config +from collections import defaultdict + +def main(): + args = sys.argv + script_name = args[0] + parser = OptionParser(usage="%(script_name)s [options]" % locals()) + parser.add_option("-d", "--display", dest="display", default=None, + help="print contents of specified gid") + parser.add_option("-s", "--sign", dest="sign", default=None, + help="gid to sign" ) + parser.add_option("-k", "--key", dest="key", default=None, + help="keyfile to use for signing") + parser.add_option("-a", "--authority", dest="authority", default=None, + help="sign the gid using the specified authority ") + parser.add_option("-i", "--import", dest="importgid", default=None, + help="gid file to import into the registry") + parser.add_option("-e", "--export", dest="export", + help="name of gid to export from registry") + parser.add_option("-o", "--outfile", dest="outfile", + help="where to write the exprted gid") + parser.add_option("-v", "--verbose", dest="verbose", default=False, + action="store_true", help="be verbose") + + (options, args) = parser.parse_args() + + + if options.display: + display(options) + elif options.sign: + sign(options) + elif options.importgid: + import_gid(options) + elif options.export: + export_gid(options) + else: + parser.print_help() + sys.exit(1) + + +def display(options): + """ + Display the sepcified GID + """ + gidfile = os.path.abspath(options.display) + if not gidfile or not os.path.isfile(gidfile): + print "No such gid: %s" % gidfile + sys.exit(1) + gid = GID(filename=gidfile) + gid.dump(dump_parents=True) + +def sign_gid(gid, parent_key, parent_gid): + gid.set_issuer(parent_key, parent_gid.get_hrn()) + gid.set_parent(parent_gid) + gid.sign() + return gid + +def sign(options): + """ + Sign the specified gid + """ + hierarchy = Hierarchy() + config = Config() + default_authority = config.SFA_INTERFACE_HRN + auth_info = hierarchy.get_auth_info(default_authority) + + # load the gid + gidfile = os.path.abspath(options.sign) + if not os.path.isfile(gidfile): + print "no such gid: %s" % gidfile + sys.exit(1) + gid = GID(filename=gidfile) + + # remove previous parent + gid = GID(string=gid.save_to_string(save_parents=False)) + + # load the parent private info + authority = options.authority + # if no pkey was specified, then use the this authority's key + if not authority: + authority = default_authority + + if not hierarchy.auth_exists(authority): + print "no such authority: %s" % authority + + # load the parent gid and key + auth_info = hierarchy.get_auth_info(authority) + pkeyfile = auth_info.privkey_filename + parent_key = Keypair(filename=pkeyfile) + parent_gid = auth_info.gid_object + + # get the outfile + outfile = options.outfile + if not outfile: + outfile = os.path.abspath('./signed-%s.gid' % gid.get_hrn()) + + # check if gid already has a parent + + # sign the gid + if options.verbose: + print "Signing %s gid with parent %s" % \ + (gid.get_hrn(), parent_gid.get_hrn()) + gid = sign_gid(gid, parent_key, parent_gid) + # save the signed gid + if options.verbose: + print "Writing signed gid %s" % outfile + gid.save_to_file(outfile, save_parents=True) + + +def export_gid(options): + from sfa.util.table import SfaTable + # lookup the record for the specified hrn + hrn = options.export + + # check sfa table first + table = SfaTable() + records = table.find({'hrn': hrn, type: 'authority'}) + 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) + +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) + + # re-sign all existing gids signed by this authority + # create a dictionary of records keyed on the record's authority + record_dict = defaultdict(list) + # only get regords that belong to this authority + # or any of its sub authorities + child_records = table.find({'hrn': '%s*' % gid.get_hrn()}) + if not child_records: + return + + for record in child_records: + record_dict[record['authority']].append(record) + + # start with the authority we just imported + authorities = [gid.get_hrn()] + while authorities: + next_authorities = [] + for authority in authorities: + # create a new signed gid for each record at this authority + # and update the registry + auth_info = hierarchy.get_auth_info(authority) + records = record_dict[authority] + for record in records: + record_gid = GID(string=record['gid']) + parent_pkey = Keypair(filename=auth_info.privkey_filename) + parent_gid = GID(filename=auth_info.gid_filename) + if options.verbose: + print "re-signing %s gid with parent %s" % \ + (record['hrn'], parent_gid.get_hrn()) + signed_gid = sign_gid(record_gid, parent_pkey, parent_gid) + record['gid'] = signed_gid.save_to_string(save_parents=True) + table.update(record) + + # if this is an authority then update the hierarchy + if record['type'] == 'authority': + record_info = hierarchy.get_auth_info(record['hrn']) + if options.verbose: + print "Writing %s gid to %s" % (record['hrn'], record_info.gid_filename) + signed_gid.save_to_file(filename=record_info.gid_filename, save_parents=True) + + # update list of next authorities + tmp_authorities = set([record['hrn'] for record in records \ + if record['type'] == 'authority']) + next_authorities.extend(tmp_authorities) + + # move on to next set of authorities + authorities = next_authorities + +if __name__ == '__main__': + main() diff --git a/sfa/server/sfa-server.py b/sfa/server/sfa-server.py index db78d5c8..06393ce4 100755 --- a/sfa/server/sfa-server.py +++ b/sfa/server/sfa-server.py @@ -157,12 +157,12 @@ def init_server(options, config): manager.init_server() -def sync_interfaces(): +def sync_interfaces(server_key_file, server_cert_file): """ Attempt to install missing trusted gids and db records for our federated interfaces """ - api = SfaAPI() + api = SfaAPI(key_file = server_key_file, cert_file = server_cert_file) registries = Registries(api) aggregates = Aggregates(api) registries.sync_interfaces() @@ -194,7 +194,6 @@ def main(): help="Run as daemon.", default=False) (options, args) = parser.parse_args() - if (options.daemon): daemon() config = Config() hierarchy = Hierarchy() @@ -203,8 +202,9 @@ def main(): init_server_key(server_key_file, server_cert_file, config, hierarchy) init_server(options, config) - sync_interfaces() + sync_interfaces(server_key_file, server_cert_file) + if (options.daemon): daemon() # start registry server if (options.registry): from sfa.server.registry import Registry diff --git a/sfa/trust/certificate.py b/sfa/trust/certificate.py index 441acaea..b82e256f 100644 --- a/sfa/trust/certificate.py +++ b/sfa/trust/certificate.py @@ -361,7 +361,7 @@ class Certificate: self.issuerReq = req if cert: # if a cert was supplied, then get the subject from the cert - subject = cert.cert.get_issuer() + subject = cert.cert.get_subject() assert(subject) self.issuerSubject = subject diff --git a/sfa/trust/gid.py b/sfa/trust/gid.py index e51b3288..db2cb44e 100644 --- a/sfa/trust/gid.py +++ b/sfa/trust/gid.py @@ -163,7 +163,7 @@ class GID(Certificate): if self.parent and dump_parents: print " "*indent, "parent:" - self.parent.dump(indent+4) + self.parent.dump(indent+4, dump_parents) ## # Verify the chain of authenticity of the GID. First perform the checks diff --git a/sfa/util/record.py b/sfa/util/record.py index f9eaa090..6af31197 100644 --- a/sfa/util/record.py +++ b/sfa/util/record.py @@ -355,7 +355,7 @@ class UserRecord(SfaRecord): 'first_name': Parameter(str, 'First name'), 'last_name': Parameter(str, 'Last name'), 'phone': Parameter(str, 'Phone Number'), - 'key': Parameter(str, 'Public key'), + 'keys': Parameter(str, 'Public key'), 'slices': Parameter([str], 'List of slices this user belongs to'), } fields.update(SfaRecord.fields) diff --git a/sfa/util/table.py b/sfa/util/table.py index 892b72cb..6c68776d 100644 --- a/sfa/util/table.py +++ b/sfa/util/table.py @@ -88,16 +88,17 @@ class SfaTable(list): self.db.commit() def remove(self, record): - query_str = "DELETE FROM %s WHERE record_id = %s" % \ - (self.tablename, record['record_id']) - self.db.do(query_str) + params = {'record_id': record['record_id']} + template = "DELETE FROM %s " % self.tablename + sql = template + "WHERE record_id = %(record_id)s" + self.db.do(sql, params) # if this is a site, remove all records where 'authority' == the # site's hrn if record['type'] == 'authority': - sql = " DELETE FROM %s WHERE authority = %s" % \ - (self.tablename, record['hrn']) - self.db.do(sql) + params = {'authority': record['hrn']} + sql = template + "WHERE authority = %(authority)s" + self.db.do(sql, params) self.db.commit() def insert(self, record):