Changeset 5538


Ignore:
Timestamp:
30/07/09 16:41:06 (10 years ago)
Author:
pjkersha
Message:

Working SAML Attribute Query with SOAP binding

Location:
TI12-security/trunk/python
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/saml/__init__.py

    r5528 r5538  
    3535from datetime import datetime, timedelta 
    3636    
    37 from ndg.security.common.utils import QName 
     37from ndg.security.common.utils import QName, TypedList 
    3838from ndg.security.common.saml.xml import SAMLConstants, XMLConstants 
    3939 
     
    443443 
    444444    def __init__(self): 
    445         self._attributes = [] 
    446         self._encryptedAttributes = [] 
     445        self.__attributes = TypedList(Attribute) 
     446        self.__encryptedAttributes = TypedList(Attribute) 
    447447 
    448448    # Element local name 
     
    465465        '''@return the attributes expressed in this statement 
    466466        ''' 
    467         return self._attributes 
     467        return self.__attributes 
    468468 
    469469    attributes = property(fget=_get_attributes) 
     
    472472       '''@return the encrypted attribtues expressed in this statement 
    473473       ''' 
    474        return self._encryptedAttributes 
     474       return self.__encryptedAttributes 
    475475    
    476476    encryptedAttributes = property(fget=_get_encryptedAttributes) 
     
    568568 
    569569 
    570 class Subject(SAMLObject): 
    571     '''Concrete implementation of @link org.opensaml.saml2.core.Subject.''' 
    572  
    573     def __init__(self, namespaceURI, elementLocalName, namespacePrefix): 
     570class AbstractNameIDType(SAMLObject): 
     571    '''Abstract implementation of NameIDType''' 
     572 
     573    # SPNameQualifier attribute name. 
     574    SP_NAME_QUALIFIER_ATTRIB_NAME = "SPNameQualifier" 
     575 
     576    # Format attribute name. 
     577    FORMAT_ATTRIB_NAME = "Format" 
     578 
     579    # SPProviderID attribute name. 
     580    SPPROVIDED_ID_ATTRIB_NAME = "SPProvidedID" 
     581 
     582    # URI for unspecified name format. 
     583    UNSPECIFIED = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" 
     584 
     585    # URI for email name format. 
     586    EMAIL = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" 
     587 
     588    # URI for X509 subject name format. 
     589    X509_SUBJECT = "urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName" 
     590 
     591    # URI for windows domain qualified name name format. 
     592    WIN_DOMAIN_QUALIFIED = \ 
     593        "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName" 
     594 
     595    # URI for kerberos name format. 
     596    KERBEROS = "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos" 
     597 
     598    # URI for SAML entity name format. 
     599    ENTITY = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity" 
     600 
     601    # URI for persistent name format. 
     602    PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" 
     603 
     604    # URI for transient name format. 
     605    TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" 
     606 
     607    # Special URI used by NameIDPolicy to indicate a NameID should be encrypted 
     608    ENCRYPTED = "urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted" 
     609     
     610    def __init__(self, namespaceURI, elementLocalName, namespacePrefix):  
    574611        '''@param namespaceURI the namespace the element is in 
    575612        @param elementLocalName the local name of the XML element this Object  
     
    577614        @param namespacePrefix the prefix for the given namespace 
    578615        ''' 
    579         super(namespaceURI, elementLocalName, namespacePrefix) 
     616        self.__qname = QName(namespaceURI, elementLocalName, namespacePrefix) 
     617     
     618        # Name of the Name ID. 
     619        self.__name = None 
     620         
     621        # Name Qualifier of the Name ID. 
     622        self.__nameQualifier = None 
     623     
     624        # SP Name Qualifier of the Name ID. 
     625        self.__spNameQualifier = None 
     626     
     627        # Format of the Name ID. 
     628        self.__format = None 
     629     
     630        # SP ProvidedID of the NameID. 
     631        self.__spProvidedID = None 
     632 
     633        self.__value = None 
     634         
     635    def _getQName(self): 
     636        return self.__qname 
     637         
     638    def _setQName(self, value): 
     639        if not isinstance(value, QName): 
     640            raise TypeError("\"qname\" must be a %r derived type, " 
     641                            "got %r" % (QName, type(value))) 
     642             
     643        self.__qname = value 
     644 
     645    qname = property(fget=_getQName, fset=_setQName, doc="qualified name") 
     646              
     647    def _getValue(self): 
     648        return self.__value 
     649         
     650    def _setValue(self, value): 
     651        if not isinstance(value, basestring): 
     652            raise TypeError("\"value\" must be a basestring derived type, " 
     653                            "got %r" % value.__class__) 
     654             
     655        self.__value = value 
     656 
     657    value = property(fget=_getValue, fset=_setValue, doc="string value")   
     658     
     659    def _getNameQualifier(self):  
     660        return self.__nameQualifier 
     661     
     662    def _setNameQualifier(self, value):  
     663        self.__nameQualifier = value 
     664 
     665    nameQualifier = property(fget=_getNameQualifier,  
     666                             fset=_setNameQualifier,  
     667                             doc="Name qualifier")     
     668 
     669    def _getSPNameQualifier(self):  
     670        return self.__spNameQualifier 
     671     
     672    def _setSPNameQualifier(self, value):  
     673        self.__spNameQualifier = value 
     674 
     675    spNameQualifier = property(fget=_getSPNameQualifier,  
     676                               fset=_setSPNameQualifier,  
     677                               doc="SP Name qualifier")     
     678     
     679    def _getFormat(self): 
     680        return self.__format 
     681         
     682    def _setFormat(self, format): 
     683        if not isinstance(format, basestring): 
     684            raise TypeError("\"format\" must be a basestring derived type, " 
     685                            "got %r" % format.__class__) 
     686             
     687        self.__format = format 
     688 
     689    format = property(fget=_getFormat, fset=_setFormat, doc="Name format")   
     690     
     691    def _getSPProvidedID(self):  
     692        return self.__spProvidedID 
     693     
     694    def _setSPProvidedID(self, value):  
     695        self.__spProvidedID = value 
     696 
     697    spProvidedID = property(fget=_getSPProvidedID, fset=_setSPProvidedID,  
     698                            doc="SP Provided Identifier")   
     699     
     700    def getOrderedChildren(self):  
     701        raise NotImplementedError() 
     702 
     703    
     704class Issuer(AbstractNameIDType): 
     705 
     706    # Element local name.  
     707    DEFAULT_ELEMENT_LOCAL_NAME = "Issuer" 
     708 
     709    # Default element name.  
     710    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS,  
     711                                 DEFAULT_ELEMENT_LOCAL_NAME, 
     712                                 SAMLConstants.SAML20_PREFIX) 
     713 
     714    # Local name of the XSI type.  
     715    TYPE_LOCAL_NAME = "IssuerType" 
     716 
     717    # QName of the XSI type. 
     718    TYPE_NAME = QName(SAMLConstants.SAML20_NS,  
     719                      TYPE_LOCAL_NAME, 
     720                      SAMLConstants.SAML20_PREFIX)  
     721     
     722    def __init__(self,  
     723                 namespaceURI=SAMLConstants.SAML20_NS,  
     724                 elementLocalName=DEFAULT_ELEMENT_LOCAL_NAME,  
     725                 namespacePrefix=SAMLConstants.SAML20_PREFIX): 
     726        super(Issuer, self).__init__(namespaceURI=namespaceURI, 
     727                                     elementLocalName=elementLocalName, 
     728                                     namespacePrefix=namespacePrefix) 
     729 
     730      
     731class NameID(AbstractNameIDType): 
     732    '''SAML 2.0 Core NameID''' 
     733    # Element local name.  
     734    DEFAULT_ELEMENT_LOCAL_NAME = "NameID" 
     735 
     736    # Default element name.  
     737    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS,  
     738                                 DEFAULT_ELEMENT_LOCAL_NAME, 
     739                                 SAMLConstants.SAML20_PREFIX) 
     740 
     741    # Local name of the XSI type.  
     742    TYPE_LOCAL_NAME = "NameIDType" 
     743 
     744    # QName of the XSI type.  
     745    TYPE_NAME = QName(SAMLConstants.SAML20_NS,  
     746                      TYPE_LOCAL_NAME, 
     747                      SAMLConstants.SAML20_PREFIX) 
     748     
     749    def __init__(self,  
     750                 namespaceURI=SAMLConstants.SAML20_NS,  
     751                 elementLocalName=DEFAULT_ELEMENT_LOCAL_NAME,  
     752                 namespacePrefix=SAMLConstants.SAML20_PREFIX): 
     753        super(NameID, self).__init__(namespaceURI=namespaceURI, 
     754                                     elementLocalName=elementLocalName, 
     755                                     namespacePrefix=namespacePrefix) 
     756         
     757     
     758class Subject(SAMLObject): 
     759    '''Concrete implementation of @link org.opensaml.saml2.core.Subject.''' 
     760     
     761    # Element local name. 
     762    DEFAULT_ELEMENT_LOCAL_NAME = "Subject" 
     763 
     764    # Default element name. 
     765    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS,  
     766                                 DEFAULT_ELEMENT_LOCAL_NAME, 
     767                                 SAMLConstants.SAML20_PREFIX) 
     768 
     769    # Local name of the XSI type. 
     770    TYPE_LOCAL_NAME = "SubjectType" 
     771 
     772    # QName of the XSI type. 
     773    TYPE_NAME = QName(SAMLConstants.SAML20_NS,  
     774                      TYPE_LOCAL_NAME, 
     775                      SAMLConstants.SAML20_PREFIX) 
     776 
     777    def __init__(self,  
     778                 namespaceURI=SAMLConstants.SAML20_NS,  
     779                 elementLocalName=DEFAULT_ELEMENT_LOCAL_NAME,  
     780                 namespacePrefix=SAMLConstants.SAML20_PREFIX): 
     781        '''@param namespaceURI the namespace the element is in 
     782        @param elementLocalName the local name of the XML element this Object  
     783        represents 
     784        @param namespacePrefix the prefix for the given namespace 
     785        ''' 
     786        self.__qname = QName(namespaceURI,  
     787                             tag=elementLocalName,  
     788                             prefix=namespacePrefix) 
    580789         
    581790        # BaseID child element. 
     
    591800        self.__subjectConfirmations = [] 
    592801     
     802    def _get_qname(self): 
     803        return self.__qname 
     804     
     805    qname = property(fget=_get_qname, doc="Qualified Name for Subject") 
     806     
    593807    def _getBaseID(self):  
    594808        return self.__baseID 
    595809 
    596810    def _setBaseID(self, value): 
     811        if not isinstance(value, basestring): 
     812            raise TypeError("Expecting %r type for \"baseID\" got %r" % 
     813                            (basestring, value.__class__)) 
    597814        self.__baseID = value 
    598      
    599     def _getNameID(self): 
    600         return self.__nameID 
    601      
    602     def _setNameID(self, value): 
    603         nameID = value 
    604  
    605     def _getEncryptedID(self): 
    606         return self.__encryptedID 
    607      
    608     def _setEncryptedID(self, value):  
    609         self.__encryptedID = value 
    610      
    611     def _getSubjectConfirmations(self):  
    612         return self.__subjectConfirmations 
    613      
    614     def getOrderedChildren(self):  
    615         children = [] 
    616  
    617         if self.baseID is not None: 
    618             children.append(self.baseID) 
    619          
    620         if self.nameID is not None:  
    621             children.append(self.nameID) 
    622          
    623         if self.encryptedID is not None:  
    624             children.append(self.encryptedID) 
    625          
    626         children += self.subjectConfirmations 
    627  
    628         return tuple(children) 
    629815 
    630816    baseID = property(fget=_getBaseID,  
    631817                      fset=_setBaseID,  
    632818                      doc="Base identifier") 
     819       
     820    def _getNameID(self): 
     821        return self.__nameID 
     822     
     823    def _setNameID(self, value): 
     824        if not isinstance(value, NameID): 
     825            raise TypeError("Expecting %r type for \"nameID\" got %r" % 
     826                            (NameID, type(value))) 
     827        self.__nameID = value 
    633828 
    634829    nameID = property(fget=_getNameID,  
    635830                      fset=_setNameID,  
    636831                      doc="Name identifier") 
     832     
     833    def _getEncryptedID(self): 
     834        return self.__encryptedID 
     835     
     836    def _setEncryptedID(self, value):  
     837        self.__encryptedID = value 
    637838 
    638839    encryptedID = property(fget=_getEncryptedID,  
    639840                           fset=_setEncryptedID,  
    640                            doc="EncryptedID's Docstring") 
     841                           doc="EncryptedID's Docstring")     
     842    def _getSubjectConfirmations(self):  
     843        return self.__subjectConfirmations 
    641844 
    642845    subjectConfirmations = property(fget=_getSubjectConfirmations,  
    643                                     doc="Subject Confirmations") 
    644  
    645  
    646 class SubjectQuery(SAMLObject): 
    647  
    648     def __init__(self): 
    649         self.__subject = None 
    650          
    651     def _getSubject(self): 
    652         '''Gets the Subject of this request. 
    653          
    654         @return the Subject of this request'''    
    655         return self.__subject 
    656      
    657     def _setSubject(self, value): 
    658         '''Sets the Subject of this request. 
    659          
    660         @param newSubject the Subject of this request''' 
    661         self.__subject = value 
    662          
    663     subject = property(fget=_getSubject, fset=_setSubject, doc="Query subject") 
    664  
     846                                    doc="Subject Confirmations")     
     847    def getOrderedChildren(self):  
     848        children = [] 
     849 
     850        if self.baseID is not None: 
     851            children.append(self.baseID) 
     852         
     853        if self.nameID is not None:  
     854            children.append(self.nameID) 
     855         
     856        if self.encryptedID is not None:  
     857            children.append(self.encryptedID) 
     858         
     859        children += self.subjectConfirmations 
     860 
     861        return tuple(children) 
     862     
    665863 
    666864class RequestAbstractType(SAMLObject):  
     
    8071005        self.__destination = value 
    8081006         
    809     destination = property(fget=_get_issuer,  
    810                            fset=_set_issuer, 
     1007    destination = property(fget=_get_destination,  
     1008                           fset=_set_destination, 
    8111009                           doc="Destination of request") 
    8121010      
     
    8321030        self.__consent = value 
    8331031               
    834     consent = property(fget=_get_issuer,  
    835                        fset=_set_issuer, 
    836                        doc="Destination of request") 
     1032    consent = property(fget=_get_consent,  
     1033                       fset=_set_consent, 
     1034                       doc="Consent for request") 
    8371035    
    8381036    def _set_issuer(self, issuer): 
    8391037        """Set issuer of request""" 
    840         if not isinstance(issuer, basestring): 
    841             raise TypeError("issuer must be a string, got %r" %  
     1038        if not isinstance(issuer, Issuer): 
     1039            raise TypeError("\"issuer\" must be a %r, got %r" %  
    8421040                            issuer.__class__) 
    8431041         
     
    8691067                          fset=_set_extensions, 
    8701068                          doc="Request extensions") 
    871      
    872          
     1069 
     1070 
     1071class SubjectQuery(RequestAbstractType): 
     1072 
     1073    def __init__(self): 
     1074        self.__subject = None 
     1075         
     1076    def _getSubject(self): 
     1077        '''Gets the Subject of this request. 
     1078         
     1079        @return the Subject of this request'''    
     1080        return self.__subject 
     1081     
     1082    def _setSubject(self, value): 
     1083        '''Sets the Subject of this request. 
     1084         
     1085        @param newSubject the Subject of this request''' 
     1086        if not isinstance(value, Subject): 
     1087            raise TypeError('Setting "subject", got %r, expecting %r' % 
     1088                            (Subject, type(value))) 
     1089             
     1090        self.__subject = value 
     1091         
     1092    subject = property(fget=_getSubject, fset=_setSubject, doc="Query subject") 
     1093     
    8731094     
    8741095class AttributeQuery(SubjectQuery): 
     
    8911112                      SAMLConstants.SAML20P_PREFIX) 
    8921113 
    893     def __init__(self, attributes): 
    894         self.__attributes = attributes 
     1114    def __init__(self): 
     1115        self.__attributes = TypedList(Attribute) 
    8951116  
    8961117    def _getAttributes(self): 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/saml/xml/__init__.py

    r5519 r5538  
    319319         
    320320         
    321 class AssertionXMLObject(XMLObject): 
     321class IssueInstantXMLObject(XMLObject): 
    322322    """Specialisation to enable inclusion of datetime formatting for issue 
    323323    instant 
     
    326326     
    327327    @classmethod 
    328     def issueInstantDatetime2Str(cls, dtIssueInstant): 
     328    def datetime2Str(cls, dtIssueInstant): 
    329329        """Convert issue instant datetime to correct string type for output 
    330330        @type dtIssueInstant: datetime.datetime 
     
    333333        @return: issue instance as a string 
    334334        """ 
    335         return dtIssueInstant.strftime(AssertionXMLObject.issueInstantFmt) 
    336  
     335        return dtIssueInstant.strftime(IssueInstantXMLObject.issueInstantFmt) 
     336 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/saml/xml/etree.py

    r5514 r5538  
    3232 
    3333try: # python 2.5 
    34     from xml.etree import cElementTree as ElementTree 
     34    from xml.etree import cElementTree, ElementTree 
    3535except ImportError: 
    3636    # if you've installed it yourself it comes this way 
    37     import cElementTree as ElementTree 
    38      
    39 from ndg.security.common.utils import canonicalize 
    40  
    41 # XML signature module based on M2Crypto 
    42 from ndg.security.common.xmlsec.etree import XMLSecDoc, InvalidSignature 
     37    import cElementTree, ElementTree 
    4338 
    4439from ndg.security.common.saml import SAMLObject, Assertion, Attribute, \ 
    4540    AttributeStatement, AttributeValue, XSStringAttributeValue, \ 
    46     XSGroupRoleAttributeValue 
    47      
    48 from ndg.security.common.saml.xml import XMLObject, AssertionXMLObject, \ 
    49     XMLConstants 
     41    XSGroupRoleAttributeValue, AttributeQuery, Subject, NameID, Issuer 
     42     
     43from ndg.security.common.saml.xml import XMLObject, IssueInstantXMLObject, \ 
     44    SAMLConstants 
    5045 
    5146 
     
    6560         
    6661        return self._elem 
     62#     
     63#    def serialize(self): 
     64#        """Serialise element tree into string""" 
     65#        return canonicalize(self._elem) 
    6766     
    6867    def serialize(self): 
    6968        """Serialise element tree into string""" 
    70         return canonicalize(self._elem) 
    71      
     69        return cElementTree.tostring(self._elem) 
     70    
    7271    def prettyPrint(self): 
    7372        """Basic pretty printing separating each element on to a new line""" 
     
    7978     
    8079                          
    81 class AssertionETreeObject(ETreeObject, AssertionXMLObject): 
     80class AssertionETreeObject(ETreeObject, IssueInstantXMLObject): 
    8281    """ElementTree based XML representation of Assertion class 
    8382    """ 
    8483    def __init__(self): 
    8584        ETreeObject.__init__(self) 
    86         AssertionXMLObject.__init__(self) 
    87      
    88     def create(self, assertion, makeNsDeclaration=True,  
     85        IssueInstantXMLObject.__init__(self) 
     86     
     87    def create(self,  
     88               assertion,  
    8989               **attributeValueETreeObjectFactoryKw): 
    9090        """Make a tree of a XML elements based on the assertion""" 
     
    9292            raise TypeError("Expecting %r type got: %r"%(Assertion, assertion)) 
    9393         
    94         issueInstant = AssertionXMLObject.issueInstantDatetime2Str( 
     94        issueInstant = IssueInstantXMLObject.datetime2Str( 
    9595                                                        assertion.issueInstant) 
    9696        attrib = { 
     
    103103        self._elem = ElementTree.Element(str(Assertion.DEFAULT_ELEMENT_NAME),  
    104104                                         **attrib) 
    105         if makeNsDeclaration: 
    106             self._elem.set("xmlns:%s" % Assertion.DEFAULT_ELEMENT_NAME.prefix,  
    107                            Assertion.DEFAULT_ELEMENT_NAME.namespaceURI) 
     105         
     106        ElementTree._namespace_map[  
     107            Assertion.DEFAULT_ELEMENT_NAME.namespaceURI 
     108        ] = Assertion.DEFAULT_ELEMENT_NAME.prefix 
    108109         
    109110        attributeStatementETreeObject = AttributeStatementETreeObject() 
     
    112113            attributeStatementElem = attributeStatementETreeObject.create( 
    113114                                        attributeStatement, 
    114                                         makeNsDeclaration=False, 
    115115                                        **attributeValueETreeObjectFactoryKw) 
    116116            self._elem.append(attributeStatementElem) 
     
    124124    """ElementTree XML representation of AttributeStatement""" 
    125125     
    126     def create(self, attributeStatement, makeNsDeclaration=True,  
     126    def create(self,  
     127               attributeStatement,  
    127128               **attributeValueETreeObjectFactoryKw): 
    128129        if not isinstance(attributeStatement, AttributeStatement): 
     
    132133        self._elem = ElementTree.Element( 
    133134                                str(AttributeStatement.DEFAULT_ELEMENT_NAME)) 
    134         if makeNsDeclaration: 
    135             self._elem.set( 
    136                 "xmlns:%s" % AttributeStatement.DEFAULT_ELEMENT_NAME.prefix,  
    137                 AttributeStatement.DEFAULT_ELEMENT_NAME.namespaceURI) 
     135        ElementTree._namespace_map[ 
     136            AttributeStatement.DEFAULT_ELEMENT_NAME.namespaceURI 
     137        ] = AttributeStatement.DEFAULT_ELEMENT_NAME.prefix  
    138138 
    139139        attributeETreeObject = AttributeETreeObject() 
     
    142142            # Factory enables support for multiple attribute types 
    143143            attributeElem = attributeETreeObject.create(attribute, 
    144                                         makeNsDeclaration=False, 
    145144                                        **attributeValueETreeObjectFactoryKw) 
    146145            self._elem.append(attributeElem) 
     
    153152    to make Attribute types"""  
    154153 
    155     def create(self, attribute, makeNsDeclaration=True, 
     154    def create(self,  
     155               attribute,  
    156156               **attributeValueETreeObjectFactoryKw): 
    157157        """Make 'Attribute' element""" 
     
    161161             
    162162        self._elem = ElementTree.Element(str(Attribute.DEFAULT_ELEMENT_NAME)) 
    163         if makeNsDeclaration: 
    164             self._elem.set("xmlns:%s" % Attribute.DEFAULT_ELEMENT_NAME.prefix,  
    165                            Attribute.DEFAULT_ELEMENT_NAME.namespaceURI) 
     163        ElementTree._namespace_map[ 
     164            Attribute.DEFAULT_ELEMENT_NAME.namespaceURI 
     165        ] = Attribute.DEFAULT_ELEMENT_NAME.prefix  
     166         
    166167             
    167168        if attribute.friendlyName: 
     
    181182            attributeValueETreeObject = factory(attributeValue) 
    182183             
    183             attributeValueElem = attributeValueETreeObject.create( 
    184                                                     attributeValue,  
    185                                                     makeNsDeclaration=False) 
     184            attributeValueElem=attributeValueETreeObject.create(attributeValue) 
    186185            self._elem.append(attributeValueElem) 
    187186             
     
    192191    """Base class ElementTree XML representation of SAML Attribute Value"""  
    193192     
    194     def create(self, attributeValue, makeNsDeclaration=True): 
     193    def create(self, attributeValue): 
    195194        """Make 'Attribute' XML element""" 
    196195 
     
    201200        self._elem = ElementTree.Element( 
    202201                                    str(AttributeValue.DEFAULT_ELEMENT_NAME)) 
    203         if makeNsDeclaration: 
    204             self._elem.set( 
    205                     "xmlns:%s" % AttributeValue.DEFAULT_ELEMENT_NAME.prefix,  
    206                     AttributeValue.DEFAULT_ELEMENT_NAME.namespaceURI) 
     202        ElementTree._namespace_map[ 
     203            AttributeValue.DEFAULT_ELEMENT_NAME.namespaceURI 
     204        ] = AttributeValue.DEFAULT_ELEMENT_NAME.prefix 
    207205 
    208206        return self._elem 
     
    212210    """ElementTree XML representation of SAML String type Attribute Value"""  
    213211     
    214     def create(self, attributeValue, makeNsDeclaration=True): 
     212    def create(self, attributeValue): 
    215213        """Create an XML representation of the input SAML Attribute Value""" 
    216         super(XSStringAttributeValueETreeObject, self).create( 
    217                                         attributeValue,  
    218                                         makeNsDeclaration=makeNsDeclaration) 
     214        super(XSStringAttributeValueETreeObject, self).create(attributeValue) 
    219215         
    220216        if not isinstance(attributeValue, XSStringAttributeValue): 
    221217            raise TypeError("Expecting %r type got: %r" %  
    222218                            (XSStringAttributeValue, attributeValue))  
    223                     
    224         self._elem.set("%s:%s" % (XMLConstants.XMLNS_PREFIX,  
    225                                   XMLConstants.XSD_PREFIX),  
    226                        XMLConstants.XSD_NS) 
    227          
    228         self._elem.set("%s:%s" % (XMLConstants.XMLNS_PREFIX, 
    229                                   XMLConstants.XSI_PREFIX),  
    230                        XMLConstants.XSI_NS) 
    231          
    232         self._elem.set("%s:%s" % (XMLConstants.XSI_PREFIX, 'type'),  
    233                        "%s:%s" % (XMLConstants.XSD_PREFIX,  
     219         
     220        # Have to explicitly add namespace declaration here rather use  
     221        # ElementTree._namespace_map because the prefixes are used for  
     222        # attributes not element names         
     223        self._elem.set("%s:%s" % (SAMLConstants.XMLNS_PREFIX,  
     224                                  SAMLConstants.XSD_PREFIX), 
     225                       SAMLConstants.XSD_NS) 
     226                                    
     227        self._elem.set("%s:%s" % (SAMLConstants.XMLNS_PREFIX,  
     228                                  SAMLConstants.XSI_PREFIX), 
     229                       SAMLConstants.XSI_NS) 
     230         
     231        self._elem.set("%s:%s" % (SAMLConstants.XSI_PREFIX, 'type'),  
     232                       "%s:%s" % (SAMLConstants.XSD_PREFIX,  
    234233                                  XSStringAttributeValue.TYPE_LOCAL_NAME)) 
    235234 
     
    243242    Attribute Value"""  
    244243 
    245     def create(self, attributeValue, makeNsDeclaration=True): 
     244    def create(self, attributeValue): 
    246245        """Create an XML representation of the input SAML Attribute Value""" 
    247         super(XSGroupRoleAttributeValueETreeObject, self).create( 
    248                                         attributeValue,  
    249                                         makeNsDeclaration=makeNsDeclaration) 
     246        super(XSGroupRoleAttributeValueETreeObject,self).create(attributeValue) 
    250247         
    251248        if not isinstance(attributeValue, XSGroupRoleAttributeValue): 
     
    253250                            (XSGroupRoleAttributeValue, attributeValue)) 
    254251             
    255         self._elem.set("%s:%s" % (XMLConstants.XMLNS_PREFIX,  
    256                                   attributeValue.namespacePrefix),  
    257                        attributeValue.namespaceURI) 
     252        ElementTree._namespace_map[attributeValue.namespaceURI 
     253                                   ] = attributeValue.namespacePrefix 
    258254         
    259255        self._elem.set(XSGroupRoleAttributeValue.GROUP_ATTRIB_NAME,  
     
    264260 
    265261        return self._elem 
     262 
    266263 
    267264class AttributeValueETreeObjectFactory(object): 
     
    290287        if not isinstance(samlObject, AttributeValue): 
    291288            raise TypeError("Expecting %r class got %r" % (AttributeValue,  
    292                                                            samlObject)) 
     289                                                           type(samlObject))) 
    293290             
    294291        xmlObjectClass = self.__classMap.get(samlObject.__class__) 
     
    298295             
    299296        return xmlObjectClass() 
     297 
     298         
     299class IssuerETreeObject(ETreeObject): 
     300    """Represent a SAML Issuer element in XML using ElementTree""" 
     301     
     302    def create(self, issuer): 
     303        """Create an XML representation of the input SAML issuer object""" 
     304        if not isinstance(issuer, Issuer): 
     305            raise TypeError("Expecting %r class got %r" % (issuer,  
     306                                                           type(Issuer))) 
     307        attrib = { 
     308            Issuer.FORMAT_ATTRIB_NAME: issuer.format 
     309        } 
     310        self._elem = ElementTree.Element(str(Issuer.DEFAULT_ELEMENT_NAME), 
     311                                         **attrib) 
     312        ElementTree._namespace_map[issuer.qname.namespaceURI 
     313                                   ] = issuer.qname.prefix 
     314                                    
     315        self._elem.text = issuer.value 
     316 
     317        return self._elem 
     318 
     319         
     320class NameIdETreeObject(ETreeObject): 
     321    """Represent a SAML Name Identifier in XML using ElementTree""" 
     322     
     323    def create(self, nameID): 
     324        """Create an XML representation of the input SAML Name Identifier 
     325        object""" 
     326        if not isinstance(nameID, NameID): 
     327            raise TypeError("Expecting %r class got %r" % (nameID,  
     328                                                           type(NameID))) 
     329        attrib = { 
     330            NameID.FORMAT_ATTRIB_NAME: nameID.format 
     331        } 
     332        self._elem = ElementTree.Element(str(NameID.DEFAULT_ELEMENT_NAME), 
     333                                         **attrib) 
     334         
     335        ElementTree._namespace_map[nameID.qname.namespaceURI 
     336                                   ] = nameID.qname.prefix 
     337         
     338        self._elem.text = nameID.value 
     339 
     340        return self._elem 
     341 
     342 
     343class SubjectETreeObject(ETreeObject): 
     344    """Represent a SAML Subject in XML using ElementTree""" 
     345     
     346    def create(self, subject): 
     347        """Create an XML representation of the input SAML subject object""" 
     348        if not isinstance(subject, Subject): 
     349            raise TypeError("Expecting %r class got %r" % (subject,  
     350                                                           type(Subject))) 
     351             
     352        self._elem = ElementTree.Element(str(Subject.DEFAULT_ELEMENT_NAME)) 
     353         
     354        ElementTree._namespace_map[ 
     355            AttributeQuery.DEFAULT_ELEMENT_NAME.namespaceURI 
     356        ] = AttributeQuery.DEFAULT_ELEMENT_NAME.prefix 
     357 
     358             
     359        nameIdETreeObject = NameIdETreeObject() 
     360        nameIdElem = nameIdETreeObject.create(subject.nameID) 
     361        self._elem.append(nameIdElem) 
     362         
     363        return self._elem 
     364 
     365      
     366class AttributeQueryETreeObject(ETreeObject, IssueInstantXMLObject): 
     367    """Represent a SAML Attribute Query in XML using ElementTree""" 
     368    def __init__(self): 
     369        ETreeObject.__init__(self) 
     370        IssueInstantXMLObject.__init__(self) 
     371         
     372    def create(self,  
     373               attributeQuery,  
     374               **attributeValueETreeObjectFactoryKw): 
     375        """Create an XML representation of the input SAML Attribute Query 
     376        object 
     377        """ 
     378        if not isinstance(attributeQuery, AttributeQuery): 
     379            raise TypeError("Expecting %r class got %r" % (AttributeQuery,  
     380                                                        type(attributeQuery))) 
     381             
     382         
     383        issueInstant = AttributeQueryETreeObject.datetime2Str( 
     384                                                attributeQuery.issueInstant) 
     385        attrib = { 
     386            AttributeQuery.ID_ATTRIB_NAME: attributeQuery.id, 
     387            AttributeQuery.ISSUE_INSTANT_ATTRIB_NAME: issueInstant, 
     388             
     389            # Nb. Version is a SAMLVersion instance and requires explicit cast 
     390            AttributeQuery.VERSION_ATTRIB_NAME: str(attributeQuery.version) 
     391        } 
     392                  
     393        self._elem = ElementTree.Element( 
     394                                    str(AttributeQuery.DEFAULT_ELEMENT_NAME), 
     395                                    **attrib) 
     396         
     397        ElementTree._namespace_map[ 
     398            AttributeQuery.DEFAULT_ELEMENT_NAME.namespaceURI 
     399        ] = AttributeQuery.DEFAULT_ELEMENT_NAME.prefix 
     400         
     401             
     402        issuerETreeObject = IssuerETreeObject() 
     403        issuerElem = issuerETreeObject.create(attributeQuery.issuer) 
     404        self._elem.append(issuerElem) 
     405 
     406        subjectETreeObject = SubjectETreeObject() 
     407        subjectElem = subjectETreeObject.create(attributeQuery.subject) 
     408         
     409        self._elem.append(subjectElem) 
     410 
     411        attributeETreeObject = AttributeETreeObject() 
     412 
     413        for attribute in attributeQuery.attributes: 
     414            # Factory enables support for multiple attribute types 
     415            attributeElem = attributeETreeObject.create(attribute, 
     416                                        **attributeValueETreeObjectFactoryKw) 
     417            self._elem.append(attributeElem) 
     418         
     419        return self._elem 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/soap/etree.py

    r5521 r5538  
    1313     
    1414try: # python 2.5 
    15     from xml.etree import cElementTree as ElementTree 
     15    from xml.etree import cElementTree, ElementTree 
    1616except ImportError: 
    1717    # if you've installed it yourself it comes this way 
    18     import cElementTree as ElementTree 
     18    import cElementTree, ElementTree 
    1919 
    2020# ElementTree helper functions 
     
    2222 
    2323from ndg.security.common.soap import SOAPObject, SOAPEnvelopeBase, \ 
    24     SOAPHeaderBase, SOAPBodyBase 
     24    SOAPHeaderBase, SOAPBodyBase, SOAPFault 
    2525 
    2626class ETreeSOAPExtensions(object):   
     
    5353    elem = property(_getElem, _setElem, None, "Root element") 
    5454     
     55#    @staticmethod 
     56#    def _serialize(elem): 
     57#        """Serialise element tree into string""" 
     58#         
     59#        # Make a basic check for the SOAP name space declaration, if the 
     60#        # element is constructed from a call to ElementTree.parse it may not 
     61#        # be present  
     62#        namespaceDeclarationFound = False 
     63#        soapElemNsDeclaration = ( 
     64#            'xmlns:%s' % SOAPObject.ELEMENT_PREFIX,  
     65#            SOAPObject.DEFAULT_NS 
     66#        ) 
     67#        if soapElemNsDeclaration[0] not in elem.attrib: 
     68#            log.warning("No SOAP namespace declaration found - adding one in") 
     69#            elem.set(*soapElemNsDeclaration) 
     70#         
     71#        return canonicalize(elem) 
     72 
    5573    @staticmethod 
    5674    def _serialize(elem): 
    57         """Serialise element tree into string""" 
    58          
    59         # Make a basic check for the SOAP name space declaration, if the 
    60         # element is constructed from a call to ElementTree.parse it may not 
    61         # be present  
    62         namespaceDeclarationFound = False 
    63         soapElemNsDeclaration = ( 
    64             'xmlns:%s' % SOAPObject.ELEMENT_PREFIX,  
    65             SOAPObject.DEFAULT_NS 
    66         ) 
    67         if soapElemNsDeclaration[0] not in elem.attrib: 
    68             log.warning("No SOAP namespace declaration found - adding one in") 
    69             elem.set(*soapElemNsDeclaration) 
    70          
    71         return canonicalize(elem) 
    72      
     75         """Serialise element tree into string""" 
     76         return cElementTree.tostring(elem) 
     77        
    7378    @classmethod 
    7479    def _prettyPrint(cls, elem): 
     
    106111                           prefix=SOAPHeaderBase.DEFAULT_ELEMENT_NS_PREFIX) 
    107112 
    108     def create(self, makeNsDeclaration=True): 
     113    def create(self): 
    109114        """Create header ElementTree element""" 
    110115         
    111116        self.elem = ElementTree.Element(str(self.qname)) 
    112         if makeNsDeclaration: 
    113             self.elem.set( 
    114                     "xmlns:%s" % SOAPHeaderBase.DEFAULT_ELEMENT_NS_PREFIX, 
    115                     SOAPHeaderBase.DEFAULT_ELEMENT_NS) 
     117        ElementTree._namespace_map[SOAPHeaderBase.DEFAULT_ELEMENT_NS 
     118                                   ] = SOAPHeaderBase.DEFAULT_ELEMENT_NS_PREFIX 
    116119     
    117120    def serialize(self): 
     
    139142                           prefix=SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX) 
    140143         
    141     def create(self, makeNsDeclaration=True): 
     144    def create(self): 
    142145        """Create header ElementTree element""" 
    143          
    144146        self.elem = ElementTree.Element(str(self.qname)) 
    145         if makeNsDeclaration: 
    146             self.elem.set("xmlns:%s" % SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX, 
    147                           SOAPBodyBase.DEFAULT_ELEMENT_NS) 
    148147     
    149148    def serialize(self): 
     
    193192    body = property(_getBody, _setBody, None, "SOAP body object") 
    194193 
    195     def create(self, makeNsDeclaration=True): 
     194    def create(self): 
    196195        """Create SOAP Envelope with header and body""" 
    197196         
    198197        self.elem = ElementTree.Element(str(self.qname)) 
    199         if makeNsDeclaration: 
    200             self.elem.set("xmlns:%s" % SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX, 
    201                           SOAPBodyBase.DEFAULT_ELEMENT_NS) 
    202198             
    203         self.header.create(makeNsDeclaration=False) 
     199        self.header.create() 
    204200        self.elem.append(self.header.elem) 
    205201         
    206         self.body.create(makeNsDeclaration=False) 
     202        self.body.create() 
    207203        self.elem.append(self.body.elem) 
    208204     
     
    228224            else: 
    229225                raise SOAPFault('Invalid child element in SOAP Envelope "%s" ' 
    230                                 'for source %r' % (localName, source)) 
     226                                'for stream %r' % (localName, source)) 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/utils/__init__.py

    r5510 r5538  
    9090 
    9191 
     92def prettyPrint(elem, indent='', html=0, space=' '*4): 
     93    '''Lightweight pretty printing of ElementTree elements''' 
     94    def estrip(elem): 
     95        ''' Just want to get rid of unwanted whitespace ''' 
     96        if elem is None: 
     97            return '' 
     98        else: 
     99            # just in case the elem is another simple type - e.g. int - wrapper 
     100            # it as a string 
     101            return str(elem).strip() 
     102         
     103    strAttrib = ''.join([' %s="%s"'% (att, attVal)  
     104                         for att, attVal in elem.attrib.items()]) 
     105             
     106    result = '%s<%s%s>%s' % (indent, elem.tag, strAttrib, estrip(elem.text)) 
     107     
     108    children = len(elem) 
     109    if children: 
     110        result += ''.join(['\n'+ prettyPrint(item, indent=indent+space)  
     111                           for item in elem]) + \ 
     112                '\n%s%s</%s>' % (indent, estrip(item.tail), elem.tag) 
     113    else: 
     114        result += '</%s>' % elem.tag 
     115         
     116    return result 
     117 
     118 
    92119class UniqList(list): 
    93     """Extended version of list type to enable a list with unique items""" 
     120    """Extended version of list type to enable a list with unique items. 
     121    If an item is added that is already present then it is silently omitted 
     122    from the list 
     123    """ 
    94124    def extend(self, iter): 
    95         super(UniqList, self).extend([i for i in iter if i not in self]) 
     125        return super(UniqList, self).extend([i for i in iter if i not in self]) 
    96126         
    97127    def __iadd__(self, iter): 
    98         raise TypeError("+= operator not possible on UniqList. Try the extend " 
    99                         "method intead") 
     128        return super(UniqList, self).__iadd__([i for i in iter  
     129                                               if i not in self]) 
     130          
     131    def append(self, item): 
     132        for i in self: 
     133            if i == item: 
     134                return None 
     135             
     136        return super(UniqList, self).append(item) 
     137 
     138 
     139class TypedList(list): 
     140    """Extend list type to enabled only items of a given type.  Supports 
     141    any type where the array type in the Standard Library is restricted to  
     142    only limited set of primitive types 
     143    """ 
     144     
     145    def __init__(self, objectType, *arg, **kw): 
     146        """ 
     147        @type objectType: type/iterable 
     148        @param objectType: object type or types which the list is allowed to 
     149        contain.  If more than one type, pass as a list, tuple or other  
     150        iterable 
     151        """ 
     152        self.__objectType = objectType 
     153        super(TypedList, self).__init__(*arg, **kw) 
     154         
     155    def extend(self, iter): 
     156        for i in iter: 
     157            if not isinstance(i, self.__objectType): 
     158                raise TypeError("List items must be of type %r" %  
     159                                self.__objectType) 
     160                 
     161        return super(TypedList, self).extend(iter) 
     162         
     163    def __iadd__(self, iter): 
     164        for i in iter: 
     165            if not isinstance(i, self.__objectType): 
     166                raise TypeError("List items must be of type %r" %  
     167                                self.__objectType) 
     168        return super(TypedList, self).__iadd__(iter) 
     169          
     170    def append(self, item): 
     171        if not isinstance(item, self.__objectType): 
     172            raise TypeError("List items must be of type %r" % 
     173                            self.__objectType) 
     174        return super(TypedList, self).append(item) 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/attributeauthority/saml/test_samlinterface.py

    r5519 r5538  
    1111import logging 
    1212logging.basicConfig(level=logging.DEBUG) 
    13      
     13import unittest 
     14 
    1415from datetime import datetime 
    1516import base64  
    1617import os 
    1718from uuid import uuid4 
    18  
    19 from ndg.security.test.unit import BaseTestCase 
     19import paste.fixture 
    2020 
    2121from ndg.security.common.saml import Assertion, Attribute, AttributeValue, \ 
    22     AttributeStatement, SAMLVersion, XSStringAttributeValue, \ 
    23     XSGroupRoleAttributeValue 
     22    AttributeStatement, SAMLVersion, Subject, NameID, Issuer, AttributeQuery, \ 
     23    XSStringAttributeValue 
    2424from ndg.security.common.saml.xml import XMLConstants 
    2525from ndg.security.common.saml.xml.etree import AssertionETreeObject, \ 
    26     XSGroupRoleAttributeValueETreeObject 
     26    AttributeQueryETreeObject 
     27     
     28from ndg.security.common.soap.etree import SOAPEnvelope 
    2729 
    28 from ndg.security.common.soap import SOAPEnvelope() 
    29  
    30  
    31 class Request(object): 
    32     pass 
    33  
    34 class Response(object): 
    35     pass 
    36  
    37 class AttributeQuery(object): 
    38     pass 
    3930 
    4031class SamlSoapBindingMiddleware(object): 
    4132    def __call__(self, environ, start_response): 
     33        soapRequestStream = environ['wsgi.input'] 
     34        soapRequest = SOAPEnvelope() 
     35        soapRequest.parse(soapRequestStream) 
     36        print "Received request from client:\n" 
     37        print soapRequest.prettyPrint() 
     38         
    4239        soapResponse = SOAPEnvelope() 
     40        soapResponse.create() 
    4341        response = soapResponse.serialize() 
    4442        start_response("200 OK", 
     
    5957         
    6058 
    61     def test02Skip200WithLoggedIn(self): 
    62         response = self.app.post('/attributeauthority/saml',  
    63                                   params='',  
    64                                   headers=None,  
    65                                   extra_environ=None, 
    66                                   status=None,  
    67                                   upload_files=None,  
    68                                   expect_errors=False) 
     59    def test01AttributeQuery(self): 
     60        attributeQuery = AttributeQuery() 
     61        attributeQuery.version = SAMLVersion(SAMLVersion.VERSION_20) 
     62        attributeQuery.id = str(uuid4()) 
     63        attributeQuery.issueInstant = datetime.utcnow() 
     64         
     65        attributeQuery.issuer = Issuer() 
     66        attributeQuery.issuer.format = Issuer.X509_SUBJECT 
     67        attributeQuery.issuer.value = \ 
     68                        "/O=NDG/OU=BADC/CN=attributeauthority.badc.rl.ac.uk" 
     69                         
     70                         
     71        attributeQuery.subject = Subject()   
     72        attributeQuery.subject.nameID = NameID() 
     73        attributeQuery.subject.nameID.format = "urn:esg:openid" 
     74        attributeQuery.subject.nameID.value = \ 
     75                                    "https://openid.localhost/philip.kershaw" 
     76         
     77        # special case handling for 'FirstName' attribute 
     78        fnAttribute = Attribute() 
     79        fnAttribute.name = "urn:esg:first:name" 
     80        fnAttribute.nameFormat = "http://www.w3.org/2001/XMLSchema#string" 
     81        fnAttribute.friendlyName = "FirstName" 
     82 
     83        attributeQuery.attributes.append(fnAttribute) 
     84     
     85        # special case handling for 'LastName' attribute 
     86        lnAttribute = Attribute() 
     87        lnAttribute.name = "urn:esg:last:name" 
     88        lnAttribute.nameFormat = "http://www.w3.org/2001/XMLSchema#string" 
     89        lnAttribute.friendlyName = "LastName" 
     90 
     91        attributeQuery.attributes.append(lnAttribute) 
     92     
     93        # special case handling for 'LastName' attribute 
     94        emailAddressAttribute = Attribute() 
     95        emailAddressAttribute.name = "urn:esg:email:address" 
     96        emailAddressAttribute.nameFormat = XMLConstants.XSD_NS+"#"+\ 
     97                                    XSStringAttributeValue.TYPE_LOCAL_NAME 
     98        emailAddressAttribute.friendlyName = "emailAddress" 
     99 
     100        attributeQuery.attributes.append(emailAddressAttribute)                                    
     101         
     102        attributeQueryETreeObject = AttributeQueryETreeObject() 
     103        elem = attributeQueryETreeObject.create(attributeQuery) 
     104        query = attributeQueryETreeObject.serialize() 
     105        soapRequest = SOAPEnvelope() 
     106        soapRequest.create() 
     107        soapRequest.body.elem.append(elem) 
     108         
     109        request = soapRequest.serialize() 
     110         
     111        header = { 
     112            'soapAction': "http://www.oasis-open.org/committees/security", 
     113            'Content-length': str(len(request)), 
     114            'Content-type': 'text/xml' 
     115        } 
     116        response = self.app.post('/attributeauthority',  
     117                                 params=request,  
     118                                 headers=header,  
     119                                 status=200) 
     120        print response.status 
     121        print response.body 
    69122         
    70123 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/saml/test_saml.py

    r5528 r5538  
    1414from datetime import datetime 
    1515from uuid import uuid4 
     16from cStringIO import StringIO 
    1617 
    1718import unittest 
     
    2122from ndg.security.common.saml import Assertion, Attribute, AttributeValue, \ 
    2223    AttributeStatement, SAMLVersion, XSStringAttributeValue, \ 
    23     AttributeQuery 
     24    XSGroupRoleAttributeValue, AttributeQuery, Issuer, Subject, NameID 
    2425from ndg.security.common.saml.xml import XMLConstants 
    2526from ndg.security.common.saml.xml.etree import AssertionETreeObject, \ 
    26     XSGroupRoleAttributeValueETreeObject 
     27    XSGroupRoleAttributeValueETreeObject, AttributeQueryETreeObject 
    2728 
    2829 
     
    7576 
    7677        attributeStatement = AttributeStatement() 
    77  
     78         
     79        for attribute in self.createAttributes(): 
     80            attributeStatement.attributes.append(attribute) 
     81             
     82        return assertion 
     83 
     84    def buildAttributeQuery(self, issuer, subjectNameID): 
     85         
     86        attributeQuery = AttributeQuery() 
     87        attributeQuery.version = SAMLVersion(SAMLVersion.VERSION_20) 
     88        attributeQuery.id = str(uuid4()) 
     89        attributeQuery.issueInstant = datetime.utcnow() 
     90         
     91        attributeQuery.issuer = Issuer() 
     92        attributeQuery.issuer.format = Issuer.X509_SUBJECT 
     93        attributeQuery.issuer.value = issuer 
     94                         
     95        attributeQuery.subject = Subject()   
     96        attributeQuery.subject.nameID = NameID() 
     97        attributeQuery.subject.nameID.format = "urn:esg:openid" 
     98        attributeQuery.subject.nameID.value = subjectNameID 
     99                                     
     100        attributeQuery.attributes = self.createAttributes() 
     101         
     102        return attributeQuery 
     103     
     104    def createAttributes(self): 
     105         
     106        attributes = [] 
    78107        if self.firstName is not None:     
    79108            # special case handling for 'FirstName' attribute 
     
    87116            fnAttribute.attributeValues.append(firstName) 
    88117 
    89             attributeStatement.attributes.append(fnAttribute) 
     118            attributes.append(fnAttribute) 
    90119         
    91120 
     
    101130            lnAttribute.attributeValues.append(lastName) 
    102131 
    103             attributeStatement.attributes.append(lnAttribute) 
     132            attributes.append(lnAttribute) 
    104133         
    105134 
     
    116145            emailAddressAttribute.attributeValues.append(emailAddress) 
    117146 
    118             attributeStatement.attributes.append(emailAddressAttribute) 
     147            attributes.append(emailAddressAttribute) 
    119148         
    120149        if len(self.__groupRoleList) > 0: 
     
    132161                groupRoleAttribute.attributeValues.append(groupRole) 
    133162             
    134             attributeStatement.attributes.append(groupRoleAttribute) 
     163            attributes.append(groupRoleAttribute) 
    135164         
    136165        for name, value in self.__miscAttrList: 
     
    143172            attribute.attributeValues.append(stringAttributeValue) 
    144173 
    145             # add all attributes to the attribute statement 
    146             attributeStatement.attributes.append(attribute) 
     174            attributes.append(attribute) 
    147175             
    148         assertion.attributeStatements.append(attributeStatement) 
    149         return assertion 
     176        return attributes 
     177 
    150178 
    151179class SAMLTestCase(unittest.TestCase): 
     
    204232 
    205233    def test02CreateAttributeQuery(self): 
    206         attributeQuery = AttributeQuery() 
    207  
     234        samlUtil = SAMLUtil() 
     235        samlUtil.firstName = '' 
     236        samlUtil.lastName = '' 
     237        samlUtil.emailAddress = '' 
     238        attributeQuery = samlUtil.buildAttributeQuery( 
     239                        "/O=NDG/OU=BADC/CN=attributeauthority.badc.rl.ac.uk", 
     240                        "https://openid.localhost/philip.kershaw") 
     241         
     242        attributeQueryETreeObject = AttributeQueryETreeObject() 
     243        attributeQueryETreeObject.create(attributeQuery) 
     244        xmlOutput = attributeQueryETreeObject.prettyPrint() 
     245        print(xmlOutput) 
     246 
     247    def test03ParseAttributeQuery(self): 
     248        samlUtil = SAMLUtil() 
     249        samlUtil.firstName = '' 
     250        samlUtil.lastName = '' 
     251        samlUtil.emailAddress = '' 
     252        attributeQuery = samlUtil.buildAttributeQuery( 
     253                        "/O=NDG/OU=BADC/CN=attributeauthority.badc.rl.ac.uk", 
     254                        "https://openid.localhost/philip.kershaw") 
     255         
     256        attributeQueryETreeObject = AttributeQueryETreeObject() 
     257        attributeQueryETreeObject.create(attributeQuery) 
     258        xmlOutput = attributeQueryETreeObject.prettyPrint() 
     259         
     260        attributeQueryETreeObject2 = AttributeQueryETreeObject() 
     261         
     262        attributeQueryStream = StringIO() 
     263        attributeQueryStream.write(xmlOutput) 
     264        attributeQueryStream.seek(0) 
     265         
     266        attributeQuery2=attributeQueryETreeObject2.parse(attributeQueryStream) 
     267        xmlOutput2 = attributeQuery2.serialize() 
     268        self.assert_(xmlOutput == xmlOutput2) 
     269         
     270         
    208271if __name__ == "__main__": 
    209272    unittest.main()         
Note: See TracChangeset for help on using the changeset viewer.