#!/usr/bin/python from __future__ import print_function import sys import os import tempfile from optparse import OptionParser from sfa.util.faults import ConnectionKeyGIDMismatch from sfa.util.config import Config from sfa.trust.certificate import Keypair, Certificate from sfa.trust.credential import Credential from sfa.trust.gid import GID from sfa.trust.hierarchy import Hierarchy from sfa.client.sfaserverproxy import SfaServerProxy from sfa.planetlab.plxrn import hrn_to_pl_slicename, slicename_to_hrn KEYDIR = "/var/lib/sfa/" CONFDIR = "/etc/sfa/" def handle_gid_mismatch_exception(f): def wrapper(*args, **kwds): try: return f(*args, **kwds) except ConnectionKeyGIDMismatch: # clean regen server keypair and try again print("cleaning keys and trying again") clean_key_cred() return f(args, kwds) return wrapper def server_proxy(url=None, port=None, keyfile=None, certfile=None, verbose=False): """ returns an xmlrpc connection to the service a the specified address """ if url: url_parts = url.split(":") if len(url_parts) > 1: pass else: url = "http://%(url)s:%(port)s" % locals() else: # connect to registry by default config = Config() addr, port = config.SFA_REGISTRY_HOST, config.SFA_REGISTRY_PORT url = "http://%(addr)s:%(port)s" % locals() if verbose: print("Contacting registry at: %(url)s" % locals()) server = SfaServerProxy(url, keyfile, certfile) return server def create_default_dirs(): config = Config() hierarchy = Hierarchy() config_dir = config.config_path trusted_certs_dir = config.get_trustedroots_dir() authorities_dir = hierarchy.basedir all_dirs = [config_dir, trusted_certs_dir, authorities_dir] for dir in all_dirs: if not os.path.exists(dir): os.makedirs(dir) def has_node_key(): key_file = KEYDIR + os.sep + 'server.key' return os.path.exists(key_file) def clean_key_cred(): """ remove the existing keypair and cred and generate new ones """ files = ["server.key", "server.cert", "node.cred"] for f in files: filepath = KEYDIR + os.sep + f if os.path.isfile(filepath): os.unlink(f) # install the new key pair # GetCredential will take care of generating the new keypair # and credential GetCredential() def get_node_key(registry=None, verbose=False): # this call requires no authentication, # so we can generate a random keypair here subject = "component" (kfd, keyfile) = tempfile.mkstemp() (cfd, certfile) = tempfile.mkstemp() key = Keypair(create=True) key.save_to_file(keyfile) cert = Certificate(subject=subject) cert.set_issuer(key=key, subject=subject) cert.set_pubkey(key) cert.sign() cert.save_to_file(certfile) registry = server_proxy(url=registry, keyfile=keyfile, certfile=certfile) registry.get_key_from_incoming_ip() def create_server_keypair(keyfile=None, certfile=None, hrn="component", verbose=False): """ create the server key/cert pair in the right place """ key = Keypair(filename=keyfile) key.save_to_file(keyfile) cert = Certificate(subject=hrn) cert.set_issuer(key=key, subject=hrn) cert.set_pubkey(key) cert.sign() cert.save_to_file(certfile, save_parents=True) @handle_gid_mismatch_exception def GetCredential(registry=None, force=False, verbose=False): config = Config() hierarchy = Hierarchy() key_dir = hierarchy.basedir data_dir = config.data_path config_dir = config.config_path credfile = data_dir + os.sep + 'node.cred' # check for existing credential if not force and os.path.exists(credfile): if verbose: print("Loading Credential from %(credfile)s " % locals()) cred = Credential(filename=credfile).save_to_string(save_parents=True) else: if verbose: print("Getting credential from registry") # make sure node private key exists node_pkey_file = config_dir + os.sep + "node.key" node_gid_file = config_dir + os.sep + "node.gid" if not os.path.exists(node_pkey_file) or \ not os.path.exists(node_gid_file): get_node_key(registry=registry, verbose=verbose) gid = GID(filename=node_gid_file) hrn = gid.get_hrn() # create server key and certificate keyfile = data_dir + os.sep + "server.key" certfile = data_dir + os.sep + "server.cert" key = Keypair(filename=node_pkey_file) key.save_to_file(keyfile) create_server_keypair(keyfile, certfile, hrn, verbose) # get credential from registry registry = server_proxy( url=registry, keyfile=keyfile, certfile=certfile) cert = Certificate(filename=certfile) cert_str = cert.save_to_string(save_parents=True) cred = registry.GetSelfCredential(cert_str, 'node', hrn) Credential(string=cred).save_to_file(credfile, save_parents=True) return cred @handle_gid_mismatch_exception def get_trusted_certs(registry=None, verbose=False): """ refresh our list of trusted certs. """ # define useful variables config = Config() data_dir = config.SFA_DATA_DIR config_dir = config.SFA_CONFIG_DIR trusted_certs_dir = config.get_trustedroots_dir() keyfile = data_dir + os.sep + "server.key" certfile = data_dir + os.sep + "server.cert" node_gid_file = config_dir + os.sep + "node.gid" node_gid = GID(filename=node_gid_file) hrn = node_gid.get_hrn() # get credential cred = GetCredential(registry=registry, verbose=verbose) # make sure server key cert pair exists create_server_keypair( keyfile=keyfile, certfile=certfile, hrn=hrn, verbose=verbose) registry = server_proxy(url=registry, keyfile=keyfile, certfile=certfile) # get the trusted certs and save them in the right place if verbose: print("Getting trusted certs from registry") trusted_certs = registry.get_trusted_certs(cred) trusted_gid_names = [] for gid_str in trusted_certs: gid = GID(string=gid_str) gid.decode() relative_filename = gid.get_hrn() + ".gid" trusted_gid_names.append(relative_filename) gid_filename = trusted_certs_dir + os.sep + relative_filename if verbose: print("Writing GID for %s as %s" % (gid.get_hrn(), gid_filename)) gid.save_to_file(gid_filename, save_parents=True) # remove old certs all_gids_names = os.listdir(trusted_certs_dir) for gid_name in all_gids_names: if gid_name not in trusted_gid_names: if verbose: print("Removing old gid ", gid_name) os.unlink(trusted_certs_dir + os.sep + gid_name) @handle_gid_mismatch_exception def get_gids(registry=None, verbose=False): """ Get the gid for all instantiated slices on this node and store it in /etc/sfa/slice.gid in the slice's filesystem """ # define useful variables config = Config() data_dir = config.data_path config_dir = config.SFA_CONFIG_DIR trusted_certs_dir = config.get_trustedroots_dir() keyfile = data_dir + os.sep + "server.key" certfile = data_dir + os.sep + "server.cert" node_gid_file = config_dir + os.sep + "node.gid" node_gid = GID(filename=node_gid_file) hrn = node_gid.get_hrn() interface_hrn = config.SFA_INTERFACE_HRN # get credential cred = GetCredential(registry=registry, verbose=verbose) # make sure server key cert pair exists create_server_keypair( keyfile=keyfile, certfile=certfile, hrn=hrn, verbose=verbose) registry = server_proxy(url=registry, keyfile=keyfile, certfile=certfile) if verbose: print("Getting current slices on this node") # get a list of slices on this node from sfa.generic import Generic generic = Generic.the_flavour() api = generic.make_api(interface='component') xids_tuple = api.driver.nodemanager.GetXIDs() slices = eval(xids_tuple[1]) slicenames = slices.keys() # generate a list of slices that dont have gids installed slices_without_gids = [] for slicename in slicenames: if not os.path.isfile("/vservers/%s/etc/slice.gid" % slicename) \ or not os.path.isfile("/vservers/%s/etc/node.gid" % slicename): slices_without_gids.append(slicename) # convert slicenames to hrns hrns = [slicename_to_hrn(interface_hrn, slicename) for slicename in slices_without_gids] # exit if there are no gids to install if not hrns: return if verbose: print("Getting gids for slices on this node from registry") # get the gids # and save them in the right palce records = registry.GetGids(hrns, cred) for record in records: # if this isnt a slice record skip it if not record['type'] == 'slice': continue slicename = hrn_to_pl_slicename(record['hrn']) # if this slice isnt really instatiated skip it if not os.path.exists("/vservers/%(slicename)s" % locals()): continue # save the slice gid in /etc/sfa/ in the vservers filesystem vserver_path = "/vservers/%(slicename)s" % locals() gid = record['gid'] slice_gid_filename = os.sep.join([vserver_path, "etc", "slice.gid"]) if verbose: print("Saving GID for %(slicename)s as %(slice_gid_filename)s" % locals()) GID(string=gid).save_to_file(slice_gid_filename, save_parents=True) # save the node gid in /etc/sfa node_gid_filename = os.sep.join([vserver_path, "etc", "node.gid"]) if verbose: print("Saving node GID for %(slicename)s as %(node_gid_filename)s" % locals()) node_gid.save_to_file(node_gid_filename, save_parents=True) def dispatch(options, args): create_default_dirs() if options.key: if options.verbose: print("Getting the component's pkey") get_node_key(registry=options.registry, verbose=options.verbose) if options.certs: if options.verbose: print("Getting the component's trusted certs") get_trusted_certs(verbose=options.verbose) if options.gids: if options.verbose: print("Geting the component's GIDs") get_gids(verbose=options.verbose) def main(): args = sys.argv prog_name = args[0] parser = OptionParser(usage="%(prog_name)s [options]" % locals()) parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="Be verbose") parser.add_option("-r", "--registry", dest="registry", default=None, help="Url of registry to contact") parser.add_option("-k", "--key", dest="key", action="store_true", default=False, help="Get the node's pkey from the registry") parser.add_option("-c", "--certs", dest="certs", action="store_true", default=False, help="Get the trusted certs from the registry") parser.add_option("-g", "--gids", dest="gids", action="store_true", default=False, help="Get gids for all the slices on the component") (options, args) = parser.parse_args() dispatch(options, args) if __name__ == '__main__': main()