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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg-security/TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/xacml/policy.py@6730
Revision 6730, 6.8 KB checked in by pjkersha, 11 years ago (diff)
  • Working Credential Wallet refactored for Python 2.6
  • Pruned out more old code: ZSI and Twisted SAOP/WSDL wrappers, Session Manager and WS-Security, Test 'Site B' Attribute Authority - for testing role mapping.
  • Started XACML package ElementTree based parser.
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    POLICY_ID_ATTRIB_NAME = "PolicyId"
43    RULE_COMBINING_ALG_ID_ATTRIB_NAME = "RuleCombiningAlgId"
44     
45    DESCRIPTION_LOCALNAME = "Description"
46    TARGET_LOCALNAME = "Target"
47    POLICY_DEFAULTS_LOCALNAME = "PolicyDefaults"
48    OBLIGATIONS_LOCALNAME = "Obligations"
49    RULE_LOCALNAME = "Rule"
50   
51    # Plan to support permit overrides in a future release
52    RULE_COMBINING_ALG_IDS = (
53#    "urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides",
54    "urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides",
55    )
56    __slots__ = (
57        '__policyId',
58        '__version',
59        '__ruleCombiningAlgId',
60        '__description',
61        '__policyDefaults',
62        '__target',
63        '__attr',
64        '__obligations'
65    )
66   
67    def __init__(self):
68        super(Policy, self).__init__()
69        self.__policyId = None
70        self.__version = None
71        self.__ruleCombiningAlgId = None
72        self.__description = None
73        self.__target = None
74       
75        # Attr should eventually allow a choice of Rule, CombinerParameter,
76        # RuleCombinerParameter and VariableDefinition but only Rule type is
77        # currently supported
78        self.__attr = TypedList(Rule)
79       
80        self.__obligations = TypedList(Obligation)
81
82    def _getPolicyId(self):
83        return self.__policyId
84
85    def _setPolicyId(self, value):
86        if not isinstance(value, basestring):
87            raise TypeError('Expecting string type for "policyId" '
88                            'attribute; got %r' % type(value))
89           
90        self.__policyId = value
91
92    policyId = property(_getPolicyId, _setPolicyId, None, "Policy Id")
93
94    def _getVersion(self):
95        return self.__version
96
97    def _setVersion(self, value):
98        if not isinstance(value, basestring):
99            raise TypeError('Expecting string type for "version" '
100                            'attribute; got %r' % type(value))
101           
102        self.__version = value
103
104    version = property(_getVersion, _setVersion, None, "Policy Version")
105
106    def _getRuleCombiningAlgId(self):
107        return self.__ruleCombiningAlgId
108
109    def _setRuleCombiningAlgId(self, value):
110        if not isinstance(value, basestring):
111            raise TypeError('Expecting string type for "ruleCombiningAlgId" '
112                            'attribute; got %r' % type(value))
113           
114        if value not in Policy.RULE_COMBINING_ALG_IDS:
115            raise AttributeError('%r rule combining algorithm is invalid.  '
116                                 'Only these algorithms are currently '
117                                 'supported %r' % 
118                                 (value, Policy.RULE_COMBINING_ALG_IDS))
119        self.__ruleCombiningAlgId = value
120
121    ruleCombiningAlgId = property(_getRuleCombiningAlgId, 
122                                  _setRuleCombiningAlgId, None, 
123                                  doc="Rule Combining Algorithm Id")
124
125
126    @property
127    def combinerParameters(self):
128        raise NotImplementedError()
129   
130    @property
131    def ruleCombinerParameters(self):
132        raise NotImplementedError()
133   
134    @property
135    def variableDefinitions(self):
136        raise NotImplementedError()
137   
138    @property
139    def rules(self):
140        return self.__attr
141   
142    @property
143    def obligations(self):
144        return self.__obligations
145
146    def _getTargets(self):
147        return self.__targets
148
149    def _setTargets(self, value):
150        if (not isinstance(value, TypedList) and 
151            not issubclass(value.elementType, Target.__class__)):
152            raise TypeError('Expecting TypedList(Target) for "targets" '
153                            'attribute; got %r' % type(value))
154        self.__targets = value
155
156    targets = property(_getTargets, _setTargets, 
157                       doc="list of Policy targets")
158
159    def _getDescription(self):
160        return self.__description
161
162    def _setDescription(self, value):
163        if not isinstance(value, basestring):
164            raise TypeError('Expecting string type for "description" '
165                            'attribute; got %r' % type(value))
166        self.__description = value
167
168    description = property(_getDescription, _setDescription, 
169                           doc="Policy Description text")
170   
171    def parse(self):
172        """Parse the policy file set in policyFilePath attribute
173        """
174        elem = ElementTree.parse(self.policyFilePath)
175        root = elem.getroot()
176       
177        self.xmlns = QName.getNs(root.tag)
178        if not self.isValidXmlns:
179            raise InvalidPolicyXmlNsError("Namespace %r is recognised; valid "
180                                          "namespaces are: %r" %
181                                          (self.xmlns, Policy.XMLNS))
182           
183        for elem in root:
184            localName = QName.getLocalPart(elem.tag)
185            if localName == Policy.DESCRIPTION_LOCALNAME:
186                self.description = elem.text.strip()
187               
188            elif localName == Policy.TARGET_LOCALNAME:
189                self.targets.append(Target.Parse(elem))
190               
191            else:
192                raise PolicyParseError("Invalid policy attribute: %s" % 
193                                        localName)
194               
195    @classmethod
196    def Parse(cls, policyFilePath):
197        policy = cls(policyFilePath=policyFilePath)
198        policy.parse()
199        return policy
Note: See TracBrowser for help on using the repository browser.