source: TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/xacml/policy.py @ 6731

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/xacml/policy.py@6731
Revision 6731, 7.0 KB checked in by pjkersha, 10 years ago (diff)

Work on XACML !ETree based parsing. Added first basic unit test.

Line 
1'''
2Created on 24 Feb 2010
3
4@author: pjkersha
5'''
6from ndg.security.common.utils import TypedList
7from ndg.security.common.authz.xacml import PolicyComponent
8from ndg.security.common.authz.xacml.rule import Rule
9from ndg.security.common.authz.xacml.obligation import Obligation
10
11
12class PolicyParseError(Exception):
13    """Error reading policy attributes from file"""
14
15
16class InvalidPolicyXmlNsError(PolicyParseError):
17    """Invalid XML namespace for policy document"""
18
19'''   
20    <xs:complexType name="PolicyType">
21        <xs:sequence>
22            <xs:element ref="xacml:Description" minOccurs="0"/>
23            <xs:element ref="xacml:PolicyDefaults" minOccurs="0"/>
24            <xs:element ref="xacml:CombinerParameters" minOccurs="0"/>
25            <xs:element ref="xacml:Target"/>
26            <xs:choice maxOccurs="unbounded">
27                <xs:element ref="xacml:CombinerParameters" minOccurs="0"/>
28                <xs:element ref="xacml:RuleCombinerParameters" minOccurs="0"/>
29                <xs:element ref="xacml:VariableDefinition"/>
30                <xs:element ref="xacml:Rule"/>
31            </xs:choice>
32            <xs:element ref="xacml:Obligations" minOccurs="0"/>
33        </xs:sequence>
34        <xs:attribute name="PolicyId" type="xs:anyURI" use="required"/>
35        <xs:attribute name="Version" type="xacml:VersionType" default="1.0"/>
36        <xs:attribute name="RuleCombiningAlgId" type="xs:anyURI" use="required"/>
37    </xs:complexType>
38''' 
39
40class Policy(PolicyComponent):
41    """NDG MSI Policy.""" 
42    DEFAULT_XACML_VERSION = "1.0"
43    ELEMENT_LOCAL_NAME = "Policy"
44    POLICY_ID_ATTRIB_NAME = "PolicyId"
45    RULE_COMBINING_ALG_ID_ATTRIB_NAME = "RuleCombiningAlgId"
46    VERSION_ATTRIB_NAME = "Version"
47
48    DESCRIPTION_LOCAL_NAME = "Description"
49    POLICY_DEFAULTS_LOCAL_NAME = "PolicyDefaults"
50    COMBINER_PARAMETERS_LOCAL_NAME = "CombinerParameters"
51    RULE_COMBINER_PARAMETERS_LOCAL_NAME = "RuleCombinerParameters"
52    OBLIGATIONS_LOCAL_NAME = "Obligations"
53   
54    # Plan to support permit overrides in a future release
55    RULE_COMBINING_ALG_IDS = (
56#    "urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides",
57    "urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides",
58    )
59    __slots__ = (
60        '__policyId',
61        '__version',
62        '__ruleCombiningAlgId',
63        '__description',
64        '__policyDefaults',
65        '__target',
66        '__attr',
67        '__obligations'
68    )
69   
70    def __init__(self):
71        super(Policy, self).__init__()
72        self.__policyId = None
73        self.__version = None
74        self.__ruleCombiningAlgId = None
75        self.__description = None
76        self.__target = None
77       
78        # Attr should eventually allow a choice of Rule, CombinerParameter,
79        # RuleCombinerParameter and VariableDefinition but only Rule type is
80        # currently supported
81        self.__attr = TypedList(Rule)
82       
83        self.__obligations = TypedList(Obligation)
84
85    def _getPolicyId(self):
86        return self.__policyId
87
88    def _setPolicyId(self, value):
89        if not isinstance(value, basestring):
90            raise TypeError('Expecting string type for "policyId" '
91                            'attribute; got %r' % type(value))
92           
93        self.__policyId = value
94
95    policyId = property(_getPolicyId, _setPolicyId, None, "Policy Id")
96
97    def _getVersion(self):
98        return self.__version
99
100    def _setVersion(self, value):
101        if not isinstance(value, basestring):
102            raise TypeError('Expecting string type for "version" '
103                            'attribute; got %r' % type(value))
104           
105        self.__version = value
106
107    version = property(_getVersion, _setVersion, None, "Policy Version")
108
109    def _getRuleCombiningAlgId(self):
110        return self.__ruleCombiningAlgId
111
112    def _setRuleCombiningAlgId(self, value):
113        if not isinstance(value, basestring):
114            raise TypeError('Expecting string type for "ruleCombiningAlgId" '
115                            'attribute; got %r' % type(value))
116           
117        if value not in Policy.RULE_COMBINING_ALG_IDS:
118            raise AttributeError('%r rule combining algorithm is invalid.  '
119                                 'Only these algorithms are currently '
120                                 'supported %r' % 
121                                 (value, Policy.RULE_COMBINING_ALG_IDS))
122        self.__ruleCombiningAlgId = value
123
124    ruleCombiningAlgId = property(_getRuleCombiningAlgId, 
125                                  _setRuleCombiningAlgId, None, 
126                                  doc="Rule Combining Algorithm Id")
127
128
129    @property
130    def combinerParameters(self):
131        raise NotImplementedError()
132   
133    @property
134    def ruleCombinerParameters(self):
135        raise NotImplementedError()
136   
137    @property
138    def variableDefinitions(self):
139        raise NotImplementedError()
140   
141    @property
142    def rules(self):
143        return self.__attr
144   
145    @property
146    def obligations(self):
147        return self.__obligations
148
149    def _getTargets(self):
150        return self.__targets
151
152    def _setTargets(self, value):
153        if (not isinstance(value, TypedList) and 
154            not issubclass(value.elementType, Target.__class__)):
155            raise TypeError('Expecting TypedList(Target) for "targets" '
156                            'attribute; got %r' % type(value))
157        self.__targets = value
158
159    targets = property(_getTargets, _setTargets, 
160                       doc="list of Policy targets")
161
162    def _getDescription(self):
163        return self.__description
164
165    def _setDescription(self, value):
166        if not isinstance(value, basestring):
167            raise TypeError('Expecting string type for "description" '
168                            'attribute; got %r' % type(value))
169        self.__description = value
170
171    description = property(_getDescription, _setDescription, 
172                           doc="Policy Description text")
173   
174    def parse(self):
175        """Parse the policy file set in policyFilePath attribute
176        """
177        elem = ElementTree.parse(self.policyFilePath)
178        root = elem.getroot()
179       
180        self.xmlns = QName.getNs(root.tag)
181        if not self.isValidXmlns:
182            raise InvalidPolicyXmlNsError("Namespace %r is recognised; valid "
183                                          "namespaces are: %r" %
184                                          (self.xmlns, Policy.XMLNS))
185           
186        for elem in root:
187            localName = QName.getLocalPart(elem.tag)
188            if localName == Policy.DESCRIPTION_LOCALNAME:
189                self.description = elem.text.strip()
190               
191            elif localName == Policy.TARGET_LOCALNAME:
192                self.targets.append(Target.Parse(elem))
193               
194            else:
195                raise PolicyParseError("Invalid policy attribute: %s" % 
196                                        localName)
197               
198    @classmethod
199    def Parse(cls, policyFilePath):
200        policy = cls(policyFilePath=policyFilePath)
201        policy.parse()
202        return policy
Note: See TracBrowser for help on using the repository browser.