def do_POST(self): """Handles the HTTPS POST request. It was copied out from SimpleXMLRPCServer.py and modified to shutdown the socket cleanly. """ try: peer_cert = Certificate() peer_cert.load_from_pyopenssl_x509(self.connection.get_peer_certificate()) generic=Generic.the_flavour() self.api = generic.make_api (peer_cert = peer_cert, interface = self.server.interface, key_file = self.server.key_file, cert_file = self.server.cert_file, cache = self.cache) #logger.info("SecureXMLRpcRequestHandler.do_POST:") #logger.info("interface=%s"%self.server.interface) #logger.info("key_file=%s"%self.server.key_file) #logger.info("api=%s"%self.api) #logger.info("server=%s"%self.server) #logger.info("handler=%s"%self) # get arguments request = self.rfile.read(int(self.headers["content-length"])) remote_addr = (remote_ip, remote_port) = self.connection.getpeername() self.api.remote_addr = remote_addr response = self.api.handle(remote_addr, request, self.server.method_map) except Exception, fault: # This should only happen if the module is buggy # internal error, report as HTTP server error logger.log_exc("server.do_POST") response = self.api.prepare_response(fault)
def GetSelfCredential(certificate, xnr, type): if type: hrn = urn_to_hrn(xrn)[0] else: hrn, type = urn_to_hrn(xrn) origin_hrn = Certificate(string=cert).get_subject() ### authenticate the gid # import here so we can load this module at build-time for sfa2wsdl #from sfa.storage.alchemy import dbsession from sfa.storage.model import RegRecord # xxx-local - the current code runs Resolve, which would forward to # another registry if needed # I wonder if this is truly the intention, or shouldn't we instead # only look in the local db ? records = self.api.manager.Resolve(self.api, xrn, type, details=False) if not records: raise RecordNotFound(hrn) record_obj = RegRecord (dict=records[0]) # xxx-local the local-only version would read #record_obj = dbsession.query(RegRecord).filter_by(hrn=hrn).first() #if not record_obj: raise RecordNotFound(hrn) gid = record_obj.get_gid_object() gid_str = gid.save_to_string(save_parents=True) self.api.auth.authenticateGid(gid_str, [cert, type, hrn]) # authenticate the certificate against the gid in the db certificate = Certificate(string=cert) if not certificate.is_pubkey(gid.get_pubkey()): for (obj,name) in [ (certificate,"CERT"), (gid,"GID"), ]: if hasattr (obj,'filename'): raise ConnectionKeyGIDMismatch(gid.get_subject()) return self.api.manager.GetCredential(self.api, xrn, type)
def do_POST(self): """Handles the HTTPS POST request. It was copied out from SimpleXMLRPCServer.py and modified to shutdown the socket cleanly. """ try: peer_cert = Certificate() peer_cert.load_from_pyopenssl_x509( self.connection.get_peer_certificate()) generic = Generic.the_flavour() self.api = generic.make_api(peer_cert=peer_cert, interface=self.server.interface, key_file=self.server.key_file, cert_file=self.server.cert_file, cache=self.cache) #logger.info("SecureXMLRpcRequestHandler.do_POST:") #logger.info("interface=%s"%self.server.interface) #logger.info("key_file=%s"%self.server.key_file) #logger.info("api=%s"%self.api) #logger.info("server=%s"%self.server) #logger.info("handler=%s"%self) # get arguments request = self.rfile.read(int(self.headers["content-length"])) remote_addr = (remote_ip, remote_port) = self.connection.getpeername() self.api.remote_addr = remote_addr response = self.api.handle(remote_addr, request, self.server.method_map) except Exception, fault: # This should only happen if the module is buggy # internal error, report as HTTP server error logger.log_exc("server.do_POST") response = self.api.prepare_response(fault)
def __init__(self, create=False, subject=None, string=None, filename=None, uuid=None, hrn=None, urn=None, lifeDays=1825, email=None): self.uuid = None self.hrn = None self.urn = None self.email = None # for adding to the SubjectAltName Certificate.__init__(self, lifeDays, create, subject, string, filename) if subject: logger.debug("Creating GID for subject: %s" % subject) if uuid: self.uuid = int(uuid) if hrn: self.hrn = hrn self.urn = hrn_to_urn(hrn, 'unknown') if urn: self.urn = urn self.hrn, type = urn_to_hrn(urn) if email: self.set_email(email)
def call(self, cert, xrn, type): """ GetSelfCredential a degenerate version of GetCredential used by a client to get his initial credential when de doesnt have one. This is the same as GetCredential(..., cred = None, ...) The registry ensures that the client is the principal that is named by (type, name) by comparing the public key in the record's GID to the private key used to encrypt the client side of the HTTPS connection. Thus it is impossible for one principal to retrieve another principal's credential without having the appropriate private key. @param type type of object (user | slice | sa | ma | node) @param hrn human readable name of authority to list @return string representation of a credential object """ if type: hrn = urn_to_hrn(xrn)[0] else: hrn, type = urn_to_hrn(xrn) self.api.auth.verify_object_belongs_to_me(hrn) origin_hrn = Certificate(string=cert).get_subject() self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, hrn, self.name)) ### authenticate the gid # import here so we can load this module at build-time for sfa2wsdl #from sfa.storage.alchemy import dbsession from sfa.storage.model import RegRecord # xxx-local - the current code runs Resolve, which would forward to # another registry if needed # I wonder if this is truly the intention, or shouldn't we instead # only look in the local db ? records = self.api.manager.Resolve(self.api, xrn, type, details=False) if not records: raise RecordNotFound(hrn) record_obj = RegRecord (dict=records[0]) # xxx-local the local-only version would read #record_obj = dbsession.query(RegRecord).filter_by(hrn=hrn).first() #if not record_obj: raise RecordNotFound(hrn) gid = record_obj.get_gid_object() gid_str = gid.save_to_string(save_parents=True) self.api.auth.authenticateGid(gid_str, [cert, type, hrn]) # authenticate the certificate against the gid in the db certificate = Certificate(string=cert) if not certificate.is_pubkey(gid.get_pubkey()): for (obj,name) in [ (certificate,"CERT"), (gid,"GID"), ]: self.api.logger.debug("ConnectionKeyGIDMismatch, %s pubkey: %s"%(name,obj.get_pubkey().get_pubkey_string())) self.api.logger.debug("ConnectionKeyGIDMismatch, %s dump: %s"%(name,obj.dump_string())) if hasattr (obj,'filename'): self.api.logger.debug("ConnectionKeyGIDMismatch, %s filename: %s"%(name,obj.filename)) raise ConnectionKeyGIDMismatch(gid.get_subject()) return self.api.manager.GetCredential(self.api, xrn, type)
def get_cert_file(self, key_file): cert_file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert") if (os.path.isfile(cert_file)): # we'd perfer to use Registry issued certs instead of self signed certs. # if this is a Registry cert (GID) then we are done gid = GID(filename=cert_file) if gid.get_urn(): return cert_file # generate self signed certificate k = Keypair(filename=key_file) cert = Certificate(subject=self.user) cert.set_pubkey(k) cert.set_issuer(k, self.user) cert.sign() self.logger.info("Writing self-signed certificate to %s"%cert_file) cert.save_to_file(cert_file) self.cert = cert # try to get registry issued cert try: self.logger.info("Getting Registry issued cert") self.read_config() # *hack. need to set registyr before _get_gid() is called self.registry = xmlrpcprotocol.get_server(self.reg_url, key_file, cert_file, timeout=self.options.timeout, verbose=self.options.debug) gid = self._get_gid(type='user') self.registry = None self.logger.info("Writing certificate to %s"%cert_file) gid.save_to_file(cert_file) except: self.logger.info("Failed to download Registry issued cert") return cert_file
def get_trusted_certs(self, opts, args): """ return uhe trusted certs at this interface """ trusted_certs = self.registry.get_trusted_certs() for trusted_cert in trusted_certs: gid = GID(string=trusted_cert) gid.dump() cert = Certificate(string=trusted_cert) self.logger.debug('Sfi.get_trusted_certs -> %r'%cert.get_subject()) return
def CreateGid(self, api, xrn, cert): # get the authority authority = Xrn(xrn=xrn).get_authority_hrn() auth_info = api.auth.get_auth_info(authority) if not cert: pkey = Keypair(create=True) else: certificate = Certificate(string=cert) pkey = certificate.get_pubkey() gid = api.auth.hierarchy.create_gid(xrn, create_uuid(), pkey) return gid.save_to_string(save_parents=True)
def init_self_signed_cert(hrn, key, server_cert_file): logger.debug("generating self signed cert") # generate self signed certificate cert = Certificate(subject=hrn) cert.set_issuer(key=key, subject=hrn) cert.set_pubkey(key) cert.sign() cert.save_to_file(server_cert_file)
def self_signed_cert_produce(self, output): self.assert_private_key() private_key_filename = self.private_key_filename() keypair = Keypair(filename=private_key_filename) self_signed = Certificate(subject=self.hrn) self_signed.set_pubkey(keypair) self_signed.set_issuer(keypair, self.hrn) self_signed.sign() self_signed.save_to_file(output) #self.logger.debug("SfaClientBootstrap: Created self-signed certificate for %s in %s"%\ #(self.hrn,output)) return output
def testSetData(self): cert = Certificate(subject="test") data = "this is a test" cert.set_data(data) self.assertEqual(cert.get_data(), data) # try something a bit more complicated, like an xmlrpc encoding of # some parameters cert = Certificate(subject="test") data = xmlrpclib.dumps((1, "foo", ["a", "b"], {"c": "d", "e": "f"}, True)) cert.set_data(data) self.assertEqual(cert.get_data(), data)
def __init__(self, create=False, subject=None, string=None, filename=None, uuid=None, hrn=None, urn=None): Certificate.__init__(self, create, subject, string, filename) if subject: logger.debug("Creating GID for subject: %s" % subject) if uuid: self.uuid = int(uuid) if hrn: self.hrn = hrn self.urn = hrn_to_urn(hrn, 'unknown') if urn: self.urn = urn self.hrn, type = urn_to_hrn(urn)
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)
def self_signed_cert_produce (self,output): self.assert_private_key() private_key_filename = self.private_key_filename() keypair=Keypair(filename=private_key_filename) self_signed = Certificate (subject = self.hrn) self_signed.set_pubkey (keypair) self_signed.set_issuer (keypair, self.hrn) self_signed.sign () self_signed.save_to_file (output) self.logger.debug("SfaClientBootstrap: Created self-signed certificate for %s in %s"%\ (self.hrn,output)) return output
def __init__ (self, encoding="utf-8", methods='sfa.methods', config = "/etc/sfa/sfa_config", peer_cert = None, interface = None, key_file = None, cert_file = None, cache = None): XmlrpcApi.__init__ (self, encoding) # we may be just be documenting the API if config is None: return # Load configuration self.config = Config(config) self.credential = None self.auth = Auth(peer_cert) self.interface = interface self.hrn = self.config.SFA_INTERFACE_HRN self.key_file = key_file self.key = Keypair(filename=self.key_file) self.cert_file = cert_file self.cert = Certificate(filename=self.cert_file) self.cache = cache if self.cache is None: self.cache = Cache() # load registries from sfa.server.registry import Registries self.registries = Registries() # load aggregates from sfa.server.aggregate import Aggregates self.aggregates = Aggregates() # filled later on by generic/Generic self.manager=None self._dbsession=None
def __init__(self, config = "/etc/sfa/sfa_config.py", encoding = "utf-8", methods='sfa.methods', peer_cert = None, interface = None, key_file = None, cert_file = None, cache = None): BaseAPI.__init__(self, config=config, encoding=encoding, methods=methods, \ peer_cert=peer_cert, interface=interface, key_file=key_file, \ cert_file=cert_file, cache=cache) self.encoding = encoding from sfa.util.table import SfaTable self.SfaTable = SfaTable # Better just be documenting the API if config is None: return # Load configuration self.config = Config(config) self.auth = Auth(peer_cert) self.interface = interface self.key_file = key_file self.key = Keypair(filename=self.key_file) self.cert_file = cert_file self.cert = Certificate(filename=self.cert_file) 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' 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"
def verify_chain(self, trusted_certs = None): # do the normal certificate verification stuff trusted_root = Certificate.verify_chain(self, trusted_certs) if self.parent: # make sure the parent's hrn is a prefix of the child's hrn if not hrn_authfor_hrn(self.parent.get_hrn(), self.get_hrn()): raise GidParentHrn("This cert HRN %s isn't in the namespace for parent HRN %s" % (self.get_hrn(), self.parent.get_hrn())) # Parent must also be an authority (of some type) to sign a GID # There are multiple types of authority - accept them all here if not self.parent.get_type().find('authority') == 0: raise GidInvalidParentHrn("This cert %s's parent %s is not an authority (is a %s)" % (self.get_hrn(), self.parent.get_hrn(), self.parent.get_type())) # Then recurse up the chain - ensure the parent is a trusted # root or is in the namespace of a trusted root self.parent.verify_chain(trusted_certs) else: # make sure that the trusted root's hrn is a prefix of the child's trusted_gid = GID(string=trusted_root.save_to_string()) trusted_type = trusted_gid.get_type() trusted_hrn = trusted_gid.get_hrn() #if trusted_type == 'authority': # trusted_hrn = trusted_hrn[:trusted_hrn.rindex('.')] cur_hrn = self.get_hrn() if not hrn_authfor_hrn(trusted_hrn, cur_hrn): raise GidParentHrn("Trusted root with HRN %s isn't a namespace authority for this cert %s" % (trusted_hrn, cur_hrn)) # There are multiple types of authority - accept them all here if not trusted_type.find('authority') == 0: raise GidInvalidParentHrn("This cert %s's trusted root signer %s is not an authority (is a %s)" % (self.get_hrn(), trusted_hrn, trusted_type)) return
def determine_sfa_filekind(fn): if fn.endswith('.gid'): return 'gid' elif fn.endswith('.cert'): return 'certificate' elif fn.endswith('cred'): return 'credential' try: cred=Credential(filename=fn) return 'credential' except: pass try: gid=GID(filename=fn) if gid.uuid: return 'gid' except: pass try: cert = Certificate(filename = fn) return 'certificate' except: pass # to be completed # if "gidCaller" in dict: # return "credential" # # if "uuid" in dict: # return "gid" return "unknown"
def verify_chain(self, trusted_certs = None): # do the normal certificate verification stuff trusted_root = Certificate.verify_chain(self, trusted_certs) if self.parent: # make sure the parent's hrn is a prefix of the child's hrn if not hrn_authfor_hrn(self.parent.get_hrn(), self.get_hrn()): raise GidParentHrn("This cert HRN %s isn't in the namespace for parent HRN %s" % (self.get_hrn(), self.parent.get_hrn())) # Parent must also be an authority (of some type) to sign a GID # There are multiple types of authority - accept them all here if not self.parent.get_type().find('authority') == 0: raise GidInvalidParentHrn("This cert %s's parent %s is not an authority (is a %s)" % (self.get_hrn(), self.parent.get_hrn(), self.parent.get_type())) # Then recurse up the chain - ensure the parent is a trusted # root or is in the namespace of a trusted root self.parent.verify_chain(trusted_certs) else: # make sure that the trusted root's hrn is a prefix of the child's trusted_gid = GID(string=trusted_root.save_to_string()) trusted_type = trusted_gid.get_type() trusted_hrn = trusted_gid.get_hrn() #if trusted_type == 'authority': # trusted_hrn = trusted_hrn[:trusted_hrn.rindex('.')] cur_hrn = self.get_hrn() if not hrn_authfor_hrn(trusted_hrn, cur_hrn): raise GidParentHrn("Trusted root with HRN %s isn't a namespace authority for this cert: %s" % (trusted_hrn, cur_hrn)) # There are multiple types of authority - accept them all here if not trusted_type.find('authority') == 0: raise GidInvalidParentHrn("This cert %s's trusted root signer %s is not an authority (is a %s)" % (self.get_hrn(), trusted_hrn, trusted_type)) return
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 get_node_key(self): # 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 = self.get_registry() # the registry will scp the key onto the node registry.get_key_from_incoming_ip()
def getCredential(self): """ Get our credential from a remote registry """ path = self.config.SFA_DATA_DIR config_dir = self.config.config_path cred_filename = path + os.sep + 'node.cred' try: credential = Credential(filename=cred_filename) return credential.save_to_string(save_parents=True) except IOError: node_pkey_file = config_dir + os.sep + "node.key" node_gid_file = config_dir + os.sep + "node.gid" cert_filename = path + os.sep + 'server.cert' if not os.path.exists(node_pkey_file) or \ not os.path.exists(node_gid_file): self.get_node_key() # get node's hrn gid = GID(filename=node_gid_file) hrn = gid.get_hrn() # get credential from registry 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
def call(self, cert, xrn, type): """ GetSelfCredential a degenerate version of GetCredential used by a client to get his initial credential when de doesnt have one. This is the same as GetCredential(..., cred = None, ...) The registry ensures that the client is the principal that is named by (type, name) by comparing the public key in the record's GID to the private key used to encrypt the client side of the HTTPS connection. Thus it is impossible for one principal to retrieve another principal's credential without having the appropriate private key. @param type type of object (user | slice | sa | ma | node) @param hrn human readable name of authority to list @return string representation of a credential object """ if type: hrn = urn_to_hrn(xrn)[0] else: hrn, type = urn_to_hrn(xrn) self.api.auth.verify_object_belongs_to_me(hrn) origin_hrn = Certificate(string=cert).get_subject() self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, hrn, self.name)) manager = self.api.get_interface_manager() # authenticate the gid records = manager.resolve(self.api, xrn, type) if not records: raise RecordNotFound(hrn) record = SfaRecord(dict=records[0]) gid = record.get_gid_object() gid_str = gid.save_to_string(save_parents=True) self.api.auth.authenticateGid(gid_str, [cert, type, hrn]) # authenticate the certificate against the gid in the db certificate = Certificate(string=cert) if not certificate.is_pubkey(gid.get_pubkey()): for (obj,name) in [ (certificate,"CERT"), (gid,"GID"), ]: self.api.logger.debug("ConnectionKeyGIDMismatch, %s pubkey: %s"%(name,obj.get_pubkey().get_pubkey_string())) self.api.logger.debug("ConnectionKeyGIDMismatch, %s dump: %s"%(name,obj.dump_string())) if hasattr (obj,'filename'): self.api.logger.debug("ConnectionKeyGIDMismatch, %s filename: %s"%(name,obj.filename)) raise ConnectionKeyGIDMismatch(gid.get_subject()) return manager.get_credential(self.api, xrn, type, is_self=True)
def verify_chain(self, trusted_certs = None): # do the normal certificate verification stuff Certificate.verify_chain(self, trusted_certs) if self.parent: # make sure the parent delegated rights to the child if not self.parent.get_delegate(): raise MissingDelegateBit(self.parent.get_subject()) # make sure the rights given to the child are a subset of the # parents rights if not self.parent.get_privileges().is_superset(self.get_privileges()): raise ChildRightsNotSubsetOfParent(self.get_subject() + " " + self.parent.get_privileges().save_to_string() + " " + self.get_privileges().save_to_string()) return
def verify_chain(self, trusted_certs=None): # do the normal certificate verification stuff Certificate.verify_chain(self, trusted_certs) if self.parent: # make sure the parent delegated rights to the child if not self.parent.get_delegate(): raise MissingDelegateBit(self.parent.get_subject()) # make sure the rights given to the child are a subset of the # parents rights if not self.parent.get_privileges().is_superset( self.get_privileges()): raise ChildRightsNotSubsetOfParent( self.get_subject() + " " + self.parent.get_privileges().save_to_string() + " " + self.get_privileges().save_to_string()) return
def CreateGid(self, api, xrn, cert): # get the authority authority = Xrn(xrn=xrn).get_authority_hrn() auth_info = api.auth.get_auth_info(authority) if not cert: pkey = Keypair(create=True) else: certificate = Certificate(string=cert) pkey = certificate.get_pubkey() # Add the email of the user to SubjectAltName in the GID email = None hrn = Xrn(xrn).get_hrn() dbsession=api.dbsession() record=dbsession.query(RegUser).filter_by(hrn=hrn).first() if record: email=getattr(record,'email',None) gid = api.auth.hierarchy.create_gid(xrn, create_uuid(), pkey, email = email) return gid.save_to_string(save_parents=True)
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 get_node_key(self): # 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 = self.get_registry() # the registry will scp the key onto the node registry.get_key()
def __init__(self, ip, port, key_file, cert_file, interface): threading.Thread.__init__(self) self.key = Keypair(filename=key_file) self.cert = Certificate(filename=cert_file) #self.server = SecureXMLRPCServer((ip, port), SecureXMLRpcRequestHandler, key_file, cert_file) self.server = ThreadedServer( (ip, int(port)), SecureXMLRpcRequestHandler, key_file, cert_file) self.server.interface = interface self.trusted_cert_list = None self.register_functions() logger.info("Starting SfaServer, interface=%s" % interface)
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
def handle_input_kind (filename, options, kind): # dump methods current do 'print' so let's go this road for now if kind=="certificate": cert=Certificate (filename=filename) print '--------------------',filename,'IS A',kind cert.dump(show_extensions=options.show_extensions) elif kind=="credential": cred = Credential(filename = filename) print '--------------------',filename,'IS A',kind cred.dump(dump_parents = options.dump_parents, show_xml=options.show_xml) if options.extract_gids: print '--------------------',filename,'embedded GIDS' extract_gids(cred, extract_parents = options.dump_parents) elif kind=="gid": gid = GID(filename = filename) print '--------------------',filename,'IS A',kind gid.dump(dump_parents = options.dump_parents) else: print "%s: unknown filekind '%s'"% (filename,kind)
def __init__(self, encoding="utf-8", methods='sfa.methods', config="/etc/sfa/sfa_config", peer_cert=None, interface=None, key_file=None, cert_file=None, cache=None): XmlrpcApi.__init__(self, encoding) # we may be just be documenting the API if config is None: return # Load configuration self.config = Config(config) self.credential = None self.auth = Auth(peer_cert) self.interface = interface self.hrn = self.config.SFA_INTERFACE_HRN self.key_file = key_file self.key = Keypair(filename=self.key_file) self.cert_file = cert_file self.cert = Certificate(filename=self.cert_file) self.cache = cache if self.cache is None: self.cache = Cache() # load registries from sfa.server.registry import Registries self.registries = Registries() # load aggregates from sfa.server.aggregate import Aggregates self.aggregates = Aggregates() # filled later on by generic/Generic self.manager = None self._dbsession = None
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
def testSign(self): cert = Certificate(subject="test") # create an issuer and sign the certificate issuerKey = Keypair(create=True) issuerSubject = "testissuer" cert.set_issuer(issuerKey, issuerSubject) cert.sign()
def handle_input (filename, options): kind = determine_sfa_filekind(filename) # dump methods current do 'print' so let's go this road for now if kind=="certificate": cert=Certificate (filename=filename) print '--------------------',filename,'IS A',kind cert.dump(show_extensions=options.show_extensions) verify_input_object (cert, kind, options) elif kind=="credential": cred = Credential(filename = filename) print '--------------------',filename,'IS A',kind cred.dump(dump_parents = options.dump_parents, show_xml=options.show_xml) if options.extract_gids: print '--------------------',filename,'embedded GIDs' extract_gids(cred, extract_parents = options.dump_parents) verify_input_object (cred, kind, options) elif kind=="gid": gid = GID(filename = filename) print '--------------------',filename,'IS A',kind gid.dump(dump_parents = options.dump_parents) verify_input_object (gid, kind, options) else: print "%s: unknown filekind '%s'"% (filename,kind)
def do_POST(self): """Handles the HTTPS POST request. It was copied out from SimpleXMLRPCServer.py and modified to shutdown the socket cleanly. """ try: peer_cert = Certificate() peer_cert.load_from_pyopenssl_x509(self.connection.get_peer_certificate()) self.api = ComponentAPI( peer_cert=peer_cert, interface=self.server.interface, key_file=self.server.key_file, cert_file=self.server.cert_file, ) # get arguments request = self.rfile.read(int(self.headers["content-length"])) # In previous versions of SimpleXMLRPCServer, _dispatch # could be overridden in this class, instead of in # SimpleXMLRPCDispatcher. To maintain backwards compatibility, # check to see if a subclass implements _dispatch and dispatch # using that method if present. # response = self.server._marshaled_dispatch(request, getattr(self, '_dispatch', None)) # XX TODO: Need to get the real remote address remote_addr = (remote_ip, remote_port) = self.connection.getpeername() self.api.remote_addr = remote_addr # remote_addr = (self.rfile.connection.remote_ip, remote_port) # self.api.remote_addr = remote_addr response = self.api.handle(remote_addr, request) except Exception, fault: raise # This should only happen if the module is buggy # internal error, report as HTTP server error self.send_response(500) self.end_headers() logger.log_exc("componentserver.SecureXMLRpcRequestHandler.do_POST")
def verify_chain(self, trusted_certs = None): # do the normal certificate verification stuff trusted_root = Certificate.verify_chain(self, trusted_certs) if self.parent: # make sure the parent's hrn is a prefix of the child's hrn if not self.get_hrn().startswith(self.parent.get_hrn()): #print self.get_hrn(), " ", self.parent.get_hrn() raise GidParentHrn("This cert %s HRN doesnt start with parent HRN %s" % (self.get_hrn(), self.parent.get_hrn())) else: # make sure that the trusted root's hrn is a prefix of the child's trusted_gid = GID(string=trusted_root.save_to_string()) trusted_type = trusted_gid.get_type() trusted_hrn = trusted_gid.get_hrn() #if trusted_type == 'authority': # trusted_hrn = trusted_hrn[:trusted_hrn.rindex('.')] cur_hrn = self.get_hrn() if not self.get_hrn().startswith(trusted_hrn): raise GidParentHrn("Trusted roots HRN %s isnt start of this cert %s" % (trusted_hrn, cur_hrn)) return
class SfaApi(XmlrpcApi): """ An SfaApi instance is a basic xmlrcp service augmented with the local cryptographic material and hrn It also has the notion of its own interface (a string describing whether we run a registry, aggregate or slicemgr) and has the notion of neighbour sfa services as defined in /etc/sfa/{aggregates,registries}.xml Finally it contains a cache instance It gets augmented by the generic layer with (*) an instance of manager (actually a manager module for now) beware that this is shared among all instances of api (*) an instance of a testbed driver """ def __init__(self, encoding="utf-8", methods='sfa.methods', config="/etc/sfa/sfa_config", peer_cert=None, interface=None, key_file=None, cert_file=None, cache=None): XmlrpcApi.__init__(self, encoding) # we may be just be documenting the API if config is None: return # Load configuration self.config = Config(config) self.credential = None self.auth = Auth(peer_cert) self.interface = interface self.hrn = self.config.SFA_INTERFACE_HRN self.key_file = key_file self.key = Keypair(filename=self.key_file) self.cert_file = cert_file self.cert = Certificate(filename=self.cert_file) self.cache = cache if self.cache is None: self.cache = Cache() # load registries from sfa.server.registry import Registries self.registries = Registries() # load aggregates from sfa.server.aggregate import Aggregates self.aggregates = Aggregates() # filled later on by generic/Generic self.manager = None self._dbsession = None def server_proxy(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.server_proxy(key_file, cert_file, timeout) return server def dbsession(self): if self._dbsession is None: self._dbsession = alchemy.session() return self._dbsession def close_dbsession(self): if self._dbsession is None: return alchemy.close_session(self._dbsession) self._dbsession = None def getCredential(self, minimumExpiration=0): """ 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 = os.path.join(path, 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() + datetime.timedelta(seconds=minimumExpiration) < cred.get_expiration(): return cred.save_to_string(save_parents=True) # get a new credential if self.interface in ['registry']: cred = self._getCredentialRaw() else: 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] hierarchy = Hierarchy() delegated_cred = None for cred in creds: if hierarchy.auth_exists( Credential(cred=cred).get_gid_caller().get_hrn()): delegated_cred = cred break return delegated_cred def _getCredential(self): """ Get our credential from a remote registry """ from sfa.server.registry import Registries registries = Registries() registry = registries.server_proxy(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. """ hrn = self.hrn auth_hrn = self.auth.get_authority(hrn) # is this a root or sub authority if not auth_hrn or hrn == self.config.SFA_INTERFACE_HRN: auth_hrn = hrn auth_info = self.auth.get_auth_info(auth_hrn) # xxx although unlikely we might want to check for a potential leak dbsession = self.dbsession() from sfa.storage.model import RegRecord record = dbsession.query(RegRecord).filter_by(type='authority+sa', hrn=hrn).first() if not record: raise RecordNotFound(hrn) type = record.type object_gid = record.get_gid_object() new_cred = Credential(subject=object_gid.get_subject()) new_cred.set_gid_caller(object_gid) new_cred.set_gid_object(object_gid) new_cred.set_issuer_keys(auth_info.get_privkey_filename(), auth_info.get_gid_filename()) r1 = determine_rights(type, hrn) new_cred.set_privileges(r1) new_cred.encode() new_cred.sign() return new_cred def loadCredential(self): """ Attempt to load credential from file if it exists. If it doesnt get credential from registry. """ # see if this file exists # XX This is really the aggregate's credential. Using this is easier than getting # the registry's credential from iteslf (ssl errors). filename = self.interface + self.hrn + ".ma.cred" ma_cred_path = os.path.join(self.config.SFA_DATA_DIR, filename) try: self.credential = Credential(filename=ma_cred_path) except IOError: self.credential = self.getCredentialFromRegistry() def get_cached_server_version(self, server): cache_key = server.url + "-version" server_version = None if self.cache: server_version = self.cache.get(cache_key) if not server_version: result = server.GetVersion() server_version = ReturnValue.get_value(result) # cache version for 24 hours self.cache.add(cache_key, server_version, ttl=60 * 60 * 24) return server_version def get_geni_code(self, result): code = { 'geni_code': GENICODE.SUCCESS, 'am_type': 'sfa', 'am_code': None, } if isinstance(result, SfaFault): code['geni_code'] = result.faultCode code['am_code'] = result.faultCode return code def get_geni_value(self, result): value = result if isinstance(result, SfaFault): value = "" return value def get_geni_output(self, result): output = "" if isinstance(result, SfaFault): output = result.faultString return output def prepare_response_am(self, result): version = version_core() response = { 'geni_api': 3, 'code': self.get_geni_code(result), 'value': self.get_geni_value(result), 'output': self.get_geni_output(result), } return response def prepare_response(self, result, method=""): """ Converts the specified result into a standard GENI compliant response """ # as of dec 13 2011 we only support API v2 if self.interface.lower() in ['aggregate', 'slicemgr']: result = self.prepare_response_am(result) return XmlrpcApi.prepare_response(self, result, method)
def testAddExtension(self): cert = Certificate(subject="test") cert.add_extension("subjectAltName", 0, "URI:http://foovalue") self.assertEqual(cert.get_extension("subjectAltName"), "URI:http://foovalue")
def testSetAndGetSubject(self): cert = Certificate() cert.create() cert.set_subject("test") subj = cert.get_subject() self.assertEqual(subj, "test")
def testSaveAndLoadString(self): cert = Certificate(subject="test") cert.add_extension("subjectAltName", 0, "URI:http://foovalue") # create an issuer and sign the certificate issuerKey = Keypair(create=True) issuerSubject = "testissuer" cert.set_issuer(issuerKey, issuerSubject) cert.sign() certstr = cert.save_to_string() #print certstr cert2 = Certificate() cert2.load_from_string(certstr) # read back the subject and make sure it is correct subj = cert2.get_subject() self.assertEqual(subj, "test") # read back the issuer and make sure it is correct issuerName = cert2.get_issuer() self.assertEqual(issuerName, "testissuer") # read back the extension and make sure it is correct self.assertEqual(cert2.get_extension("subjectAltName"), "URI:http://foovalue")
def __init__(self, create=False, subject=None, string=None, filename=None): Certificate.__init__(self, create, subject, string, filename)
def testLongExtension(self): cert = Certificate(subject="test") # should produce something around 256 KB veryLongString = "URI:http://" shortString = "" for i in range(1, 80): shortString = shortString + "abcdefghijklmnopqrstuvwxyz012345" for i in range(1, 100): veryLongString = veryLongString + shortString + str(i) cert.add_extension("subjectAltName", 0, veryLongString) # create an issuer and sign the certificate issuerKey = Keypair(create=True) issuerSubject = "testissuer" cert.set_issuer(issuerKey, issuerSubject) cert.sign() certstr = cert.save_to_string() cert2 = Certificate() cert2.load_from_string(certstr) val = cert2.get_extension("subjectAltName") self.assertEqual(val, veryLongString)
def testCreate(self): cert = Certificate() cert.create()
class SfaApi (XmlrpcApi): """ An SfaApi instance is a basic xmlrcp service augmented with the local cryptographic material and hrn It also has the notion of its own interface (a string describing whether we run a registry, aggregate or slicemgr) and has the notion of neighbour sfa services as defined in /etc/sfa/{aggregates,registries}.xml Finally it contains a cache instance It gets augmented by the generic layer with (*) an instance of manager (actually a manager module for now) beware that this is shared among all instances of api (*) an instance of a testbed driver """ def __init__ (self, encoding="utf-8", methods='sfa.methods', config = "/etc/sfa/sfa_config", peer_cert = None, interface = None, key_file = None, cert_file = None, cache = None): XmlrpcApi.__init__ (self, encoding) # we may be just be documenting the API if config is None: return # Load configuration self.config = Config(config) self.credential = None self.auth = Auth(peer_cert) self.interface = interface self.hrn = self.config.SFA_INTERFACE_HRN self.key_file = key_file self.key = Keypair(filename=self.key_file) self.cert_file = cert_file self.cert = Certificate(filename=self.cert_file) self.cache = cache if self.cache is None: self.cache = Cache() # load registries from sfa.server.registry import Registries self.registries = Registries() # load aggregates from sfa.server.aggregate import Aggregates self.aggregates = Aggregates() # filled later on by generic/Generic self.manager=None self._dbsession=None def server_proxy(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.server_proxy(key_file, cert_file, timeout) return server def dbsession(self): if self._dbsession is None: self._dbsession=alchemy.session() return self._dbsession def close_dbsession(self): if self._dbsession is None: return alchemy.close_session(self._dbsession) self._dbsession=None def getCredential(self, minimumExpiration=0): """ 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 = os.path.join(path,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() + datetime.timedelta(seconds=minimumExpiration) < cred.get_expiration(): return cred.save_to_string(save_parents=True) # get a new credential if self.interface in ['registry']: cred = self._getCredentialRaw() else: 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] hierarchy = Hierarchy() delegated_cred = None for cred in creds: if hierarchy.auth_exists(Credential(cred=cred).get_gid_caller().get_hrn()): delegated_cred = cred break return delegated_cred def _getCredential(self): """ Get our credential from a remote registry """ from sfa.server.registry import Registries registries = Registries() registry = registries.server_proxy(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. """ hrn = self.hrn auth_hrn = self.auth.get_authority(hrn) # is this a root or sub authority if not auth_hrn or hrn == self.config.SFA_INTERFACE_HRN: auth_hrn = hrn auth_info = self.auth.get_auth_info(auth_hrn) # xxx although unlikely we might want to check for a potential leak dbsession=self.dbsession() from sfa.storage.model import RegRecord record = dbsession.query(RegRecord).filter_by(type='authority+sa', hrn=hrn).first() if not record: raise RecordNotFound(hrn) type = record.type object_gid = record.get_gid_object() new_cred = Credential(subject = object_gid.get_subject()) new_cred.set_gid_caller(object_gid) new_cred.set_gid_object(object_gid) new_cred.set_issuer_keys(auth_info.get_privkey_filename(), auth_info.get_gid_filename()) r1 = determine_rights(type, hrn) new_cred.set_privileges(r1) new_cred.encode() new_cred.sign() return new_cred def loadCredential (self): """ Attempt to load credential from file if it exists. If it doesnt get credential from registry. """ # see if this file exists # XX This is really the aggregate's credential. Using this is easier than getting # the registry's credential from iteslf (ssl errors). filename = self.interface + self.hrn + ".ma.cred" ma_cred_path = os.path.join(self.config.SFA_DATA_DIR,filename) try: self.credential = Credential(filename = ma_cred_path) except IOError: self.credential = self.getCredentialFromRegistry() def get_cached_server_version(self, server): cache_key = server.url + "-version" server_version = None if self.cache: server_version = self.cache.get(cache_key) if not server_version: result = server.GetVersion() server_version = ReturnValue.get_value(result) # cache version for 24 hours self.cache.add(cache_key, server_version, ttl= 60*60*24) return server_version def get_geni_code(self, result): code = { 'geni_code': GENICODE.SUCCESS, 'am_type': 'sfa', 'am_code': None, } if isinstance(result, SfaFault): code['geni_code'] = result.faultCode code['am_code'] = result.faultCode return code def get_geni_value(self, result): value = result if isinstance(result, SfaFault): value = "" return value def get_geni_output(self, result): output = "" if isinstance(result, SfaFault): output = result.faultString return output def prepare_response_am(self, result): version = version_core() response = { 'geni_api': 3, 'code': self.get_geni_code(result), 'value': self.get_geni_value(result), 'output': self.get_geni_output(result), } return response def prepare_response(self, result, method=""): """ Converts the specified result into a standard GENI compliant response """ # as of dec 13 2011 we only support API v2 if self.interface.lower() in ['aggregate', 'slicemgr']: result = self.prepare_response_am(result) return XmlrpcApi.prepare_response(self, result, method)
def authenticateCert(self, certStr, requestHash): cert = Certificate(string=certStr) # xxx should be validateCred ?? self.validateCred(cert)
def test_parents(self): cert_root = Certificate(subject="root") key_root = Keypair(create=True) cert_root.set_pubkey(key_root) cert_root.set_issuer(key_root, "root") cert_root.sign() cert1 = Certificate(subject="one") key1 = Keypair(create=True) cert1.set_pubkey(key1) cert1.set_issuer(key_root, "root") cert1.sign() cert2 = Certificate(subject="two") key2 = Keypair(create=True) cert2.set_pubkey(key2) cert2.set_issuer(key1, cert=cert1) cert2.set_parent(cert1) cert2.sign() cert3 = Certificate(subject="three") key3 = Keypair(create=True) cert3.set_pubkey(key3) cert3.set_issuer(key2, cert=cert2) cert3.set_parent(cert2) cert3.sign() self.assert_(cert1.verify(key_root)) self.assert_(cert2.is_signed_by_cert(cert1)) self.assert_(cert3.is_signed_by_cert(cert2)) cert3.verify_chain([cert_root]) # now save the chain to a string and load it into a new certificate str_chain = cert3.save_to_string(save_parents=True) cert4 = Certificate(string = str_chain) # verify the newly loaded chain still verifies cert4.verify_chain([cert_root]) # verify the parentage self.assertEqual(cert4.get_parent().get_subject(), "two") self.assertEqual(cert4.get_parent().get_parent().get_subject(), "one")
def test_is_signed_by(self): cert1 = Certificate(subject="one") key1 = Keypair() key1.create() cert1.set_pubkey(key1) # create an issuer and sign the certificate issuerKey = Keypair(create=True) issuerSubject = "testissuer" cert1.set_issuer(issuerKey, issuerSubject) cert1.sign() cert2 = Certificate(subject="two") key2 = Keypair(create=True) cert2.set_pubkey(key2) cert2.set_issuer(key1, cert=cert1) # cert2 is signed by cert1 self.assert_(cert2.is_signed_by_cert(cert1)) # cert1 is not signed by cert2 self.assert_(not cert1.is_signed_by_cert(cert2))