source: TI12-security/trunk/ndg_xacml/ndg/xacml/test/test_policy.py @ 7661

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/ndg_xacml/ndg/xacml/test/test_policy.py@7661
Revision 7661, 14.6 KB checked in by pjkersha, 10 years ago (diff)

ndg_xacml:

  • added support for custom AttributeValue? DataTypes? - this means that the ESGF GroupRole? attribute type can be added directly into XACML policies.
  • TODO: add support for adding custom functions so that a PDP can correctly apply rules based on custom types like the ESGF GroupRole?.
  • Property svn:keywords set to Id
Line 
1#!/usr/bin/env python
2"""NDG XACML Policy unit test package
3
4NERC DataGrid
5"""
6__author__ = "P J Kershaw"
7__date__ = "16/03/10"
8__copyright__ = "(C) 2010 Science and Technology Facilities Council"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__license__ = "BSD - see LICENSE file in top-level directory"
11__contact__ = "Philip.Kershaw@stfc.ac.uk"
12__revision__ = "$Id$"
13import unittest
14from os import path
15import logging
16logging.basicConfig(level=logging.DEBUG)
17
18from ndg.xacml.core.policy import Policy
19from ndg.xacml.core.attributedesignator import SubjectAttributeDesignator
20from ndg.xacml.core.attributeselector import AttributeSelector
21from ndg.xacml.core.attributevalue import (AttributeValueClassFactory, 
22                                           AttributeValue)
23from ndg.xacml.parsers.etree import QName
24from ndg.xacml.parsers.etree.factory import ReaderFactory
25from ndg.xacml.parsers.etree.attributevaluereader import (
26                                                DataTypeReaderClassFactory,
27                                                ETreeDataTypeReaderBase)
28
29from ndg.xacml.test import XACML_NDGTEST1_FILEPATH, THIS_DIR
30
31
32class GroupRoleAttributeValue(AttributeValue):
33    IDENTIFIER = 'urn:esgf:pcmdi:grouprole'
34    TYPE = dict
35    GROUPROLE_ELEMENT_LOCAL_NAME = 'groupRole'
36    GROUP_ELEMENT_LOCAL_NAME = 'group'
37    ROLE_ELEMENT_LOCAL_NAME = 'role'
38    ROLE_DEFAULT_VALUE = 'default'
39   
40    __slots__ = ('group', 'role')
41   
42    def __init__(self):
43        super(GroupRoleAttributeValue, self).__init__()
44        self.group = None
45        self.role = self.__class__.ROLE_DEFAULT_VALUE
46   
47   
48class ETreeGroupRoleDataTypeReader(ETreeDataTypeReaderBase):
49       
50    @classmethod
51    def parse(cls, elem, attributeValue):
52        """Parse ESG Group/Role type object
53
54        @param obj: input object to parse
55        @type obj: ElementTree Element, or stream object
56        @return: ElementTree element
57        @rtype: xml.etree.Element
58        """
59        if len(elem) != 1:
60            raise XMLParseError("Expecting single groupRole child element but " 
61                                "found only %d element(s)" % len(elem))
62                     
63        groupRoleElem = elem[0]
64       
65        if (QName.getLocalPart(groupRoleElem.tag) != 
66            attributeValue.__class__.GROUPROLE_ELEMENT_LOCAL_NAME):
67            raise XMLParseError("%r element found, expecting \"%s\" element " 
68                                "instead" % 
69                                xacmlType.GROUPROLE_ELEMENT_LOCAL_NAME)
70       
71        # Allow for any of the defined Expression sub-types in the child
72        # elements
73        for subElem in groupRoleElem:
74            localName = QName.getLocalPart(subElem.tag)
75            if localName == attributeValue.__class__.ROLE_ELEMENT_LOCAL_NAME:
76                attributeValue.role = subElem.text
77            elif localName == attributeValue.__class__.GROUP_ELEMENT_LOCAL_NAME:
78                attributeValue.group = subElem.text
79            else:
80                raise XMLParseError('%r ESG Group/Role sub-element not '
81                                    'recognised' % localName) 
82                               
83   
84class XACMLPolicyTestCase(unittest.TestCase):
85    XACML_TEST1_FILENAME = "rule1.xml"
86    XACML_TEST1_FILEPATH = path.join(THIS_DIR, XACML_TEST1_FILENAME)
87    XACML_TEST2_FILENAME = "rule2.xml"
88    XACML_TEST2_FILEPATH = path.join(THIS_DIR, XACML_TEST2_FILENAME)
89    XACML_TEST3_FILENAME = "rule3.xml"
90    XACML_TEST3_FILEPATH = path.join(THIS_DIR, XACML_TEST3_FILENAME)
91    XACML_TEST4_FILENAME = "rule4.xml"
92    XACML_TEST4_FILEPATH = path.join(THIS_DIR, XACML_TEST4_FILENAME)
93    XACML_ESGFTEST1_FILENAME = "esgf1.xml"
94    XACML_ESGFTEST1_FILEPATH = path.join(THIS_DIR, XACML_ESGFTEST1_FILENAME)
95   
96    def test01ETreeParseRule1Policy(self):
97        PolicyReader = ReaderFactory.getReader(Policy)
98        policy = PolicyReader.parse(XACMLPolicyTestCase.XACML_TEST1_FILEPATH)
99        self.assert_(policy)
100       
101        self.assert_(
102            policy.policyId == "urn:oasis:names:tc:example:SimplePolicy1")
103       
104        self.assert_(policy.ruleCombiningAlgId == \
105        "urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides")
106       
107        self.assert_(
108            "Med Example Corp access control policy" in policy.description)
109       
110        self.assert_(len(policy.target.subjects) == 0)
111       
112        self.assert_(policy.rules[0].id == \
113                     "urn:oasis:names:tc:xacml:2.0:example:SimpleRule1")
114       
115        self.assert_(policy.rules[0].effect == 'Permit')
116       
117        self.assert_(
118            'Any subject with an e-mail name in the med.example.com domain' in \
119            policy.rules[0].description)
120       
121        self.assert_(len(policy.rules[0].target.subjects) == 1)
122        self.assert_(len(policy.rules[0].target.actions) == 0)
123        self.assert_(len(policy.rules[0].target.resources) == 0)
124        self.assert_(len(policy.rules[0].target.environments) == 0)
125       
126        self.assert_(len(policy.rules[0].target.subjects[0
127                                                         ].subjectMatches) == 1)
128       
129        self.assert_(policy.rules[0].target.subjects[0].subjectMatches[0
130            ].matchId == \
131            "urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match")
132       
133        self.assert_(policy.rules[0].target.subjects[0].subjectMatches[0
134            ].attributeValue.dataType == \
135            "urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name")
136       
137        self.assert_(policy.rules[0].target.subjects[0].subjectMatches[0
138            ].attributeDesignator.dataType == \
139            "urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name")
140       
141        # Attribute ID
142        self.assert_(policy.rules[0].target.subjects[0].subjectMatches[0
143            ].attributeDesignator.attributeId == \
144            "urn:oasis:names:tc:xacml:1.0:subject:subject-id")
145         
146    def test02ETreeParseRule2Policy(self):
147        PolicyReader = ReaderFactory.getReader(Policy)
148        policy = PolicyReader.parse(XACMLPolicyTestCase.XACML_TEST2_FILEPATH)
149        self.assert_(policy)
150       
151        self.assert_(
152        policy.policyId == "urn:oasis:names:tc:xacml:2.0:example:policyid:2")
153       
154        self.assert_(policy.ruleCombiningAlgId == \
155        "urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides")
156       
157        self.assert_(policy.description is None)
158       
159        self.assert_(len(policy.target.actions) == 0)
160       
161        self.assert_(policy.rules[0].id == \
162                     "urn:oasis:names:tc:xacml:2.0:example:ruleid:2")
163       
164        self.assert_(policy.rules[0].effect == 'Permit')
165       
166        self.assert_(policy.rules[0].description == """\
167A person may read any medical record in the
168            http://www.med.example.com/records.xsd namespace
169            for which he or she is the designated parent or guardian,
170            and for which the patient is under 16 years of age""")
171       
172        self.assert_(len(policy.rules[0].target.subjects) == 0)
173        self.assert_(len(policy.rules[0].target.actions) == 1)
174        self.assert_(len(policy.rules[0].target.resources) == 1)
175        self.assert_(len(policy.rules[0].target.environments) == 0)
176       
177        self.assert_(len(policy.rules[0].target.resources[0
178                                                    ].resourceMatches) == 2)
179       
180        self.assert_(policy.rules[0].target.resources[0].resourceMatches[0
181            ].matchId == "urn:oasis:names:tc:xacml:1.0:function:string-equal")
182       
183        self.assert_(policy.rules[0].target.resources[0].resourceMatches[0
184            ].attributeValue.dataType == \
185                                    "http://www.w3.org/2001/XMLSchema#string")
186       
187        self.assert_(policy.rules[0].target.resources[0].resourceMatches[0
188            ].attributeValue.value == 'urn:med:example:schemas:record')
189       
190        self.assert_(policy.rules[0].target.resources[0].resourceMatches[0
191            ].attributeDesignator.dataType == \
192                                    "http://www.w3.org/2001/XMLSchema#string")
193       
194        self.assert_(policy.rules[0].target.resources[0].resourceMatches[1
195            ].attributeDesignator.attributeId == \
196                            "urn:oasis:names:tc:xacml:1.0:resource:xpath")
197        self.assert_(policy.rules[0].target.resources[0].resourceMatches[1
198            ].matchId == \
199                "urn:oasis:names:tc:xacml:1.0:function:xpath-node-match")
200       
201        self.assert_(policy.rules[0].target.resources[0].resourceMatches[1
202            ].attributeValue.dataType == \
203                                    "http://www.w3.org/2001/XMLSchema#string")
204       
205        self.assert_(policy.rules[0].target.resources[0].resourceMatches[1
206            ].attributeValue.value == '/md:record')
207       
208        self.assert_(policy.rules[0].target.resources[0].resourceMatches[1
209            ].attributeDesignator.dataType == \
210                                    "http://www.w3.org/2001/XMLSchema#string")
211       
212        self.assert_(policy.rules[0].target.resources[0].resourceMatches[1
213            ].attributeDesignator.attributeId == \
214                                "urn:oasis:names:tc:xacml:1.0:resource:xpath")
215       
216        # Verify Action
217        self.assert_(len(policy.rules[0].target.actions[0
218                                                    ].actionMatches) == 1)
219       
220        self.assert_(policy.rules[0].target.actions[0].actionMatches[0
221            ].matchId == "urn:oasis:names:tc:xacml:1.0:function:string-equal")
222       
223        self.assert_(policy.rules[0].target.actions[0].actionMatches[0
224            ].attributeValue.dataType == \
225                                    "http://www.w3.org/2001/XMLSchema#string")
226       
227        self.assert_(policy.rules[0].target.actions[0].actionMatches[0
228            ].attributeValue.value == "read")
229       
230        self.assert_(policy.rules[0].target.actions[0].actionMatches[0
231            ].attributeDesignator.dataType == \
232                                    "http://www.w3.org/2001/XMLSchema#string")
233       
234        self.assert_(policy.rules[0].target.actions[0].actionMatches[0
235            ].attributeDesignator.attributeId == \
236                            "urn:oasis:names:tc:xacml:1.0:action:action-id")
237
238        self.assert_(policy.rules[0].condition)       
239        self.assert_(policy.rules[0].condition.expression.functionId == \
240                     "urn:oasis:names:tc:xacml:1.0:function:and")
241       
242        self.assert_(len(policy.rules[0].condition.expression.expressions) == 1)
243       
244        self.assert_(policy.rules[0].condition.expression.expressions[0
245            ].functionId == \
246                'urn:oasis:names:tc:xacml:1.0:function:string-equal')
247       
248        self.assert_(len(policy.rules[0].condition.expression.expressions) == 1)
249       
250        self.assert_(len(policy.rules[0].condition.expression.expressions[0
251                     ].expressions) == 2)
252       
253        self.assert_(policy.rules[0].condition.expression.expressions[0
254            ].expressions[0].functionId == \
255                "urn:oasis:names:tc:xacml:1.0:function:string-one-and-only")
256       
257        self.assert_(isinstance(
258                        policy.rules[0].condition.expression.expressions[0
259                            ].expressions[0
260                            ].expressions[0], SubjectAttributeDesignator))
261       
262        self.assert_(policy.rules[0].condition.expression.expressions[0
263                            ].expressions[0
264                            ].expressions[0].attributeId == \
265                            "urn:oasis:names:tc:xacml:2.0:example:attribute:"
266                            "parent-guardian-id")
267
268        self.assert_(policy.rules[0].condition.expression.expressions[0
269                            ].expressions[0
270                            ].expressions[0].dataType == \
271                            "http://www.w3.org/2001/XMLSchema#string")
272       
273        self.assert_(policy.rules[0].condition.expression.expressions[0
274                            ].expressions[0
275                            ].expressions[0].attributeId == \
276                            "urn:oasis:names:tc:xacml:2.0:example:attribute:"
277                            "parent-guardian-id")
278       
279        self.assert_(isinstance(policy.rules[0
280                            ].condition.expression.expressions[0
281                            ].expressions[1
282                            ].expressions[0], AttributeSelector))
283       
284        self.assert_(policy.rules[0
285                            ].condition.expression.expressions[0
286                            ].expressions[1
287                            ].expressions[0].requestContextPath == \
288                            "//md:record/md:parentGuardian/md:parentGuardianId/"
289                            "text()")
290       
291        self.assert_(policy.rules[0
292                            ].condition.expression.expressions[0
293                            ].expressions[1
294                            ].expressions[0].dataType == \
295                            "http://www.w3.org/2001/XMLSchema#string")
296
297    def test03ETreeParseRule3Policy(self):
298        PolicyReader = ReaderFactory.getReader(Policy)
299       
300        try:
301            policy = PolicyReader.parse(
302                                    XACMLPolicyTestCase.XACML_TEST3_FILEPATH)
303            self.assert_(policy)
304        except NotImplementedError, e:
305            print("Expecting Obligations not implemented exception: %s" %e)
306                   
307    def test04ETreeParseRule4Policy(self):
308        PolicyReader = ReaderFactory.getReader(Policy)
309        policy = PolicyReader.parse(XACMLPolicyTestCase.XACML_TEST4_FILEPATH)
310        self.assert_(policy)
311                   
312    def test05ETreeParseNdg1Policy(self):
313        # Example policy for URI Regular expression based matching of
314        # resources for NDG
315        PolicyReader = ReaderFactory.getReader(Policy)
316        policy = PolicyReader.parse(XACML_NDGTEST1_FILEPATH)
317        self.assert_(policy)   
318                   
319    def test05ETreeParseEsgf1Policy(self):
320        # Example policy with custom attribute value type used with ESGF
321       
322        # Add new type
323        AttributeValueClassFactory.addClass('urn:esgf:pcmdi:grouprole', 
324                                            GroupRoleAttributeValue)
325       
326        # Add new parser for this type
327        DataTypeReaderClassFactory.addReader('urn:esgf:pcmdi:grouprole', 
328                                ETreeGroupRoleDataTypeReader)
329       
330        PolicyReader = ReaderFactory.getReader(Policy)
331        policy = PolicyReader.parse(self.__class__.XACML_ESGFTEST1_FILEPATH)
332        self.assert_(policy) 
333       
334       
335if __name__ == "__main__":
336    unittest.main()
Note: See TracBrowser for help on using the repository browser.