def verify_from_strings(self, gid_string, cred_strings, target_urn, privileges): '''Create Credential and GID objects from the given strings, and then verify the GID has the right privileges according to the given credentials on the given target.''' if gid_string is None: return def make_cred(cred_string): return cred.Credential(string=cred_string) return self.verify(gid.GID(string=gid_string), map(make_cred, cred_strings), target_urn, privileges)
def create_credential(caller_gid, object_gid, expiration, typename, issuer_keyfile, issuer_certfile, trusted_roots, delegatable=False): '''Create and Return a Credential object issued by given key/cert for the given caller and object GID objects, given life in seconds, and given type. Privileges are determined by type per sfa/trust/rights.py Privileges are delegatable if requested.''' # FIXME: Validate args: my gids, >0 life, # type of cred one I can issue # and readable key and cert files if caller_gid is None: raise ValueError("Missing Caller GID") if object_gid is None: raise ValueError("Missing Object GID") if expiration is None: raise ValueError("Missing expiration") naive_expiration = naiveUTC(expiration) duration = naive_expiration - datetime.datetime.utcnow() life_secs = duration.seconds + duration.days * 24 * 3600 if life_secs < 1: raise ValueError("Credential expiration is in the past") if trusted_roots is None: raise ValueError("Missing list of trusted roots") if typename is None or typename.strip() == '': raise ValueError("Missing credential type") typename = typename.strip().lower() if typename not in ("user", "sa", "ma", "authority", "slice", "component"): raise ValueError("Unknown credential type %s" % typename) if not os.path.isfile(issuer_keyfile): raise ValueError("Cant read issuer key file %s" % issuer_keyfile) if not os.path.isfile(issuer_certfile): raise ValueError("Cant read issuer cert file %s" % issuer_certfile) issuer_gid = gid.GID(filename=issuer_certfile) if not (object_gid.get_urn() == issuer_gid.get_urn() or (issuer_gid.get_type().find('authority') == 0 and hrn_authfor_hrn(issuer_gid.get_hrn(), object_gid.get_hrn()))): raise ValueError("Issuer not authorized to issue credential: Issuer=%s Target=%s" % (issuer_gid.get_urn(), object_gid.get_urn())) ucred = cred.Credential() # FIXME: Validate the caller_gid and object_gid # are my user and slice # Do get_issuer and compare to the issuer cert? # Or do gid.is_signed_by_cert(issuer_certfile)? ucred.set_gid_caller(caller_gid) ucred.set_gid_object(object_gid) ucred.set_expiration(expiration) # Use sfa/trust/rights.py to figure out what privileges # the credential should have. # user means refresh, resolve, info # per the privilege_table that lets users do # remove, update, resolve, list, getcredential, # listslices, listnodes, getpolicy # Note that it does not allow manipulating slivers # And every right is delegatable if any are delegatable (default False) privileges = rights.determine_rights(typename, None) privileges.delegate_all_privileges(delegatable) ucred.set_privileges(privileges) ucred.encode() ucred.set_issuer_keys(issuer_keyfile, issuer_certfile) ucred.sign() try: ucred.verify(trusted_roots) except Exception, exc: raise Exception("Create Credential failed to verify new credential from trusted roots: %s" % exc)
class CredentialVerifier(object): """Utilities to verify signed credentials from a given set of root certificates. Will compare target and source URNs, and privileges. See verify and verify_from_strings methods in particular.""" CATEDCERTSFNAME = 'CATedCACerts.pem' # root_cert_fileordir is a trusted root cert file or directory of # trusted roots for verifying credentials def __init__(self, root_cert_fileordir): if root_cert_fileordir is None: raise Exception("Missing Root certs argument") elif os.path.isdir(root_cert_fileordir): files = os.listdir(root_cert_fileordir) self.root_cert_files = [] for file in files: # FIXME: exclude files that aren't cert files? #print file == CredentialVerifier.CATEDCERTSFNAME if file == CredentialVerifier.CATEDCERTSFNAME: continue self.root_cert_files.append(os.path.expanduser(os.path.join(root_cert_fileordir, file))) #self.root_cert_files = [root_cert_fileordir] else: raise Exception("Couldn't find Root certs in %s" % root_cert_fileordir) @classmethod def getCAsFileFromDir(cls, caCerts): '''Take a directory of CA certificates and concatenate them into a single file suitable for use by the Python SSL library to validate client credentials. Existing file is replaced.''' if caCerts is None: raise Exception ('Missing caCerts argument') if os.path.isfile(os.path.expanduser(caCerts)): return caCerts if not os.path.isdir(os.path.expanduser(caCerts)): raise Exception ('caCerts arg Not a file or a dir: %s' % caCerts) # Now we have a dir of caCerts files # For each file in the dir (isfile), concatenate them into a new file comboFullPath = os.path.join(caCerts, CredentialVerifier.CATEDCERTSFNAME) caFiles = os.listdir(caCerts) #logger.debug('Got %d potential caCert files in the dir', len(caFiles)) outfile = open(comboFullPath, "w") okFileCount = 0 for filename in caFiles: filepath = os.path.join(caCerts, filename) # Confirm it's a CA file? # if not file.endswith('.pem'): # continue if not os.path.isfile(os.path.expanduser(filepath)): continue if filename == CredentialVerifier.CATEDCERTSFNAME: # logger.debug('Skipping previous cated certs file') continue okFileCount += 1 certfile = open(filepath) for line in certfile: outfile.write(line) certfile.close() outfile.close() if okFileCount == 0: sys.exit('Found NO trusted certs in %s!' % caCerts) return comboFullPath def verify_from_strings(self, gid_string, cred_strings, target_urn, privileges, options=None): '''Create Credential and GID objects from the given strings, and then verify the GID has the right privileges according to the given credentials on the given target.''' def make_cred(cred_string): credO = None try: credO = CredentialFactory.createCred(credString=cred_string) except Exception, e: print(e) return credO root_certs = \ [Certificate(filename=root_cert_file) \ for root_cert_file in self.root_cert_files] caller_gid = gid.GID(string=gid_string) # Potentially, change gid_string to be the cert of the actual user # if this is a 'speaks-for' invocation speaksfor_gid = \ determine_speaks_for(None, \ cred_strings, # May include ABAC speaks_for credential caller_gid, # Caller cert (may be the tool 'speaking for' user) options, # May include 'geni_speaking_for' option with user URN root_certs ) if caller_gid.get_subject() != speaksfor_gid.get_subject(): speaksfor_urn = speaksfor_gid.get_urn() caller_gid = speaksfor_gid # Remove the abac credentials cred_strings = [cred_string for cred_string in cred_strings \ if CredentialFactory.getType(cred_string) == cred.Credential.SFA_CREDENTIAL_TYPE] return self.verify(caller_gid, map(make_cred, cred_strings), target_urn, privileges)