source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/pep.py @ 4035

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/pep.py@4035
Revision 4035, 8.0 KB checked in by pjkersha, 12 years ago (diff)

Fixes following update to NOCS deployment.

  • m2CryptoSSLUtility.HTTPSConnection now overrides putrequest in order to ensure that the URL path is string type. unicode type gives an error
  • added a unit test for BrowsePDP - gatekeeper for MOLES/CSML access control.
Line 
1"""NDG Gatekeeper - A PEP (Policy Enforcement Point) enforces authorisation
2decision made by a PDP (Policy Decision Point)
3
4Adapted from original gatekeeper.py code
5
6NERC Data Grid Project
7"""
8__author__ = "P J Kershaw"
9__date__ = "04/04/08"
10__copyright__ = "(C) 200* STFC & NERC"
11__contact__ = "P.J.Kershaw@rl.ac.uk"
12__license__ = \
13"""This software may be distributed under the terms of the Q Public
14License, version 1.0 or later."""
15__contact__ = "P.J.Kershaw@rl.ac.uk"
16__revision__ = "$Id:gatekeeper.py 3079 2007-11-30 09:39:46Z pjkersha $"
17
18import logging
19log = logging.getLogger(__name__)
20
21# For parsing of properties file
22from os.path import expandvars as expVars
23
24# Expand environment vars in paths
25import os
26
27# System path modification for module import
28import sys
29
30from ConfigParser import SafeConfigParser
31from ndg.security.common.AttCert import *
32from ndg.security.common.authz.pdp import PDPInterface
33
34class PEPError(Exception):
35    """Exception handling for NDG Policy Enforcement Point class."""
36
37class PDPInitError(PEPError):
38    """Errors importing and instantiating Policy Decision Point class"""
39
40           
41class PEP(object):
42    """NDG Policy Enforcement Point class - determines whether a given
43    Attribute Certificate can access a given resource."""
44   
45    defParam = {'pdpModFilePath': None,
46                'pdpModName': '<pdpModName>',
47                'pdpClassName': '<pdpClassName>',
48                'pdpCfgFilePath': None,
49                'pdpCfgSection': 'DEFAULT'}
50   
51    def __init__(self,
52                 cfg=None,
53                 cfgSection='DEFAULT',
54                 pdpCfgKw={},
55                 **prop):
56        '''Initialise settings from a config file and/or keyword settings
57       
58        @type cfg: string / ConfigParser object
59        @param cfg: if a string type, this is interpreted as the file path to
60        a configuration file, otherwise it will be treated as a ConfigParser
61        object
62        @type cfgSection: string
63        @param cfgSection: sets the section name to retrieve config params
64        from
65        @type pdpCfgKw: dict
66        @param pdpCfgKw: parameters to pass to PDP interface - alternative to
67        passing settings in a config file or config object.  Keywords override
68        any duplicates set by the latter.
69        @type prop: dict
70        @param prop: set parameters as key value pairs.'''
71         
72        log.debug("PEP.__init__ ...")
73        self._pdp = None
74        self._pdpCfgKw = pdpCfgKw
75       
76        if isinstance(cfg, basestring):
77            log.debug('Setting PEP config from file: "%s" ...' % cfg)
78            self._cfg = SafeConfigParser()
79            self.readConfig(cfg)
80        else:
81            log.debug('Setting PEP config from existing config object ...')
82            self._cfg = cfg
83           
84        if cfg: # i.e. at least some kind of config was input
85            self.parseConfig(cfgSection)
86           
87        # Any keywords set will override equivalent file property settings
88        # Copy directly into attribute of this object
89        for paramName in prop:
90            if paramName not in PEP.defParam:
91                raise AttributeError(
92                            'Keyword "%s" is not a valid config parameter' % \
93                            paramName)
94            setattr(self, paramName, expVars(prop['paramName']))
95
96        # Default parameters if not set above
97        for paramName in PEP.defParam:
98            if not hasattr(self, paramName):
99                setattr(self, paramName, PEP.defParam[paramName])
100       
101        if not hasattr(self, 'pdpCfgSection'):
102            self.pdpCfgSection = 'DEFAULT'
103           
104        # Check for minimum param settings necessary for initialising a PDP
105        # object (the module can be on the existing class path)
106        if getattr(self, 'pdpModName', None) and \
107           getattr(self, 'pdpClassName', None):
108            # Initialize if all required resource URI class properties are set
109            self.initPDPInterface()
110       
111       
112    def initPDPInterface(self):
113        """Set-up PDP interface to PEP"""
114       
115        log.debug("PEP.initPDPInterface ...")
116        sysPathBak = None # extra bullet proofing for finally block
117        try:
118            try:
119                # Temporarily extend system path ready for import
120                if self.pdpModFilePath:
121                    sysPathBak = sys.path[:]
122                    sys.path.append(self.pdpModFilePath)
123
124                # Import module name specified in properties file
125                pdpMod = __import__(self.pdpModName,
126                                    globals(),
127                                    locals(),
128                                    [self.pdpClassName])
129   
130                pdpClass = eval('pdpMod.' + self.pdpClassName)
131
132            finally:
133                if sysPathBak:
134                    sys.path[:] = sysPathBak
135                               
136        except KeyError, e:
137            raise PDPInitError('Importing PDP module, key not recognised: %s'%\
138                               e)                         
139        except Exception, e:
140            raise PDPInitError('Importing PDP module: %s' % e)
141
142
143        # Check class inherits from PEPResrc abstract base class
144        if not issubclass(pdpClass, PDPInterface):
145            raise PDPInitError, \
146                "PDP interface class %s must be derived from PDPInterface" % \
147                    self.pdpClassName
148
149
150        # Instantiate custom class
151        self._pdp = pdpClass(cfg=self.pdpCfgFilePath or self._cfg,
152                             cfgSection=self.pdpCfgSection,
153                             **self._pdpCfgKw)           
154
155
156    def readConfig(self, cfgFilePath):
157        """Read the configuration file"""
158        self._cfg.read(cfgFilePath)
159
160
161    def parseConfig(self, section='DEFAULT'):
162        '''Extract config properties for the interface to the PDP'''
163       
164        log.debug("PEP.parseConfig ...")
165       
166        # Copy directly into attribute of this object
167        for paramName in PEP.defParam:
168            if self._cfg.has_option(section, paramName): 
169                val = expVars(self._cfg.get(section, paramName, None))
170                setattr(self, paramName, val)
171            else:
172                setattr(self, paramName, PEP.defParam[paramName])
173
174   
175    def __call__(self, resrcHandle, userHandle, accessType, *arg, **kw):
176        """Make an Access control decision with this behaviour:
177       
178        @type resrcHandle: any - determined by the PDP used
179        @param resrcHandle: a handle to the resource which the PEP protects. 
180        This could be for example a resource ID string, or a dict or other
181        object to hold resource information required by the PDP
182       
183        @type userHandle: any - determined by the PDP used
184        @param userHandle: a handle to the user requesting access. 
185        e.g. a user ID, an attribute certificate or a handle to a service
186        which can be interrogated to get the required information
187       
188        @type accessType: any - determined by the PDP used
189        @param accessType: the type of access being requested e.g. read,
190        read/write, put etc.
191       
192        @rtype: bool
193        @return: True if access permitted; False if denied or else raise
194        an Exception
195       
196        Nb.
197       
198        *arg and **kw are included to enable further customisation,
199        resrcHandle, userHandle and accessType are merely indicators.
200       
201        The alias to this method 'accessPermitted'"""
202       
203        if self._pdp is None:
204            raise PDPInitError("PDP object is not set - " + \
205                "ensure initPDPInterface has been called and the relevant " + \
206                " configuration parameters have been set")
207           
208        return self._pdp.accessPermitted(resrcHandle, 
209                                         userHandle, 
210                                         accessType, 
211                                         *arg, 
212                                         **kw)
213       
214    accessPermitted = __call__
215   
216   
217def accessPermitted():
218    '''Convenience wrapper routine for PEP'''
Note: See TracBrowser for help on using the repository browser.