Changeset 6553 for TI12-security


Ignore:
Timestamp:
10/02/10 17:04:46 (10 years ago)
Author:
pjkersha
Message:

Unit testing AuthzDecisionStatement? added to a Response.

Location:
TI12-security/trunk/ndg_security_saml/saml
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/ndg_security_saml/saml/saml2/core.py

    r6547 r6553  
    322322        ''' 
    323323        raise NotImplementedError() 
    324              
     324 
     325 
     326class DecisionType(object): 
     327    """Define decision types for the authorisation decisions""" 
     328     
     329    # "Permit" decision type 
     330    PERMIT = "Permit" 
     331     
     332    # "Deny" decision type 
     333    DENY = "Deny" 
     334     
     335    # "Indeterminate" decision type 
     336    INDETERMINATE = "Indeterminate" 
     337         
     338    TYPES = (PERMIT, DENY, INDETERMINATE) 
     339     
     340    __slots__ = ('__value',) 
     341     
     342    def __init__(self, decisionType): 
     343        self.__value = None 
     344        self.value = decisionType 
     345 
     346    def _setValue(self, value): 
     347        if not isinstance(value, basestring): 
     348            raise TypeError('Expecting string type for "value" attribute; got ' 
     349                            'instead' % type(value)) 
     350             
     351        if value not in DecisionType.TYPES: 
     352            raise AttributeError('Permissable decision types are %r; got %r ' 
     353                                 'instead' % (DecisionType.TYPES, 
     354                                              value)) 
     355        self.__value = value 
     356         
     357    def _getValue(self): 
     358        return self.__value 
     359     
     360    value = property(fget=_getValue, fset=_setValue, doc="Decision value") 
     361     
     362    def __str__(self): 
     363        return self.__value 
     364 
    325365 
    326366class AuthzDecisionStatement(Statement): 
     
    359399 
    360400        # Resource attribute value.  
    361         self.__resource = None 
     401        self.__resource = None   
     402         
     403        self.__decision = DecisionType(DecisionType.INDETERMINATE)     
     404        self.__actions = TypedList(Action) 
     405        self.__evidence = None 
    362406         
    363407        # Tuning for normalization of resource URIs in property set method 
     
    454498        @return: the decision of the authorization request 
    455499        ''' 
    456         raise NotImplementedError() 
     500        return self.__decision 
    457501 
    458502    def _setDecision(self, value): 
     
    462506        @param value: the decision of the authorization request 
    463507        ''' 
    464         raise NotImplementedError() 
     508        if not isinstance(value, basestring): 
     509            raise TypeError('Expecting %r type for "decision" attribute; ' 
     510                            'got instead' % (DecisionType, type(value))) 
     511        self.__decision = value 
    465512     
    466513    @property 
     
    10431090        # TODO: Implement AuthnStatement and AuthzDecisionStatement classes 
    10441091        self.__authnStatements = [] 
    1045         self.__authzDecisionStatements = [] 
     1092        self.__authzDecisionStatements = TypedList(AuthzDecisionStatement) 
    10461093        self.__attributeStatements = TypedList(AttributeStatement) 
    10471094         
     
    11661213                      doc="Attribute Assertion advice") 
    11671214     
    1168     def _get_statements(self): 
    1169         """Get statements string.""" 
     1215    @property 
     1216    def statements(self): 
     1217        """Attribute Assertion statements""" 
    11701218        return self.__statements 
    1171  
    1172     statements = property(fget=_get_statements, 
    1173                           doc="Attribute Assertion statements") 
    1174      
    1175     def _get_authnStatements(self): 
    1176         """Get authnStatements string.""" 
     1219     
     1220    @property 
     1221    def authnStatements(self): 
     1222        """Attribute Assertion authentication""" 
    11771223        return self.__authnStatements 
    1178  
    1179     authnStatements = property(fget=_get_authnStatements, 
    1180                                doc="Attribute Assertion authentication " 
    1181                                    "statements") 
    1182      
    1183     def _get_authzDecisionStatements(self): 
    1184         """Get authorisation decision statements.""" 
     1224     
     1225    @property 
     1226    def authzDecisionStatements(self): 
     1227        """Attribute Assertion authorisation decision statements""" 
    11851228        return self.__authzDecisionStatements 
    1186  
    1187     authzDecisionStatements = property(fget=_get_authzDecisionStatements, 
    1188                                        doc="Attribute Assertion authorisation " 
    1189                                            "decision statements") 
    1190      
    1191     def _get_attributeStatements(self): 
    1192         """Get attributeStatements string.""" 
     1229     
     1230    @property 
     1231    def attributeStatements(self): 
     1232        """Attribute Assertion attribute statements""" 
    11931233        return self.__attributeStatements 
    1194  
    1195     attributeStatements = property(fget=_get_attributeStatements, 
    1196                                    doc="Attribute Assertion attribute " 
    1197                                        "statements") 
    11981234     
    11991235 
     
    16521688    UNIX_NS_URI = "urn:oasis:names:tc:SAML:1.0:action:unix" 
    16531689 
     1690    ACTION_NS_IDENTIFIERS = ( 
     1691        RWEDC_NS_URI, 
     1692        RWEDC_NEGATION_NS_URI,     
     1693        GHPP_NS_URI, 
     1694        UNIX_NS_URI        
     1695    ) 
     1696     
    16541697    # Read action.  
    16551698    READ_ACTION = "Read" 
     
    16941737    HTTP_POST_ACTION = "POST" 
    16951738     
     1739    ACTION_TYPES = { 
     1740        RWEDC_NS_URI: (READ_ACTION, WRITE_ACTION, EXECUTE_ACTION, DELETE_ACTION, 
     1741                       CONTROL_ACTION), 
     1742        RWEDC_NEGATION_NS_URI: (READ_ACTION, WRITE_ACTION, EXECUTE_ACTION,  
     1743                                DELETE_ACTION, CONTROL_ACTION, NEG_READ_ACTION,  
     1744                                NEG_WRITE_ACTION, NEG_EXECUTE_ACTION,  
     1745                                NEG_CONTROL_ACTION),     
     1746        GHPP_NS_URI: (HTTP_GET_ACTION, HTTP_HEAD_ACTION, HTTP_PUT_ACTION, 
     1747                      HTTP_POST_ACTION), 
     1748                       
     1749        # This namespace uses octal bitmask for file permissions 
     1750        UNIX_NS_URI: ()    
     1751    } 
     1752     
    16961753    def __init__(self, **kw): 
    16971754        '''Create an authorization action type 
     
    16991756        super(Action, self).__init__(**kw) 
    17001757 
    1701         # URI of the Namespace of this action 
    1702         self.__namespace = None 
     1758        # URI of the Namespace of this action.  Default to read/write/negation  
     1759        # type - 2.7.4.2 SAML 2 Core Spec. 15 March 2005 
     1760        self.__namespace = Action.RWEDC_NEGATION_NS_URI 
    17031761 
    17041762        #Value value 
    17051763        self.__action = None        
    17061764     
     1765        self.__actionTypes = Action.ACTION_TYPES 
     1766 
     1767    def _getActionTypes(self): 
     1768        return self.__actionTypes 
     1769 
     1770    def _setActionTypes(self, value): 
     1771        if not isinstance(value, dict): 
     1772            raise TypeError('Expecting list or tuple type for "actionTypes" ' 
     1773                            'attribute; got %r' % type(value)) 
     1774             
     1775        for k, v in value.items(): 
     1776            if not isinstance(v, (tuple, type(None))): 
     1777                raise TypeError('Expecting None or tuple type for ' 
     1778                                '"actionTypes" dictionary values; got %r for ' 
     1779                                '%r key' % (type(value), k)) 
     1780        self.__actionTypes = value 
     1781 
     1782    actionTypes = property(_getActionTypes,  
     1783                           _setActionTypes,  
     1784                           doc="Restrict vocabulary of action types") 
     1785         
    17071786    def _getNamespace(self): 
    17081787        ''' 
    1709         gets the namespace scope of the specifiedvalue. 
    1710          
    1711         @return: the namespace scope of the specifiedvalue 
     1788        gets the namespace scope of the specified value. 
     1789         
     1790        @return: the namespace scope of the specified value 
    17121791        ''' 
    17131792        return self.__namespace 
     
    17151794    def _setNamespace(self, value): 
    17161795        ''' 
    1717         Sets the namespace scope of the specifiedvalue. 
    1718          
    1719         @param value: the namespace scope of the specifiedvalue 
     1796        Sets the namespace scope of the specified value. 
     1797         
     1798        @param value: the namespace scope of the specified value 
    17201799        ''' 
    17211800        if not isinstance(value, basestring): 
    17221801            raise TypeError('Expecting string type for "namespace" ' 
    17231802                            'attribute; got %r' % type(value)) 
     1803             
     1804        if value not in self.__actionTypes.keys(): 
     1805            raise AttributeError('"namespace" action type %r not recognised. ' 
     1806                                 'It must be one of these action types: %r' %  
     1807                                 self.__actionNsIdentifiers) 
     1808             
    17241809        self.__namespace = value 
    17251810 
     
    17381823        Sets the URI of the action to be performed. 
    17391824         
    1740         @param value: the URI of thevalue to be performed 
    1741         ''' 
    1742         if not isinstance(value, basestring): 
    1743             raise TypeError('Expecting string type for "action" ' 
     1825        @param value: the URI of the value to be performed 
     1826        ''' 
     1827        # int and oct allow for UNIX file permissions action type 
     1828        if not isinstance(value, (basestring, int)): 
     1829            raise TypeError('Expecting string or int type for "action" ' 
    17441830                            'attribute; got %r' % type(value)) 
     1831             
     1832        # Default to read/write/negation type - 2.7.4.2 SAML 2 Core Spec. 
     1833        # 15 March 2005 
     1834        allowedActions = self.__actionTypes.get(self.__namespace, 
     1835                                                Action.RWEDC_NEGATION_NS_URI) 
     1836         
     1837        # Only apply restriction for action type that has a restricted  
     1838        # vocabulary - UNIX type is missed out of this because its an octal 
     1839        # mask 
     1840        if len(allowedActions) > 0 and value not in allowedActions: 
     1841            raise AttributeError('%r action not recognised; known actions for ' 
     1842                                 'the %r namespace identifier are: %r.  '  
     1843                                 'If this is not as expected make sure to set ' 
     1844                                 'the "namespace" attribute to an alternative ' 
     1845                                 'value first or override completely by ' 
     1846                                 'explicitly setting the "allowTypes" ' 
     1847                                 'attribute' %  
     1848                                 (value, self.__namespace, allowedActions)) 
    17451849        self.__value = value 
    17461850 
  • TI12-security/trunk/ndg_security_saml/saml/test/test_saml.py

    r6547 r6553  
    2222 
    2323from saml.saml2.core import (SAMLVersion, Attribute, AttributeStatement,  
    24                              Assertion, AttributeQuery, Response, Issuer,  
    25                              Subject, NameID, StatusCode,  
     24                             AuthzDecisionStatement, Assertion, AttributeQuery,  
     25                             Response, Issuer, Subject, NameID, StatusCode,  
    2626                             StatusMessage, Status, Conditions,  
    2727                             XSStringAttributeValue, Action, 
     
    196196        for action, namespace in actions: 
    197197            authzDecisionQuery.actions.append(Action()) 
     198            authzDecisionQuery.actions[-1].namespace = namespace 
    198199            authzDecisionQuery.actions[-1].value = action 
    199             authzDecisionQuery.actions[-1].namespace = namespace 
    200200             
    201201        return authzDecisionQuery 
     
    210210    RESOURCE_URI = SAMLUtil.RESOURCE_URI 
    211211     
    212     def _createAssertionHelper(self): 
     212    def _createAttributeAssertionHelper(self): 
    213213        samlUtil = SAMLUtil() 
    214214         
     
    237237    def test01CreateAssertion(self): 
    238238          
    239         assertion = self._createAssertionHelper() 
     239        assertion = self._createAttributeAssertionHelper() 
    240240 
    241241         
     
    254254 
    255255    def test02ParseAssertion(self): 
    256         assertion = self._createAssertionHelper() 
     256        assertion = self._createAttributeAssertionHelper() 
    257257         
    258258        # Create ElementTree Assertion Element 
     
    327327        print("_"*80) 
    328328 
    329     def test05CreateResponse(self): 
     329    def test05CreateAttributeQueryResponse(self): 
    330330        response = Response() 
    331331        response.issueInstant = datetime.utcnow() 
     
    347347        response.status.statusMessage.value = "Response created successfully" 
    348348            
    349         assertion = self._createAssertionHelper() 
     349        assertion = self._createAttributeAssertionHelper() 
    350350         
    351351        # Add a conditions statement for a validity of 8 hours 
     
    407407         
    408408        authzDecisionQuery.actions.append(Action()) 
     409        authzDecisionQuery.actions[0].namespace = Action.GHPP_NS_URI 
    409410        authzDecisionQuery.actions[0].value = Action.HTTP_GET_ACTION 
    410         authzDecisionQuery.actions[0].namespace = Action.GHPP_NS_URI 
    411411         
    412412        self.assert_( 
     
    414414        self.assert_( 
    415415            authzDecisionQuery.actions[0].namespace == Action.GHPP_NS_URI) 
     416         
     417        # Try out the restricted vocabulary 
     418        try: 
     419            authzDecisionQuery.actions[0].value = "delete everything" 
     420            self.fail("Expecting AttributeError raised for incorrect action " 
     421                      "setting.") 
     422        except AttributeError, e: 
     423            print("Caught incorrect action type setting: %s" % e) 
     424         
     425        authzDecisionQuery.actions[0].actionTypes = {'urn:malicious':  
     426                                                     ("delete everything",)} 
     427         
     428        # Try again now that the actipn types have been adjusted 
     429        authzDecisionQuery.actions[0].namespace = 'urn:malicious' 
     430        authzDecisionQuery.actions[0].value = "delete everything" 
    416431         
    417432    def test07SerializeAuthzDecisionQuery(self): 
     
    471486        self.assert_(authzDecisionQuery2.evidence is None) 
    472487 
     488 
     489    def test05CreateAuthzDecisionQueryResponse(self): 
     490        response = Response() 
     491        response.issueInstant = datetime.utcnow() 
     492         
     493        # Make up a request ID that this response is responding to 
     494        response.inResponseTo = str(uuid4()) 
     495        response.id = str(uuid4()) 
     496        response.version = SAMLVersion(SAMLVersion.VERSION_20) 
     497             
     498        response.issuer = Issuer() 
     499        response.issuer.format = Issuer.X509_SUBJECT 
     500        response.issuer.value = \ 
     501                        SAMLTestCase.ISSUER_DN 
     502         
     503        response.status = Status() 
     504        response.status.statusCode = StatusCode() 
     505        response.status.statusCode.value = StatusCode.SUCCESS_URI 
     506        response.status.statusMessage = StatusMessage()         
     507        response.status.statusMessage.value = "Response created successfully" 
     508            
     509        assertion = Assertion() 
     510        authzDecisionStatement = AuthzDecisionStatement() 
     511        authzDecisionStatement.resource = SAMLTestCase.RESOURCE_URI 
     512        authzDecisionStatement.actions.append(Action()) 
     513        authzDecisionStatement.actions[-1].namespace = Action.GHPP_NS_URI 
     514        authzDecisionStatement.actions[-1].value = Action.HTTP_GET_ACTION 
     515        assertion.authzDecisionStatements.append(authzDecisionStatement) 
     516         
     517#        assertion.subject = Subject()   
     518#        assertion.subject.nameID = NameID() 
     519#        assertion.subject.nameID.format = SAMLTestCase.NAMEID_FORMAT 
     520#        assertion.subject.nameID.value = SAMLTestCase.NAMEID_VALUE     
     521#             
     522#        assertion.issuer = Issuer() 
     523#        assertion.issuer.format = Issuer.X509_SUBJECT 
     524#        assertion.issuer.value = SAMLTestCase.ISSUER_DN 
     525 
     526        response.assertions.append(assertion) 
     527         
     528        # Create ElementTree Assertion Element 
     529        responseElem = ResponseElementTree.toXML(response) 
     530         
     531        self.assert_(iselement(responseElem)) 
     532         
     533        # Serialise to output         
     534        xmlOutput = prettyPrint(responseElem)        
     535        self.assert_(len(xmlOutput)) 
     536        print("\n"+"_"*80) 
     537        print(xmlOutput) 
     538        print("_"*80) 
     539 
    473540        
    474541if __name__ == "__main__": 
  • TI12-security/trunk/ndg_security_saml/saml/xml/etree.py

    r6547 r6553  
    4343                             AuthzDecisionQuery, Subject, NameID, Issuer,  
    4444                             Response, Status, StatusCode, StatusMessage,  
    45                              StatusDetail, Advice, Action, 
     45                             StatusDetail, Advice, Action, Evidence, 
    4646                             XSStringAttributeValue)  
    4747                              
     
    371371         
    372372        for authzDecisionStatement in assertion.authzDecisionStatements: 
    373             raise NotImplementedError("Assertion Authorisation Decision " 
    374                                       "Statement creation is not implemented") 
     373            authzDecisionStatementElem = AuthzDecisionStatementElementTree.toXML( 
     374                                        authzDecisionStatement, 
     375                                        **authzDecisionValueElementTreeFactoryKw) 
     376            elem.append(authzDecisionStatementElem) 
    375377             
    376378        for attributeStatement in assertion.attributeStatements: 
     
    417419            attributeValues.append(attributeValue) 
    418420         
    419         assertion = Assertion() 
     421        assertion = cls() 
    420422        assertion.version = SAMLVersion(attributeValues[0]) 
    421423        if assertion.version != SAMLVersion.VERSION_20: 
     
    451453                                          "parsing is not implemented") 
    452454         
    453             elif localName==AuthzDecisionStatement.DEFAULT_ELEMENT_LOCAL_NAME: 
    454                 raise NotImplementedError("Assertion Authorisation Decision " 
    455                                           "Statement parsing is not " 
    456                                           "implemented") 
     455            elif localName == AuthzDecisionStatement.DEFAULT_ELEMENT_LOCAL_NAME: 
     456                authzDecisionStatement = \ 
     457                    AuthzDecisionStatementElementTree.fromXML(childElem) 
     458                assertion.authzDecisionStatements.append(authzDecisionStatement) 
    457459             
    458460            elif localName == AttributeStatement.DEFAULT_ELEMENT_LOCAL_NAME: 
     
    463465            else: 
    464466                raise XMLTypeParseError('Assertion child element name "%s" ' 
    465                                           'not recognised' % localName) 
     467                                        'not recognised' % localName) 
    466468         
    467469        return assertion 
     
    533535         
    534536        return attributeStatement 
     537 
     538   
     539class AuthzDecisionStatementElementTree(AuthzDecisionStatement): 
     540    """ElementTree XML representation of AuthzDecisionStatement""" 
     541     
     542    @classmethod 
     543    def toXML(cls, authzDecisionStatement): 
     544        """Make a tree of a XML elements based on the authzDecision statement 
     545         
     546        @type assertion: saml.saml2.core.AuthzDecisionStatement 
     547        @param assertion: AuthzDecision Statement to be represented as an  
     548        ElementTree Element 
     549        factory 
     550        @rtype: ElementTree.Element 
     551        @return: ElementTree Element 
     552        """ 
     553        if not isinstance(authzDecisionStatement, AuthzDecisionStatement): 
     554            raise TypeError("Expecting %r type got: %r" %  
     555                            (AuthzDecisionStatement, authzDecisionStatement)) 
     556           
     557        if not authzDecisionStatement.resource: 
     558            raise AttributeError("Resource for AuthzDecisionStatement is not " 
     559                                 "set") 
     560               
     561        attrib = { 
     562            cls.DECISION_ATTRIB_NAME: authzDecisionStatement.decision, 
     563            cls.RESOURCE_ATTRIB_NAME: authzDecisionStatement.resource 
     564        } 
     565             
     566        tag = str(QName.fromGeneric(cls.DEFAULT_ELEMENT_NAME))   
     567        elem = ElementTree.Element(tag, **attrib) 
     568        ElementTree._namespace_map[cls.DEFAULT_ELEMENT_NAME.namespaceURI 
     569                                   ] = cls.DEFAULT_ELEMENT_NAME.prefix  
     570 
     571        for action in authzDecisionStatement.actions: 
     572            # Factory enables support for multiple authzDecision types 
     573            actionElem = ActionElementTree.toXML(action) 
     574            elem.append(actionElem) 
     575         
     576        if (authzDecisionStatement.evidence and  
     577            len(authzDecisionStatement.evidence.values) > 0): 
     578            raise NotImplementedError("authzDecisionStatementElementTree does " 
     579                                      "not currently support the Evidence type") 
     580             
     581        return elem 
     582     
     583    @classmethod 
     584    def fromXML(cls, elem, **authzDecisionValueElementTreeFactoryKw): 
     585        """Parse an ElementTree SAML AuthzDecisionStatement element into an 
     586        AuthzDecisionStatement object 
     587         
     588        @type elem: ElementTree.Element 
     589        @param elem: ElementTree element containing the AuthzDecisionStatement 
     590        @type authzDecisionValueElementTreeFactoryKw: dict 
     591        @param authzDecisionValueElementTreeFactoryKw: keywords for AuthzDecisionValue 
     592        factory 
     593        @rtype: saml.saml2.core.AuthzDecisionStatement 
     594        @return: AuthzDecision Statement""" 
     595         
     596        if not ElementTree.iselement(elem): 
     597            raise TypeError("Expecting %r input type for parsing; got %r" % 
     598                            (ElementTree.Element, elem)) 
     599 
     600        localName = QName.getLocalPart(elem.tag) 
     601        if localName != cls.DEFAULT_ELEMENT_LOCAL_NAME: 
     602            raise XMLTypeParseError("No \"%s\" element found" % 
     603                                    cls.DEFAULT_ELEMENT_LOCAL_NAME) 
     604         
     605         
     606        authzDecisionStatement = cls() 
     607 
     608        for childElem in elem: 
     609            localName = QName.getLocalPart(childElem.tag) 
     610             
     611            if localName == Action.DEFAULT_ELEMENT_LOCAL_NAME: 
     612                action = ActionElementTree.fromXML(childElem) 
     613                authzDecisionStatement.actions.append(action) 
     614                 
     615            elif localName == Evidence.DEFAULT_ELEMENT_LOCAL_NAME: 
     616                raise NotImplementedError("XML parse of %s element is not " 
     617                                          "implemented" % 
     618                                          Evidence.DEFAULT_ELEMENT_LOCAL_NAME) 
     619            else: 
     620                raise XMLTypeParseError("AuthzDecisionStatement child element " 
     621                                        "name %r not recognised" % localName) 
     622         
     623        return authzDecisionStatement 
    535624 
    536625 
Note: See TracChangeset for help on using the changeset viewer.