X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Ftrust%2Fabac_credential.py;h=51e86483e2e2c1040a5b8fad44763071efa8e9d2;hb=04acd3228e5911d36d0cd58dc35b9319fc558e17;hp=407f405f9fc330f39481a6d9eb6825f477dc43bf;hpb=4f9d407d0ce159bdb359e9ab500bf88b5f586e62;p=sfa.git diff --git a/sfa/trust/abac_credential.py b/sfa/trust/abac_credential.py index 407f405f..51e86483 100644 --- a/sfa/trust/abac_credential.py +++ b/sfa/trust/abac_credential.py @@ -21,13 +21,16 @@ # IN THE WORK. #---------------------------------------------------------------------- + + from sfa.trust.credential import Credential, append_sub, DEFAULT_CREDENTIAL_LIFETIME from sfa.util.sfalogging import logger from sfa.util.sfatime import SFATIME_FORMAT -from StringIO import StringIO from xml.dom.minidom import Document, parseString +from io import StringIO + HAVELXML = False try: from lxml import etree @@ -41,13 +44,13 @@ except: # or between a subject and a class of targets (all those satisfying a role). # # An ABAC credential is like a normal SFA credential in that it has -# a validated signature block and is checked for expiration. +# a validated signature block and is checked for expiration. # It does not, however, have 'privileges'. Rather it contains a 'head' and # list of 'tails' of elements, each of which represents a principal and # role. # A special case of an ABAC credential is a speaks_for credential. Such -# a credential is simply an ABAC credential in form, but has a single +# a credential is simply an ABAC credential in form, but has a single # tail and fixed role 'speaks_for'. In ABAC notation, it asserts # AGENT.speaks_for(AGENT)<-CLIENT, or "AGENT asserts that CLIENT may speak # for AGENT". The AGENT in this case is the head and the CLIENT is the @@ -63,16 +66,20 @@ except: # An ABAC element contains a principal (keyid and optional mnemonic) # and optional role and linking_role element class ABACElement: - def __init__(self, principal_keyid, principal_mnemonic=None, \ - role=None, linking_role=None): + + def __init__(self, principal_keyid, principal_mnemonic=None, + role=None, linking_role=None): self._principal_keyid = principal_keyid self._principal_mnemonic = principal_mnemonic self._role = role self._linking_role = linking_role def get_principal_keyid(self): return self._principal_keyid + def get_principal_mnemonic(self): return self._principal_mnemonic + def get_role(self): return self._role + def get_linking_role(self): return self._linking_role def __str__(self): @@ -88,26 +95,28 @@ class ABACElement: # Subclass of Credential for handling ABAC credentials # They have a different cred_type (geni_abac vs. geni_sfa) # and they have a head and tail and role (as opposed to privileges) + + class ABACCredential(Credential): ABAC_CREDENTIAL_TYPE = 'geni_abac' - def __init__(self, create=False, subject=None, + def __init__(self, create=False, subject=None, string=None, filename=None): - self.head = None # An ABACElemenet - self.tails = [] # List of ABACElements - super(ABACCredential, self).__init__(create=create, - subject=subject, - string=string, + self.head = None # An ABACElemenet + self.tails = [] # List of ABACElements + super(ABACCredential, self).__init__(create=create, + subject=subject, + string=string, filename=filename) self.cred_type = ABACCredential.ABAC_CREDENTIAL_TYPE - def get_head(self) : - if not self.head: + def get_head(self): + if not self.head: self.decode() return self.head - def get_tails(self) : + def get_tails(self): if len(self.tails) == 0: self.decode() return self.tails @@ -122,7 +131,8 @@ class ABACCredential(Credential): rt0_root = rt0s[0] heads = self._get_abac_elements(rt0_root, 'head') if len(heads) != 1: - raise CredentialNotVerifiable("ABAC credential should have exactly 1 head element, had %d" % len(heads)) + raise CredentialNotVerifiable( + "ABAC credential should have exactly 1 head element, had %d" % len(heads)) self.head = heads[0] self.tails = self._get_abac_elements(rt0_root, 'tail') @@ -133,7 +143,8 @@ class ABACCredential(Credential): for elt in elements: keyids = elt.getElementsByTagName('keyid') if len(keyids) != 1: - raise CredentialNotVerifiable("ABAC credential element '%s' should have exactly 1 keyid, had %d." % (label, len(keyids))) + raise CredentialNotVerifiable( + "ABAC credential element '%s' should have exactly 1 keyid, had %d." % (label, len(keyids))) keyid_elt = keyids[0] keyid = keyid_elt.childNodes[0].nodeValue.strip() @@ -150,7 +161,8 @@ class ABACCredential(Credential): linking_role = None linking_role_elts = elt.getElementsByTagName('linking_role') if len(linking_role_elts) > 0: - linking_role = linking_role_elts[0].childNodes[0].nodeValue.strip() + linking_role = linking_role_elts[ + 0].childNodes[0].nodeValue.strip() abac_element = ABACElement(keyid, mnemonic, role, linking_role) abac_elements.append(abac_element) @@ -159,12 +171,14 @@ class ABACCredential(Credential): def dump_string(self, dump_parents=False, show_xml=False): result = "ABAC Credential\n" - filename=self.get_filename() - if filename: result += "Filename %s\n"%filename + filename = self.get_filename() + if filename: + result += "Filename %s\n" % filename if self.expiration: - result += "\texpiration: %s \n" % self.expiration.strftime(SFATIME_FORMAT) + result += "\texpiration: %s \n" % self.expiration.strftime( + SFATIME_FORMAT) - result += "\tHead: %s\n" % self.get_head() + result += "\tHead: %s\n" % self.get_head() for tail in self.get_tails(): result += "\tTail: %s\n" % tail if self.get_signature(): @@ -179,13 +193,14 @@ class ABACCredential(Credential): result += "\nEnd XML\n" except: import traceback - print "exc. Credential.dump_string / XML" + print("exc. Credential.dump_string / XML") traceback.print_exc() return result # sounds like this should be __repr__ instead ?? - # Produce the ABAC assertion. Something like [ABAC cred: Me.role<-You] or similar - def get_summary_tostring(self): + # Produce the ABAC assertion. Something like [ABAC cred: Me.role<-You] or + # similar + def pretty_cred(self): result = "[ABAC cred: " + str(self.get_head()) for tail in self.get_tails(): result += "<-%s" % str(tail) @@ -194,9 +209,9 @@ class ABACCredential(Credential): def createABACElement(self, doc, tagName, abacObj): kid = abacObj.get_principal_keyid() - mnem = abacObj.get_principal_mnemonic() # may be None - role = abacObj.get_role() # may be None - link = abacObj.get_linking_role() # may be None + mnem = abacObj.get_principal_mnemonic() # may be None + role = abacObj.get_role() # may be None + link = abacObj.get_linking_role() # may be None ele = doc.createElement(tagName) prin = doc.createElement('ABACprincipal') ele.appendChild(prin) @@ -215,7 +230,8 @@ class ABACCredential(Credential): # WARNING: # In general, a signed credential obtained externally should # not be changed else the signature is no longer valid. So, once - # you have loaded an existing signed credential, do not call encode() or sign() on it. + # you have loaded an existing signed credential, do not call encode() or + # sign() on it. def encode(self): # Create the XML document @@ -228,9 +244,12 @@ class ABACCredential(Credential): # Note that delegation of credentials between the 2 only really works # cause those schemas are identical. # Also note these PG schemas talk about PG tickets and CM policies. - signed_cred.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") - signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.geni.net/resources/credential/2/credential.xsd") - signed_cred.setAttribute("xsi:schemaLocation", "http://www.planet-lab.org/resources/sfa/ext/policy/1 http://www.planet-lab.org/resources/sfa/ext/policy/1/policy.xsd") + signed_cred.setAttribute( + "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", + "http://www.geni.net/resources/credential/2/credential.xsd") + signed_cred.setAttribute( + "xsi:schemaLocation", "http://www.planet-lab.org/resources/sfa/ext/policy/1 http://www.planet-lab.org/resources/sfa/ext/policy/1/policy.xsd") # PG says for those last 2: # signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.protogeni.net/resources/credential/credential.xsd") @@ -253,12 +272,14 @@ class ABACCredential(Credential): append_sub(doc, cred, "uuid", "") if not self.expiration: - self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + self.set_expiration(datetime.datetime.utcnow( + ) + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) self.expiration = self.expiration.replace(microsecond=0) if self.expiration.tzinfo is not None and self.expiration.tzinfo.utcoffset(self.expiration) is not None: # TZ aware. Make sure it is UTC self.expiration = self.expiration.astimezone(tz.tzutc()) - append_sub(doc, cred, "expires", self.expiration.strftime(SFATIME_FORMAT)) # RFC3339 + append_sub(doc, cred, "expires", self.expiration.strftime( + SFATIME_FORMAT)) # RFC3339 abac = doc.createElement("abac") rt0 = doc.createElement("rt0")