Package SPyRO :: Module policies
[hide private]
[frames] | no frames]

Source Code for Module SPyRO.policies

  1  #coding: utf-8; 
  2  __doc__ = """ 
  3  This module implements a set of predefined sharing policies in SPyRO 
  4  The policies are very important in order to keep safe your servers. 
  5   
  6  Sharing Policies specifies what kind of clients must be allowed to connect 
  7  and what resources are capable of use in SPyRO servers and objects. 
  8   
  9  Policies exists at object granularity and attribute object granularity. 
 10  Every client that request objects operations and execution of methods 
 11  are granted with the authorization of a guardian object called Authority 
 12  that must implements the following methods: 
 13   
 14      @every method receives one dictionary (req, the spyro request) with the following keys: 
 15          |objname| The object name (ID in the server) 
 16          |attrname| The name of the requested attribute 
 17          |rettype| The type to return or send objects (REF to send by reference or VAL to send by value) 
 18          |reqtype| The type of the request. It can be ReqBye (BYE), ReqGetAttr (GET), 
 19                    ReqSetAttr (SET), ReqCallMethod (CALL), (ReqDelObj) DEL 
 20          |obj| The requested object (if any), not available to can_follow_objname 
 21          Additionally it could have any of the following keys (if the reqtype applies): 
 22              |local_server| The server of the remote caller (If ) 
 23              |value| in the SET reqtype 
 24              In the CALL request: 
 25                  |args|. Positional arguments 
 26                  |kwargs|. Keyword arguments 
 27              And optionally: 
 28                  |extra| Used to send data between calls (as user level routing info) 
 29       
 30      def can_set(self, req): 
 31          Return True if |auth| is granted to perform a set operation in 
 32          the guarded object (i.e. obj.x = y), False otherwise.  
 33   
 34      def can_get(self, req): 
 35          Return True if |auth| is granted to perform a get operation in 
 36          the guarded object (i.e. obj.x), False otherwise.  
 37   
 38      def can_del(self, req): 
 39          ** TODO & Warning: 
 40              this method must (and will) be renamed to can_unregister and 
 41              and del must be used as del attribute ** 
 42          Return True if |auth| is granted to unregister the guarded object. 
 43   
 44   
 45      def can_call(self, req): 
 46          Return True if |auth| is granted to perform a call in a method 
 47          of the guarded object (i.e. obj.meth()). 
 48          Note that is necesary return True in can_get to use transparent 
 49          mode in SPyRO. In transluced mode is not necesary. 
 50   
 51      def can_follow_objname(self, req): 
 52          Return True if |auth| is granted to access using the dot operator 
 53          in the method or attribute name to access attributes of attributes 
 54          (i.e. obj.attr1.attr2[...]) 
 55   
 56      def can_register(self, req): 
 57          Return True if |auth| is granted to register new objects in server, 
 58          is needed to return objects by reference. 
 59   
 60   
 61  Note: A bunch of predefined authorities are provided in this module, but if 
 62  a more specific Authority is needed it must be implemented 
 63   
 64   
 65  Note: auth key can be None, because is the default (no authorization provided from the client side) 
 66        The meaning of None and the effect is responsability of the Authority implementation 
 67  Note: If the Policy is None (at server side) all properties are granted, this is the default. 
 68   
 69  """ 
 70   
 71  import types 
72 -def _set_booleans():
73 BooleanType = types.IntType 74 __builtins__['True'] = 1 75 __builtins__['False'] = 0
76 77 try: 78 BooleanType = types.BooleanType 79 True 80 except: 81 warn.warn("An old version of python or jython was detected") 82 _set_booleans() 83 84 import warn 85 warn = warn.Warn("SPyRO.policies") 86 ############################################################################## 87 ############################################################################## 88 ##### Authentication methods 89 ############################################################################## 90 ############################################################################## 91
92 -class AuthError(Exception):
93 """ Authentication Error """ 94 pass
95 96 # class AuthorizationRequest: 97 # def __init__(self): 98 # pass 99 # 100 # def setstate(self, state): 101 # for k,v in state.items(): 102 # setattr(self,k,v) 103 # return self 104 # 105 # class AuthPasswordRequest(AuthorizationRequest): 106 # """ A Request to authenticate with the user/password schema""" 107 # def __init__(self, username, password): 108 # self.username = username 109 # self.password = password 110 111 112 ############################################################################## 113 ############################################################################## 114 ##### Mixin section 115 ############################################################################## 116 ############################################################################## 117
118 -class MixinCheckDB:
119 """ Mixin to check against username-password pairs (dictionary like object) """
120 - def _initCheckDB(self, allowed):
121 self.allowed = allowed
122
123 - def _auth(self, req):
124 """ Check credentials """ 125 # if not isinstance(auth, AuthorizationRequest): return False 126 try: 127 u = self.allowed.get(req['auth']['username']) 128 return u and u == req['auth']['password'] 129 except (KeyError, TypeError): 130 return False
131
132 - def _isgood(self, req):
133 return self._auth(req)
134
135 -class MixinPublicAuth:
136 - def _auth(self, req):
137 return True
138
139 - def _isgood(self, req):
140 return True
141
142 -class MixinDenyUnderscore:
143 """ Mixin to deny every attribute starting with underscore '_' character """
144 - def _isgood(self, req):
145 return self._auth(req) and req['attrname'][0] != '_'
146
147 -class MixinDenyAll:
148 """ Mixin that deny all options, it must be taken as parent class """
149 - def can_set(self, req):
150 return False
151
152 - def can_get(self, req):
153 return False
154
155 - def can_del(self, req):
156 return False
157
158 - def can_call(self, req):
159 return False
160
161 - def can_follow_objname(self, req):
162 return False
163
164 - def can_register(self, req):
165 return False
166
167 -class MixinAllowAllChecking:
168 """ Mixin that allows all options, useful as parent class """
169 - def can_set(self, req):
170 return self._isgood(req)
171
172 - def can_get(self, req):
173 return self._isgood(req)
174
175 - def can_del(self, req):
176 return self._isgood(req)
177
178 - def can_call(self, req):
179 return self._isgood(req)
180
181 - def can_follow_objname(self, req):
182 return self._isgood(req)
183
184 - def can_register(self, req):
185 return self._isgood(req)
186
187 -class MixinAllowCall:
188 """ Allow call methods, the methods must not start 189 with '_' underscore. If an special authentication method is needed _auth 190 method must be overloaded. """
191 - def can_get(self, req):
192 try: 193 attr = getattr(req['obj'], req['attrname']) 194 except AttributeError: 195 return False 196 return callable(attr) and self._isgood(req)
197
198 - def can_call(self, req):
199 return self._isgood(req)
200 201 202 ############################################################################## 203 ############################################################################## 204 ##### Authorities 205 ############################################################################## 206 ############################################################################## 207 208 ## Public authorities 209 210
211 -class PublicAllowCall(MixinDenyUnderscore, 212 MixinAllowCall, 213 MixinDenyAll, 214 MixinPublicAuth):
215 """ Allow call methods that does not start with underscore 216 """ 217 pass
218
219 -class PublicAllowAllCall(MixinAllowCall, 220 MixinDenyAll, 221 MixinPublicAuth):
222 """ 223 Allow all call request (even private methods aka. 224 starting '_') 225 """ 226 pass
227
228 -class PublicAllowAll(MixinAllowAllChecking, 229 MixinPublicAuth):
230 """ 231 Allow all operations 232 """ 233 pass
234
235 -class PublicAllowAllButDenyUnderscore(MixinDenyUnderscore, 236 MixinAllowAllChecking, 237 MixinPublicAuth):
238 """ 239 Allow all operations, but deny attrname starting with 240 underscore '_' 241 """ 242 pass
243 244 ## Authentication needed 245
246 -class AuthAllowCall(MixinDenyUnderscore, 247 MixinCheckDB, 248 MixinAllowCall, 249 MixinDenyAll):
250 """ Allow call methods that does not start with underscore 251 Every request must be qualified by the MixinCheckDB _auth method 252 """
253 - def __init__(self, allowed):
254 self._initCheckDB(allowed)
255 256
257 -class AuthAllowAllCall(MixinCheckDB, 258 MixinPublicAuth, 259 MixinAllowCall, 260 MixinDenyAll):
261 """ 262 Allow all call request (even starting '_') 263 Every request must be qualified by the MixinCheckDB _auth method 264 """
265 - def __init__(self, allowed):
266 self._initCheckDB(allowed)
267
268 -class AuthAllowAll(MixinCheckDB, 269 MixinAllowAllChecking):
270 """ 271 Allow all operations 272 Every request must be qualified by the MixinCheckDB _auth method 273 """
274 - def __init__(self, allowed):
275 self._initCheckDB(allowed)
276
277 -class AuthAllowAllButDenyUnderscore(MixinDenyUnderscore, 278 MixinCheckDB, 279 MixinAllowAllChecking):
280 """ 281 Allow all operations, but deny attrname starting with 282 underscore '_'. 283 Every request must be qualified by the MixinCheckDB _auth method 284 """
285 - def __init__(self, allowed):
286 self._initCheckDB(allowed)
287