Changeset 3896 for TI12-security


Ignore:
Timestamp:
13/05/08 16:11:23 (12 years ago)
Author:
pjkersha
Message:

Updates for ndg.security.common.authz.pep and ndg.security.common.authz.pdp for BrowsePDP Gatekeeper code for ows_server.

Location:
TI12-security/trunk/python
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/pdp/__init__.py

    r3790 r3896  
    4343    def __init__(self, msg=None): 
    4444        PDPError.__init__(self, msg or PDPMissingResourceConstraints.__doc__) 
     45 
     46class PDPUnknownResourceType(PDPError): 
     47    """The type for requested resource is not known""" 
     48    def __init__(self, msg=None): 
     49        PDPError.__init__(self, msg or PDPUnknownResourceType.__doc__) 
    4550             
    4651  
     
    5055    PDPs must adhere to this interface by subclassing from it""" 
    5156     
    52     def __init__(self, cfgFilePath=None, **cfgKw): 
    53         "__init__ should accept a config file path input or config keywords" 
     57    def __init__(self,  
     58                 cfgFilePath=None,  
     59                 cfg=None,  
     60                 cfgSection='DEFAULT', 
     61                 **cfgKw): 
     62        """PDPInterface(cfgFilePath|cfg|**cfgKw) 
     63         
     64        @type cfgFilePath: string 
     65        @param cfgFilePath: file path to configuration file 
     66        @type cfg: ConfigParser object to retrieve parameters from as an  
     67        alternative to cfgFilePath input 
     68        @type cfgSection: string 
     69        @param cfgSection: sets the section name to retrieve config params  
     70        from 
     71        @type cfgKw: dict 
     72        @param cfgKw: set parameters as key value pairs.""" 
    5473        raise NotImplementedError("%s\n%s" % (PDPInterface.__doc__, 
    5574                                              PDPInterface.__init__.__doc__)) 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/pdp/browse.py

    r3894 r3896  
    11"""NDG Policy Decision Point for NDG Browse - access constraints for a  
    2 resource are determined from MOLES access constraints in the data 
     2resource are determined from MOLES access constraints in the data.  Nb. the 
     3access control portions of the schema are used for CSML also. 
    34 
    45NERC Data Grid Project 
     
    2627 
    2728from ndg.security.common.authz.pdp import PDPInterface, PDPError, \ 
    28     PDPUserAccessDenied, PDPUserNotLoggedIn, PDPMissingResourceConstraints 
     29    PDPUserAccessDenied, PDPUserNotLoggedIn, PDPMissingResourceConstraints, \ 
     30    PDPUnknownResourceType 
    2931     
    3032from ndg.security.common.SessionMgr import SessionMgrClient, SessionNotFound,\ 
     
    6567 
    6668 
    67 class MolesPDP(PDPInterface): 
     69class BrowsePDP(PDPInterface): 
    6870    """Make access control decision based on a MOLES access constraint  
    69     (applies to CSML too) and user security token""" 
     71    (applies to CSML too) and user security token 
     72     
     73    This class conforms to the PDPInterface and so can be set-up from a PEP 
     74    (Policy Enforcement Point) object""" 
     75     
     76    molesXMLNS = 'http://ndg.nerc.ac.uk/moles' 
     77    csmlXMLNS = 'http://ndg.nerc.ac.uk/csml' 
     78 
     79    # MOLES B1 is dynamically generated from B0 and has no schema     
     80    b1dgSecurityConditionXPth = 'dgMetadataSecurity/dgSecurityCondition' 
     81     
     82    # Add schemae prefixes for B0 query 
     83    b0dgSecurityConditionXPth = '{%s}%s'%(molesXMLNS,b1dgSecurityConditionXPth) 
     84     
     85    csmlDGSecurityConditionXPth = \ 
     86        '{%s}AccessControlPolicy/{%s}dgSecurityCondition' % ((csmlXMLNS, )*2) 
    7087 
    7188    molesXPathQueryPfx = \ 
     
    8198             
    8299     
    83     def __init__(self, cfgFilePath=None, **cfgKw): 
    84         """Initialise settings for WS-Security and SSL for SOAP 
    85         call to Session Manager 
    86          
    87         @type uri: string 
    88         @param uri: URI corresponding to data granule ID 
    89          
    90         @type securityElement: ElementTree Element 
    91         @param securityElement: MOLES security constraint containing role and 
    92         Attribute Authority URI. In xml, could look like: 
    93         <moles:effect>allow</moles:effect> 
    94             <moles:simpleCondition> 
    95             <moles:dgAttributeAuthority>https://glue.badc.rl.ac.uk/AttributeAuthority</moles:dgAttributeAuthority> 
    96             <moles:attrauthRole>coapec</moles:attrauthRole> 
    97         </moles:simpleCondition> 
    98         NB: xmlns:moles="http://ndg.nerc.ac.uk/moles 
    99         """ 
    100          
    101         self.cfgFilePath = cfgFilePath 
     100    def __init__(self, 
     101                 cfg=None,  
     102                 cfgSection='DEFAULT', 
     103                 **cfgKw): 
     104        """Initialise based on settings from a config file, config file object 
     105        or keywords: 
     106         
     107        @type cfg: string / ConfigParser object 
     108        @param cfg: if a string type, this is interpreted as the file path to 
     109        a configuration file, otherwise it will be treated as a ConfigParser  
     110        object  
     111        @type cfgSection: string 
     112        @param cfgSection: sets the section name to retrieve config params  
     113        from 
     114        @type cfgKw: dict 
     115        @param cfgKw: set parameters as key value pairs.""" 
     116         
     117        self._cfg = cfg or SafeConfigParser() 
     118         
    102119        self.resrcURI = None 
    103120        self.securityElement = None 
     
    105122         
    106123        # Set from config file 
    107         if cfgFilePath: 
    108             self._readConfig() 
    109              
     124        if isinstance(cfg, basestring): 
     125            self._readConfig(cfgFilePath) 
     126        else: 
     127            self._cfg = cfg 
     128         
     129        # Parse settings 
     130        if cfg: 
     131            self._parseConfig(cfgSection) 
     132             
     133                 
    110134        # Separate keywords into PDP and WS-Security specific items 
    111135        paramNames = cfgKw.keys() 
    112136        for paramName in paramNames: 
    113             if paramName in MolesPDP.defParam: 
     137            if paramName in BrowsePDP.defParam: 
    114138                # Keywords are deleted as they are set 
    115139                setattr(self, paramName, cfgKw.pop('paramName')) 
     
    118142        self.wssCfg = cfgKw     
    119143 
    120             
    121     def _readConfig(self, section='DEFAULT'): 
     144         
     145    def _getSecurityElem(self): 
     146        '''Query the input document for a security constraint element.         
     147        The query type is dependent on the schema of the document''' 
     148         
     149        if self.resrcURI.schema == 'DIF': 
     150            log.info('BrowsePDP: DIF record found - no security applied') 
     151            return None # no access control 
     152         
     153        elif self.resrcURI.schema == 'NDG-B0': 
     154            log.info(\ 
     155            'BrowsePDP: Checking for constraints for MOLES B0 document ...') 
     156            return self.resrcDoc.tree.find(BrowsePDP.b1dgSecurityConditionXPth) 
     157         
     158        elif self.resrcURI.schema == 'NDG-B1': 
     159            # MOLES B1 is dynamically generated from B0 and has no schema 
     160            log.info(\ 
     161            'BrowsePDP: Checking for constraints for MOLES B1 document ...') 
     162            return self.resrcDoc.tree.find(BrowsePDP.b1dgSecurityConditionXPth) 
     163          
     164        elif self.resrcURI.schema == 'NDG-A0': 
     165            log.info(\ 
     166            'BrowsePDP: Checking for constraints for CSML document ...') 
     167            return \ 
     168                self.resrcDoc.tree.find(BrowsePDP.csmlDGSecurityConditionXPth) 
     169        else: 
     170            log.error('BrowsePDP._getSecurityElem: unknown schema type "%s"'%\ 
     171                      self.resrcURI.schema) 
     172            raise PDPUnknownResourceType() 
     173 
     174   
     175    def _readConfig(self): 
    122176        '''Read PDP configuration file''' 
    123         cfg = SafeConfigParser() 
    124         cfg.read(self.cfgFilePath) 
    125          
     177        self._cfg.read(self.cfgFilePath) 
     178 
     179 
     180    def _parseConfig(self, section='DEFAULT'): 
     181        '''Extract parameters from _cfg config object''' 
    126182        # Copy directly into attribute of this object 
    127         for paramName, paramVal in MolesPDP.defParam.items(): 
     183        for paramName, paramVal in BrowsePDP.defParam.items(): 
    128184            if isinstance(paramVal, list): 
    129                 paramListVal = expVars(cfg.get(section, paramName)).split() 
    130                 setattr(self, paramName, paramListVal) 
     185                listVal = expVars(self._cfg.get(section, paramName)).split() 
     186                setattr(self, paramName, listVal) 
    131187            else: 
    132                 setattr(self, paramName, expVars(cfg.get(section, paramName)))             
     188                val = expVars(self._cfg.get(section, paramName)) 
     189                setattr(self, paramName, val)             
    133190 
    134191 
     
    138195         
    139196        @type resrcHandle: dict 
    140         @param resrcHandle: dict 'uri' = resource URI, 'securityElement' =  
    141         ElementTree type MOLES security Element 
     197        @param resrcHandle: dict 'uri' = resource URI, 'doc' =  
     198        ElementTree type doc 
    142199         
    143200        @type userHandle: dict 
     
    169226        tokens.  Resets equivalent object attribute.""" 
    170227           
     228        log.debug("BrowsePDP.accessPermitted ...") 
     229         
    171230        # Resource handle contains URI and ElementTree resource security  
    172231        # element 
    173232        try: 
    174233            self.resrcURI = resrcHandle['uri'] 
    175             self.securityElement = resrcHandle['securityElement']  
     234            self.resrcDoc = resrcHandle['doc']  
    176235        except KeyError, e: 
    177236            log.error("Resource handle missing key %s" % e) 
    178237            raise PDPMissingResourceConstraints() 
     238 
     239        # First query the document for a security constraint 
     240        self.securityElement = self._getSecurityElem() 
     241        if not self.securityElement: 
     242            # No security set 
     243            log.info("BrowsePDP: no security constraints found for [%s]" % \ 
     244                     self.resrcURI.schema + \ 
     245                     " type document [%s]" % self.resrcURI) 
     246            return 
     247         
    179248         
    180249        # User handle contains 'h' = Session Manager URI and 'sid' user  
     
    188257 
    189258             
    190         roleElem = self.securityElement.find(MolesPDP.roleXPathQuery) 
     259        roleElem = self.securityElement.find(BrowsePDP.roleXPathQuery) 
    191260        if roleElem is None or not roleElem.text: 
    192261            log.error("PDP: role not set in MOLES security " + \ 
     
    196265        self.reqRole = roleElem.text 
    197266 
    198         aaElem = self.securityElement.find(MolesPDP.aaXPathQuery) 
     267        aaElem = self.securityElement.find(BrowsePDP.aaXPathQuery) 
    199268         
    200269        # Sanity check on Attribute Authority URI 
     
    204273            # Check Attribute Authority address 
    205274            try: 
    206                 MolesPDP.urlCanBeOpened(aaURI) 
     275                BrowsePDP.urlCanBeOpened(aaURI) 
    207276            except URLCannotBeOpened, e: 
    208277                # Catch situation where either Attribute Authority address in the 
     
    342411def makeDecision(resrcHandle, userHandle, accessType=None, **kw): 
    343412    '''One call Wrapper interface to PDP''' 
    344     return MolesPDP(**kw)(resrcHandle, userHandle) 
     413    return BrowsePDP(**kw)(resrcHandle, userHandle) 
    345414 
    346415  
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/pep.cfg

    r3759 r3896  
    2525 
    2626# File Path to configuration file used by PDP class (environment variables 
    27 # can be used in this path e.g. $PDP_CONFIG_DIR/pdp.cfg 
     27# can be used in this path e.g. $PDP_CONFIG_DIR/pdp.cfg).  Omit this parameter 
     28# to make the PEP read the PDP settings from THIS config file 
    2829pdpCfgFilePath:  
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/pep.py

    r3790 r3896  
    3232from ndg.security.common.authz.pdp import PDPInterface 
    3333 
    34 #_____________________________________________________________________________ 
    3534class PEPError(Exception): 
    36     """Exception handling for NDG PEP class.""" 
     35    """Exception handling for NDG Policy Enforcement Point class.""" 
    3736 
    3837class PDPInitError(PEPError): 
    39     """Errors importing and instiating PDP class""" 
    40  
    41              
    42 #_____________________________________________________________________________ 
     38    """Errors importing and instantiating Policy Decision Point class""" 
     39 
     40             
    4341class PEP(object): 
    44     """NDG PEP class - determines whether a given Attribute  
    45     Certificate can access a given resource.""" 
    46      
    47     defParam = {'pdpModFilePath': '', 
    48                 'pdpModName': '', 
    49                 'pdpClassName': '', 
    50                 'pdpCfgFilePath': ''} 
    51      
    52     #_________________________________________________________________________ 
    53     def __init__(self, cfgFilePath=None, **prop): 
     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.''' 
    5471          
    55         self.cfgFilePath = cfgFilePath 
    56         self._cfg = SafeConfigParser() 
    57                        
     72        log.debug("PEP.__init__ ...") 
    5873        self._pdp = None 
    59          
    60         if cfgFilePath: 
    61             self.readConfig() 
     74        self._pdpCfgKw = pdpCfgKw 
     75         
     76        if isinstance(cfg, basestring): 
     77            log.debug('Setting PEP config from file: "%s" ...' % cfg) 
     78            self.readConfig(cfgFilePath) 
     79        else: 
     80            log.debug('Setting PEP config from existing config object ...') 
     81            self._cfg = cfg 
     82             
     83        if cfg: # i.e. at least some kind of config was input 
     84            self.parseConfig(cfgSection) 
    6285             
    6386        # Any keywords set will override equivalent file property settings 
     
    6588        for paramName in prop: 
    6689            if paramName not in PEP.defParam: 
    67                 raise AttributeError(\ 
    68                             'Keyword "%s" is not a valid config parameter"' % \ 
     90                raise AttributeError( 
     91                            'Keyword "%s" is not a valid config parameter' % \ 
    6992                            paramName) 
    7093            setattr(self, paramName, expVars(prop['paramName'])) 
    71          
    72         # Make a copy of ref params deleting 'pdpModFilePath' as this isn't 
    73         # necessary for initialising a PDP object (the module can be on the 
    74         # existing class path) 
    75         param4PDPInit = PEP.defParam.copy() 
    76         param4PDPInit.pop('pdpModFilePath') 
    77           
    78         paramFound = [paramName for paramName in param4PDPInit \ 
    79                       if getattr(self, paramName, None)] 
    80         if len(paramFound) == len(param4PDPInit): 
     94 
     95        # Default parameters if not set above 
     96        for paramName in PEP.defParam: 
     97            if not hasattr(self, paramName): 
     98                setattr(self, paramName, PEP.defParam[paramName]) 
     99         
     100        if not hasattr(self, 'pdpCfgSection'): 
     101            self.pdpCfgSection = 'DEFAULT' 
     102             
     103        # Check for minimum param settings necessary for initialising a PDP  
     104        # object (the module can be on the existing class path) 
     105        if getattr(self, 'pdpModName', None) and \ 
     106           getattr(self, 'pdpClassName', None): 
    81107            # Initialize if all required resource URI class properties are set 
    82108            self.initPDPInterface() 
    83109        
    84110         
    85     #_________________________________________________________________________ 
    86111    def initPDPInterface(self): 
    87112        """Set-up PDP interface to PEP""" 
    88113         
     114        log.debug("PEP.initPDPInterface ...") 
    89115        sysPathBak = None # extra bullet proofing for finally block 
    90116        try: 
    91117            try: 
    92                 sysPathBak = sys.path[:] 
    93                  
    94118                # Temporarily extend system path ready for import 
    95                 sys.path.append(self.pdpModFilePath) 
    96                  
     119                if self.pdpModFilePath: 
     120                    sysPathBak = sys.path[:] 
     121                    sys.path.append(self.pdpModFilePath) 
     122 
    97123                # Import module name specified in properties file 
    98124                pdpMod = __import__(self.pdpModName, 
     
    102128     
    103129                pdpClass = eval('pdpMod.' + self.pdpClassName) 
    104                  
     130 
    105131            finally: 
    106                 sys.path[:] = sysPathBak 
     132                if sysPathBak: 
     133                    sys.path[:] = sysPathBak 
    107134                                 
    108135        except KeyError, e: 
     
    121148 
    122149        # Instantiate custom class 
    123         try: 
    124             self._pdp = pdpClass(self.pdpCfgFilePath)             
    125         except Exception, e: 
    126             raise PDPInitError("Error instantiating PDP interface %s: %s" % \ 
    127                                (pdpClass, e)) 
    128  
    129  
    130     #_________________________________________________________________________ 
    131     def readConfig(self, section='DEFAULT'): 
    132         """Read the configuration properties for the interface to the PDP 
    133         """ 
    134         self._cfg.read(self.cfgFilePath) 
     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 ...") 
    135164         
    136165        # Copy directly into attribute of this object 
    137166        for paramName in PEP.defParam: 
    138             setattr(self, paramName, expVars(self._cfg.get(section,paramName))) 
     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]) 
    139172 
    140173    
    141     #_________________________________________________________________________ 
    142174    def __call__(self, resrcHandle, userHandle, accessType, *arg, **kw): 
    143175        """Make an Access control decision with this behaviour: 
     
    169201         
    170202        if self._pdp is None: 
    171             raise PDPInitError(\ 
    172             "PDP object is not set - ensure initPDPInterface has been called") 
     203            raise PDPInitError("PDP object is not set - " + \ 
     204                "ensure initPDPInterface has been called and the relevant " + \ 
     205                " configuration parameters have been set") 
    173206             
    174207        return self._pdp.accessPermitted(resrcHandle,  
     
    179212         
    180213    accessPermitted = __call__ 
     214     
     215     
     216def accessPermitted(): 
     217    '''Convenience wrapper routine for PEP''' 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso/config/ssoServiceMiddleware.py

    r3892 r3896  
    122122        self.wss = dict(wss.items()) 
    123123 
    124          
    125         # Gatekeeper params 
    126          
    127         # Attribute Certificate Issuer 
    128         self.acIssuer = self.cfg.get(defSection, 'acIssuer') 
    129          
    130         # verification of X.509 cert back to CA 
    131         try: 
    132             self.acCACertFilePathList = xpdvars(self.cfg.get(defSection,  
    133                                             'acCACertFilePathList')).split()           
    134         except AttributeError: 
    135             raise SSOServiceConfigError( 
    136                                 'No "acCACertFilePathList" security setting') 
    137124 
    138125        # Hostname 
    139         self.server=self.cfg.get(defSection, 'server', '') 
     126        self.server = self.cfg.get(defSection, 'server', '') 
    140127 
    141128        # For secure connections 
Note: See TracChangeset for help on using the changeset viewer.