bugfix, correct previous change on locating xmlsec1
[sfa.git] / sfa / trust / speaksfor_util.py
index ab74237..9e85924 100644 (file)
@@ -31,6 +31,8 @@ import tempfile
 from xml.dom.minidom import *
 from StringIO import StringIO
 
+from sfa.util.sfatime import SFATIME_FORMAT
+
 from sfa.trust.certificate import Certificate
 from sfa.trust.credential import Credential, signature_template, HAVELXML
 from sfa.trust.abac_credential import ABACCredential, ABACElement
@@ -129,26 +131,26 @@ def verify_speaks_for(cred, tool_gid, speaking_for_urn,
 
     # Credential has not expired
     if cred.expiration and cred.expiration < datetime.datetime.utcnow():
-        return False, None, "ABAC Credential expired at %s (%s)" % (cred.expiration.isoformat(), cred.get_summary_tostring())
+        return False, None, "ABAC Credential expired at %s (%s)" % (cred.expiration.strftime(SFATIME_FORMAT), cred.pretty_cred())
 
     # Must be ABAC
     if cred.get_cred_type() != ABACCredential.ABAC_CREDENTIAL_TYPE:
         return False, None, "Credential not of type ABAC but %s" % cred.get_cred_type
 
     if cred.signature is None or cred.signature.gid is None:
-        return False, None, "Credential malformed: missing signature or signer cert. Cred: %s" % cred.get_summary_tostring()
+        return False, None, "Credential malformed: missing signature or signer cert. Cred: %s" % cred.pretty_cred()
     user_gid = cred.signature.gid
     user_urn = user_gid.get_urn()
 
     # URN of signer from cert must match URN of 'speaking-for' argument
     if user_urn != speaking_for_urn:
         return False, None, "User URN from cred doesn't match speaking_for URN: %s != %s (cred %s)" % \
-            (user_urn, speaking_for_urn, cred.get_summary_tostring())
+            (user_urn, speaking_for_urn, cred.pretty_cred())
 
     tails = cred.get_tails()
     if len(tails) != 1: 
         return False, None, "Invalid ABAC-SF credential: Need exactly 1 tail element, got %d (%s)" % \
-            (len(tails), cred.get_summary_tostring())
+            (len(tails), cred.pretty_cred())
 
     user_keyid = get_cert_keyid(user_gid)
     tool_keyid = get_cert_keyid(tool_gid)
@@ -158,16 +160,6 @@ def verify_speaks_for(cred, tool_gid, speaking_for_urn,
     principal_keyid = head.get_principal_keyid()
     role = head.get_role()
 
-    logger.info('user keyid: %s' % user_keyid)         
-    logger.info('principal keyid: %s' % principal_keyid)       
-    logger.info('tool keyid: %s' % tool_keyid)         
-    logger.info('subject keyid: %s' % subject_keyid) 
-    logger.info('role: %s' % role) 
-    logger.info('user gid: %s' % user_gid.dump_string())
-    f = open('/tmp/speaksfor/tool.gid', 'w')
-    f.write(tool_gid.dump_string())
-    f.close()  
-
     # Credential must pass xmlsec1 verify
     cred_file = write_to_tempfile(cred.save_to_string())
     cert_args = []
@@ -175,7 +167,10 @@ def verify_speaks_for(cred, tool_gid, speaking_for_urn,
         for x in trusted_roots:
             cert_args += ['--trusted-pem', x.filename]
     # FIXME: Why do we not need to specify the --node-id option as credential.py does?
-    xmlsec1_args = [cred.xmlsec_path, '--verify'] + cert_args + [ cred_file]
+    xmlsec1 = cred.get_xmlsec1_path()
+    if not xmlsec1:
+        raise Exception("Could not locate required 'xmlsec1' program")
+    xmlsec1_args = [xmlsec1, '--verify'] + cert_args + [ cred_file]
     output = run_subprocess(xmlsec1_args, stdout=None, stderr=subprocess.PIPE)
     os.unlink(cred_file)
     if output != 0:
@@ -196,7 +191,7 @@ def verify_speaks_for(cred, tool_gid, speaking_for_urn,
     if user_keyid != principal_keyid or \
             tool_keyid != subject_keyid or \
             role != ('speaks_for_%s' % user_keyid):
-        return False, None, "ABAC statement doesn't assert U.speaks_for(U)<-T (%s)" % cred.get_summary_tostring()
+        return False, None, "ABAC statement doesn't assert U.speaks_for(U)<-T (%s)" % cred.pretty_cred()
 
     # If schema provided, validate against schema
     if HAVELXML and schema and os.path.exists(schema):
@@ -206,7 +201,7 @@ def verify_speaks_for(cred, tool_gid, speaking_for_urn,
         xmlschema = etree.XMLSchema(schema_doc)
         if not xmlschema.validate(tree):
             error = xmlschema.error_log.last_error
-            message = "%s: %s (line %s)" % (cred.get_summary_tostring(), error.message, error.line)
+            message = "%s: %s (line %s)" % (cred.pretty_cred(), error.message, error.line)
             return False, None, ("XML Credential schema invalid: %s" % message)
 
     if trusted_roots:
@@ -239,12 +234,9 @@ def verify_speaks_for(cred, tool_gid, speaking_for_urn,
 # trusted_roots is a list of Certificate objects from the system
 #   trusted_root directory
 # Optionally, provide an XML schema against which to validate the credential
-def determine_speaks_for(logger, credentials, caller_gid, options,
-                         trusted_roots, schema=None):
-    logger.info(options)
-    logger.info("geni speaking for:%s " % 'geni_speaking_for' in options)  
-    if options and 'geni_speaking_for' in options:
-        speaking_for_urn = options['geni_speaking_for'].strip()
+def determine_speaks_for(logger, credentials, caller_gid, speaking_for_xrn, trusted_roots, schema=None):
+    if speaking_for_xrn:
+        speaking_for_urn = Xrn (speaking_for_xrn.strip()).get_urn()
         for cred in credentials:
             # Skip things that aren't ABAC credentials
             if type(cred) == dict:
@@ -263,13 +255,9 @@ def determine_speaks_for(logger, credentials, caller_gid, options,
             if not isinstance(cred_value, ABACCredential):
                 cred = CredentialFactory.createCred(cred_value)
 
-#            print "Got a cred to check speaksfor for: %s" % cred.get_summary_tostring()
+#            print "Got a cred to check speaksfor for: %s" % cred.pretty_cred()
 #            #cred.dump(True, True)
 #            print "Caller: %s" % caller_gid.dump_string(2, True)
-            logger.info(cred.dump_string())
-            f = open('/tmp/speaksfor/%s.cred' % cred, 'w')
-            f.write(cred.xml)
-            f.close()
             # See if this is a valid speaks_for
             is_valid_speaks_for, user_gid, msg = \
                 verify_speaks_for(cred,
@@ -319,9 +307,8 @@ def create_sign_abaccred(tool_gid, user_gid, ma_gid, user_key_file, cred_filenam
     # Save it
     cred.save_to_file(cred_filename)
     print "Created ABAC credential: '%s' in file %s" % \
-            (cred.get_summary_tostring(), cred_filename)
+            (cred.pretty_cred(), cred_filename)
 
-# FIXME: Assumes xmlsec1 is on path
 # FIXME: Assumes signer is itself signed by an 'ma_gid' that can be trusted
 def create_speaks_for(tool_gid, user_gid, ma_gid, \
                           user_key_file, cred_filename, dur_days=365):
@@ -365,8 +352,8 @@ def create_speaks_for(tool_gid, user_gid, ma_gid, \
 
 
     credential_duration = datetime.timedelta(days=dur_days)
-    expiration = datetime.datetime.now(du_tz.tzutc()) + credential_duration
-    expiration_str = expiration.strftime('%Y-%m-%dT%H:%M:%SZ') # FIXME: libabac can't handle .isoformat()
+    expiration = datetime.datetime.utcnow() + credential_duration
+    expiration_str = expiration.strftime(SFATIME_FORMAT)
     version = "1.1"
 
     user_keyid = get_cert_keyid(user_gid)
@@ -381,8 +368,10 @@ def create_speaks_for(tool_gid, user_gid, ma_gid, \
     # --output signed.xml tosign.xml
     pems = "%s,%s,%s" % (user_key_file, user_gid.get_filename(),
                          ma_gid.get_filename())
-    # FIXME: assumes xmlsec1 is on path
-    cmd = ['xmlsec1',  '--sign',  '--privkey-pem', pems, 
+    xmlsec1 = Credential.get_xmlsec1_path()
+    if not xmlsec1:
+        raise Exception("Could not locate required 'xmlsec1' program")
+    cmd = [ xmlsec1,  '--sign',  '--privkey-pem', pems, 
            '--output', cred_filename, unsigned_cred_filename]
 
 #    print " ".join(cmd)