source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/models/ndgSecurity.py @ 2785

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/trunk/ows_server/ows_server/models/ndgSecurity.py@2785
Revision 2785, 6.5 KB checked in by lawrence, 12 years ago (diff)

A temporary fix (I think) for ticket:841.
Some more improvements with security (still turned off though)

Line 
1from ows_common.exception_report import OwsError
2from pylons import request
3from ndg.security.common.SessionMgr import SessionMgrClient, \
4    AttributeRequestDenied
5
6def HandleSecurity(securityElement, securityTokens):
7    return SecurityHandler(securityElement, securityTokens)()
8
9# This is an initial implementation and is untested.  See TODOs
10# for more info
11#
12# P J Kershaw 26/07/07
13class SecurityHandler(object):
14    """Make access control decision based on CSML constraint and user security
15    token"""
16   
17    AccessAllowedMsg = "Access Allowed"
18    AccessDeniedMsg = "Access Denied"
19    NotLoggedInMsg = 'Not Logged in'
20   
21    def __init__(self, securityElement, securityTokens):
22        """Initialise settings for WS-Security and SSL for SOAP
23        call to Session Manager
24       
25        @type: ? TODO: set type
26        @param securityElement: CSML security constraint containing role and
27        Attribute Authority URI
28       
29        @type: pylons.session
30        @param securityTokens: dict-like session object containing security
31        tokens"""
32       
33        self.securityElement = securityElement
34        self.securityTokens = securityTokens
35       
36       
37        # we need access to the config file to get the various PKI certificates.
38        # note that this is already a config parser instance
39        try:
40            self.ndgCfg = request.environ['ndgConfig']
41            self.tracefile = self.ndgCfg.get('NDG_SECURITY','tracefile',None)
42        except:
43            raise OwsError('NDG Security not enabled')
44       
45        # ... for SSL connections to security web services
46        try:   
47           
48            m='sslCACertFilePathList'
49            self.sslCACertFilePathList = \
50            self.ndgCfg.get('NDG_SECURITY',m).split()
51           
52            m='sslPeerCertCN'
53            self.sslPeerCertCN = self.ndgCfg.get('NDG_SECURITY',m)
54               
55            # ...and for WS-Security digital signature
56            m='wssCertFilePath'
57            self.wssCertFilePath = self.ndgCfg.get('NDG_SECURITY',m) 
58            m='wssKeyFilePath'
59            self.wssPriKeyFilePath = self.ndgCfg.get('NDG_SECURITY',m)
60            m='wssKeyPwd'
61            self.wssPriKeyPwd = self.ndgCfg.get('NDG_SECURITY',m)   
62            m='wssCACertFilePathList'
63            self.wssCACertFilePathList =self.ndgCfg.get('NDG_SECURITY',m).split()
64           
65            # Attribute Certificate verification of X.509 cert chain back to CA
66            m='acCACertFilePathList'
67            self.acCACertFilePathList = self.ndgCfg.get('NDG_SECURITY',m).split()
68               
69        except AttributeError:
70            raise OwsError, 'NDG Security Error: No %s'%m
71
72        # Create Session Manager client
73        self.smClnt = SessionMgrClient(uri=self.securityTokens['h'],
74                        sslCACertFilePathList=self.sslCACertFilePathList,
75                        sslPeerCertCN=self.sslPeerCertCN,
76                        signingCertChain=securityTokens.get('wssCertChain'),
77                        signingCertFilePath=self.wssCertFilePath,
78                        signingPriKeyFilePath=self.wssPriKeyFilePath,
79                        signingPriKeyPwd=self.wssPriKeyPwd,
80                        caCertFilePathList=self.wssCACertFilePathList,
81                        tracefile=self.tracefile)       
82
83        # Fix WS-Security BinarySecurityToken Value Type for the passing of a
84        # cert chain - required for use with proxy cert.
85        #if wssCertChain:
86        #    self.smClnt.signatureHandler.reqBinSecTokValType = 'X509PKIPathv1'
87
88
89    def __call__(self, **kw):
90        """Convenience wrapper for checkAccess"""
91        return self.checkAccess(**kw)
92
93
94    def checkAccess(self, securityElement=None, securityTokens=None):
95        """Make an access control decision based on whether the user is
96        authenticated and has the required roles
97       
98        @type: ElementTree Element
99        @keyword securityElement: MOES security constraint containing role and
100        Attribute Authority URI. In xml, could look like:
101        <moles:effect>allow</moles:effect>
102            <moles:simpleCondition>
103            <moles:dgAttributeAuthority>https://glue.badc.rl.ac.uk/AttributeAuthority</moles:dgAttributeAuthority>
104            <moles:attrauthRole>coapec</moles:attrauthRole>
105        </moles:simpleCondition>
106        NB: xmlns:moles="http://ndg.nerc.ac.uk/moles"
107       
108        @type: pylons.session
109        @keyword securityTokens: dict-like session object containing security
110        tokens.  Resets equivalent object attribute."""
111     
112        if securityElement:
113            self.securityElement=securityElement
114           
115        xpathr='{http://ndg.nerc.ac.uk/moles}simpleCondition/{http://ndg.nerc.ac.uk/moles}attrauthRole'
116        xpathaa='{http://ndg.nerc.ac.uk/moles}simpleCondition/{http://ndg.nerc.ac.uk/moles}dgAttributeAuthority'
117        roleE,aaE=self.securityElement.find(xpathr),self.securityElement.find(xpathaa)
118        if None in (roleE,aaE):
119            return True,'Invalid Security Condition'
120        self.reqRole=roleE.text
121        self.reqAAURI=aaE.text
122           
123        if securityTokens:
124            self.securityTokens = securityTokens
125       
126        if not self.securityTokens:
127            return False, self.__class__.NotLoggedInMsg
128        else:
129            return self.__checkAttCert()
130           
131
132   
133    def __checkAttCert(self):
134        """Check to see if the Session Manager can deliver an Attribute
135        Certificate with the required role to gain access to the resource
136        in question"""
137       
138        try:
139
140            # Make request for attribute certificate
141            #
142            # sessID is needed if proxy cert is unavailable as ID
143
144            attCert = self.smClnt.getAttCert(attAuthorityURI=self.reqAAURI,
145                                     sessID=self.securityTokens.get('sessID'),
146                                     reqRole=self.reqRole)
147
148        except AttributeRequestDenied, e:
149            # TODO: write exception to log
150            return False, self.__class__.AccessDeniedMsg
151       
152        # Check attribute certificate is valid
153        attCert.certFilePathList = self.acCACertFilePathList
154        attCert.isValid(raiseExcep=True)
155           
156        # Check it's issuer is as expected
157        if attCert.issuerName != self.acIssuerName:
158            raise OwsError, "Attribute Certificate issuer must match " + \
159                "this data provider's Attribute Authority name id"
160                       
161        return True, self.__class__.AccessAllowedMsg
162       
Note: See TracBrowser for help on using the repository browser.