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

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

ndg.security.common.wssecurity.__init: fix for reading parameters with prefix set.

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("PDP interface class %s must be derived from "
146                               "PDPInterface" % self.pdpClassName)
147
148
149        # Instantiate custom class
150        self._pdp = pdpClass(cfg=self.pdpCfgFilePath or self._cfg,
151                             cfgSection=self.pdpCfgSection,
152                             **self._pdpCfgKw)           
153
154
155    def readConfig(self, cfgFilePath):
156        """Read the configuration file"""
157        self._cfg.read(cfgFilePath)
158
159
160    def parseConfig(self, section='DEFAULT'):
161        '''Extract config properties for the interface to the PDP'''
162       
163        log.debug("PEP.parseConfig ...")
164       
165        # Copy directly into attribute of this object
166        for paramName in PEP.defParam:
167            if self._cfg.has_option(section, paramName): 
168                val = expVars(self._cfg.get(section, paramName, None))
169                setattr(self, paramName, val)
170            else:
171                setattr(self, paramName, PEP.defParam[paramName])
172
173   
174    def __call__(self, resrcHandle, userHandle, accessType, *arg, **kw):
175        """Make an Access control decision with this behaviour:
176       
177        @type resrcHandle: any - determined by the PDP used
178        @param resrcHandle: a handle to the resource which the PEP protects. 
179        This could be for example a resource ID string, or a dict or other
180        object to hold resource information required by the PDP
181       
182        @type userHandle: any - determined by the PDP used
183        @param userHandle: a handle to the user requesting access. 
184        e.g. a user ID, an attribute certificate or a handle to a service
185        which can be interrogated to get the required information
186       
187        @type accessType: any - determined by the PDP used
188        @param accessType: the type of access being requested e.g. read,
189        read/write, put etc.
190       
191        @rtype: bool
192        @return: True if access permitted; False if denied or else raise
193        an Exception
194       
195        Nb.
196       
197        *arg and **kw are included to enable further customisation,
198        resrcHandle, userHandle and accessType are merely indicators.
199       
200        The alias to this method 'accessPermitted'"""
201       
202        if self._pdp is None:
203            raise PDPInitError("PDP object is not set - ensure "
204                               "initPDPInterface has been called and the "
205                               "relevant configuration parameters have been "
206                               "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.