1 | from ows_common.exception_report import OwsError |
---|
2 | from pylons import request |
---|
3 | from ndg.security.common.SessionMgr import SessionMgrClient, \ |
---|
4 | AttributeRequestDenied |
---|
5 | |
---|
6 | def 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 |
---|
13 | class 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 | # TODO: fix this ref. |
---|
37 | self.ndgCfg = request.environ['ndgConfig'] |
---|
38 | |
---|
39 | self.tracefile = eval(self.ndgCfg.get('NDG_SECURITY','tracefile')) |
---|
40 | |
---|
41 | # ... for SSL connections to security web services |
---|
42 | try: |
---|
43 | self.sslCACertFilePathList = \ |
---|
44 | self.ndgCfg.get('NDG_SECURITY','sslCACertFilePathList').split() |
---|
45 | |
---|
46 | except AttributeError: |
---|
47 | raise OwsError, 'No "sslCACertFilePathList" security setting' |
---|
48 | |
---|
49 | self.sslPeerCertCN = self.ndgCfg.get('NDG_SECURITY', 'sslPeerCertCN') |
---|
50 | |
---|
51 | # ...and for WS-Security digital signature |
---|
52 | self.wssCertFilePath = self.ndgCfg.get('NDG_SECURITY', |
---|
53 | 'wssCertFilePath') |
---|
54 | self.wssPriKeyFilePath = self.ndgCfg.get('NDG_SECURITY', |
---|
55 | 'wssKeyFilePath') |
---|
56 | self.wssPriKeyPwd = self.ndgCfg.get('NDG_SECURITY', 'wssKeyPwd') |
---|
57 | |
---|
58 | try: |
---|
59 | self.wssCACertFilePathList = \ |
---|
60 | self.ndgCfg.get('NDG_SECURITY', 'wssCACertFilePathList').split() |
---|
61 | |
---|
62 | except AttributeError: |
---|
63 | raise OwsError, 'No "wssCACertFilePathList" security setting' |
---|
64 | |
---|
65 | # Attribute Certificate verification of X.509 cert chain back to CA |
---|
66 | try: |
---|
67 | self.acCACertFilePathList = \ |
---|
68 | self.ndgCfg.get('NDG_SECURITY', 'acCACertFilePathList').split() |
---|
69 | |
---|
70 | except AttributeError: |
---|
71 | raise OwsError, 'No "wssCACertFilePathList" security setting' |
---|
72 | |
---|
73 | # Create Session Manager client |
---|
74 | self.smClnt = SessionMgrClient(uri=self.securityTokens['smURI'], |
---|
75 | sslCACertFilePathList=self.sslCACertFilePathList, |
---|
76 | sslPeerCertCN=self.sslPeerCertCN, |
---|
77 | signingCertChain=securityTokens.get('wssCertChain'), |
---|
78 | signingCertFilePath=self.wssCertFilePath, |
---|
79 | signingPriKeyFilePath=self.wssPriKeyFilePath, |
---|
80 | signingPriKeyPwd=self.wssPriKeyPwd, |
---|
81 | caCertFilePathList=self.wssCACertFilePathList, |
---|
82 | tracefile=self.tracefile) |
---|
83 | |
---|
84 | # Fix WS-Security BinarySecurityToken Value Type for the passing of a |
---|
85 | # cert chain - required for use with proxy cert. |
---|
86 | if wssCertChain: |
---|
87 | self.smClnt.signatureHandler.reqBinSecTokValType = 'X509PKIPathv1' |
---|
88 | |
---|
89 | |
---|
90 | def __call__(self, **kw): |
---|
91 | """Convenience wrapper for checAccess""" |
---|
92 | return self.checkAccess(**kw) |
---|
93 | |
---|
94 | |
---|
95 | def checkAccess(self, securityElement=None, securityTokens=None): |
---|
96 | """Make an access control decision based on whether the user is |
---|
97 | authenticated and has the required roles |
---|
98 | |
---|
99 | @type: ? TODO: set type |
---|
100 | @keyword securityElement: CSML security constraint containing role and |
---|
101 | Attribute Authority URI. Resets equivalent object attribute. |
---|
102 | |
---|
103 | @type: pylons.session |
---|
104 | @keyword securityTokens: dict-like session object containing security |
---|
105 | tokens. Resets equivalent object attribute.""" |
---|
106 | |
---|
107 | if securityElement: |
---|
108 | self.securityElement = securityElement |
---|
109 | |
---|
110 | if securityTokens: |
---|
111 | self.securityTokens = securityTokens |
---|
112 | |
---|
113 | if self.securityTokens is not None: |
---|
114 | return self.__checkAttCert() |
---|
115 | else: |
---|
116 | return False, self.__class__.NotLoggedInMsg |
---|
117 | |
---|
118 | |
---|
119 | def __checkAttCert(self): |
---|
120 | """Check to see if the Session Manager can deliver an Attribute |
---|
121 | Certificate with the required role to gain access to the resource |
---|
122 | in question""" |
---|
123 | |
---|
124 | try: |
---|
125 | # Get the Attribute Authority address for the Session Manager to |
---|
126 | # send its attribute request to |
---|
127 | # |
---|
128 | # # TODO: get the correct AA URI attribute name |
---|
129 | aaURI = self.securityElement.aaURI |
---|
130 | |
---|
131 | # Make request for attribute certificate |
---|
132 | # |
---|
133 | # sessID is needed if proxy cert is unavailable as ID |
---|
134 | # |
---|
135 | # TODO: get correct role name attribute from securityElement var |
---|
136 | attCert = self.smClnt.getAttCert(attAuthorityURI=aaURI, |
---|
137 | sessID=self.securityToken.get('sessID'), |
---|
138 | reqRole=self.securityElement.roleName) |
---|
139 | |
---|
140 | except AttributeRequestDenied, e: |
---|
141 | # TODO: write exception to log |
---|
142 | return False, self.__class__.AccessDeniedMsg |
---|
143 | |
---|
144 | # Check attribute certificate is valid |
---|
145 | attCert.certFilePathList = self.acCACertFilePathList |
---|
146 | attCert.isValid(raiseExcep=True) |
---|
147 | |
---|
148 | # Check it's issuer is as expected |
---|
149 | if attCert.issuerName != self.acIssuerName: |
---|
150 | raise OwsError, "Attribute Certificate issuer must match " + \ |
---|
151 | "this data provider's Attribute Authority name id" |
---|
152 | |
---|
153 | return True, self.__class__.AccessAllowedMsg |
---|
154 | |
---|