Can SecurityPolicy handle multi rules ?

SecurityPolicy is a good idea, but it hasn't multi RULES.

SecurityPolicy and SecurityRules

sr.png

In Unix world, ACL is a very common control. that control how to access system resource and what is the way to access the system resource.

ACL system is like SecurityPolicy. ACL has more rules.

   1 class SecurityPolicy:
   2     def get_security_rules(self):
   3         return [security_rule_a, security_rule_b]

security_rule define a pattern. let MoinMoin to check it.

   1 class security_rules:
   2     def check_pattern(self, request, attr):
   3         if request match pattern about attr:
   4             return True
   5         else:
   6             return False
   7 
   8 class security_rule_a(security_rules):
   9     ....

And the rule have a JUMP like ( accept / Drop ) or ( allow / Deny ) or more . ( What is JUMP ? Please see man 8 iptables. )

maybe you can rewrite the code like this.

   1 class security_rules:
   2     def __init__(self, request, jump):
   3         self.jump = jump
   4     def check_pattern(self, request, attr):
   5         if request match pattern about attr:
   6             return self.jump
   7         else: return None

policy in Iptables

If you reference iptables rules, it has policy. What is it ?

In here, I suggest use MoinMoin's acl_rights_default to be policy. so:

   1 class security_policy:
   2     def get_security_rules(self):
   3         return [security_rule_a, security_rule_b, security_rule_moin_acl]

Reference to Apache's mod_access

If you reference to mod_access, It was ordering by ALLOW and DENY, If the httpd.conf setting is like this

order allow,deny

see the deny items first.

order deny,allow

see the allow items first.

What problem in here ?

  1. moin_acl maybe need to rewrite.
  2. How to handle MoinMoin.util.antispam and Old SecurityPolicy Object.

  3. What about attr of save ? ( this is diff of read,write,... )
  4. Do People like this ?

Solutions

If you handle it. you need to modify the MoinMoin/security.py .

   1 import MoinMoin.securityrule as SecurityRule 
   2 ...
   3 class DefaultConfig:
   4     ...
   5     security_rules = [{'rule' :SecurityRule.vaild_user, "is_non": 0, 'write': 0}]
   6     security_rules_fifo = 0
   7     ...

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     MoinMoin - Wiki Security Interface
   4 
   5     This implements the basic interface for user permissions and
   6     system policy. If you want to define your own policy, inherit
   7     from the base class 'Permissions', so that when new permissions
   8     are defined, you get the defaults.
   9 
  10     Then assign your new class to "SecurityPolicy" in wikiconfig;
  11     and I mean the class, not an instance of it!
  12 
  13     @copyright: 2000-2004 by Jürgen Hermann <jh@web.de>
  14     @license: GNU GPL, see COPYING for details.
  15 """
  16 
  17 #############################################################################
  18 ### Basic Permissions Interface -- most features enabled by default
  19 #############################################################################
  20 
  21 
  22 class Permissions:
  23     """ Basic interface for user permissions and system policy.
  24 
  25         Note that you still need to allow some of the related actions, this
  26         just controls their behaviour, not their activation.
  27     """
  28 
  29     def __init__(self, user):
  30         """ Calculate the permissons `user` has.
  31         """
  32         from MoinMoin.Page import Page
  33         self.Page = Page
  34         self.name = user.name
  35         self.request = user._request
  36 
  37     def save(self, editor, newtext, rev, **kw):
  38         """ Check whether user may save a page.
  39 
  40             `editor` is the PageEditor instance, the other arguments are
  41             those of the `PageEditor.saveText` method.
  42         """
  43         return self.write(editor.page_name)
  44 
  45     def __getattr__(self, attr):
  46         request = self.request
  47         Page = self.Page
  48 
  49         # check right in security_rules
  50         for s in request.cfg.security_rules:
  51             # Make Sure the SecurityRules have 'rule' and attr
  52             # and the SecurityRules is a Dict.
  53             try:
  54                 if s.has_key('rule') and s.has_key(attr):
  55                    valid_security_rule = 1
  56                 else:
  57                    valid_security_rule = 0
  58             except AttributeError:
  59                 valid_security_rule = 0
  60             if valid_security_rule:
  61                 sr = s['rule']
  62                 security_rule = sr(request.user, s)
  63                 # Check dict again, Is it developer like ?
  64                 if security_rule.check_dict(attr):
  65                     return lambda pagename, **kw: getattr(security_rule, attr)(pagename, **kw)
  66 
  67         # If cann't check in security_rules, try it in moin_acl
  68         if attr in request.cfg.acl_rights_valid:
  69             return lambda pagename, Page=Page, request=request, attr=attr: Page(request, pagename).getACL(request).may(request, self.name, attr)
  70         else:
  71             raise AttributeError, attr
  72         
  73 
  74 # make an alias for the default policy
  75 Default = Permissions

security.py

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3 @copyright: (c) Bastian Blank, Florian Festi, Thomas Waldmann
   4 @copyright: MoinMoin:FrankieChow
   5 @license: GNU GPL, see COPYING for details.
   6 """
   7 
   8 class security_rules_obj:
   9     """ Template of SecurityRules Object
  10     """
  11 
  12     def __init__(self, user, dict):
  13         """ Calculate the permissons `user` has.
  14         """
  15         self.user = user
  16         self.name = user.name
  17         self.request = user._request
  18         self.dict = dict
  19 
  20     def cal_rule_result(self):
  21         """ Cal the dict('is_non') and set the rule_result.
  22         """
  23         if self.dict.has_key('is_non'):
  24             self.rule_result = self.dict['is_non'] * self.match_rule()
  25         else:
  26             self.rule_result = self.match_rule()
  27 
  28     def check_dict(self):
  29         """
  30         Developer can override it to check pass dict.
  31         """
  32         self.cal_rule_result()
  33         if getattr(self, attr, 0):
  34             return 1
  35 
  36     def true(self, pagename, **kw):
  37         return 1
  38     def false(self, pagename, **kw):
  39         return 0
  40 
  41     def __getattr__(self, attr):
  42         if not self.rule_result: raise AttributeError, attr
  43         if self.dict[attr]:
  44             return lambda pagename, **kw: self.true(pagename, **kw)
  45         else:
  46             return lambda pagename, **kw: self.false(pagename, **kw)
  47 
  48 class vaild_user(security_rules_obj):
  49     """
  50     Maybe Developer must need to write this module.
  51     """
  52     def match_rule(self):
  53         if self.user.valid:
  54             return 1
  55         else:
  56             return 0

securityrule.py

   1     from MoinMoin.util.antispam import SecurityPolicy

Above case

:D Yes, I know this case is easy done by acl, ( But don't easy done in SecurityPolicy. And you can thank more about it!)

:-? I will give you the using case, later.

Using Case

This is some using case by security_rules. I think, this is very useful.

Allow Google, Yahoo, Baidu and MSN to read your moin

This is my security_rule to allow the search engine to read moin.

This is in MoinMoin/securityrule.py

   1 class google_yahoo(security_rules_obj):
   2     def match_rule(self):
   3         if self.request.http_user_agent in [
   4          'Baiduspider+(+http://www.baidu.com/search/spider.htm)',
   5          'Googlebot/2.1 (+http://www.google.com/bot.html)',
   6          'Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)',
   7          'Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html)',
   8          'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
   9          'msnbot/1.0 (+http://search.msn.com/msnbot.htm)',
  10          ]: return 1

I don't like FlashGet

   1 class flashget(security_rules_obj):
   2     def match_rule(self):
   3         if self.request.http_user_agent in [
   4          'FlashGet',
   5          ]: return 1

I want Member can write under His name subpages

   1 class user_subpages(security_rules_obj):
   2     def match_rule(self):
   3         if self.user.valid and self.request.page.page_name.startswith(self.name):
   4             return 1
   5         else: return 0

This is my wikiconfig.py

   1     import MoinMoin.securityrule as SecurityRule
   2     security_rules = [{"rule": SecurityRule.google_yahoo, 'read': 1},
   3            {"rule": SecurityRule.flashget, 'read': 0, 'write': 0},
   4            {"rule": SecurityRule.user_subpages, 'write': 1, 'read': 1},
   5                       ]

Discussion

You do not really need this if you use python inheritance. I think the following should solve your issue (haven't tested it ;-) ). -- RobertSeeger 2006-01-11 10:49:31

   1 from MoinMoin.security import Permissions
   2 from MoinMoin.util.antispam import SecurityPolicy as AntiSpamPolicy
   3 
   4 class Config(...):
   5 
   6     class SecurityPolicy(AntiSpamPolicy):
   7         def write(self, pagename, **kw):
   8             return self.request.user.valid

Yes, I known it. but if I have more then two rules ? -- FrankieChow 2006-01-11 19:19:00

summary of purpose?

It is hard to understand what this feature request is all about. Perhaps a bit more overview could be useful. I think I see what you are attempting, but please correct me. Here's my best interpretation:

The term rule as you've used it is really more like a kind of security test, or an access control system. For instance the ACL is one such system or rule. The antispam stuff is a different one, and so on. What you are doing is allowing the wiki to be configured to have any number of such systems, as a list. This is perhaps more flexible than relying on inheritance as a way to combin multiple access systems.

Then when evaluating permissions you seem to just scan that list (security_rules[]) looking for "rules" which supports the given attribute, such as "write", "read", etc. Also you look for the presence of a similarly named attribute, such as "write_non_continue". Then you only return the last rule which has the given attribute, but you stop scanning the rules list at the first _non_continue one.

Is that basically correct? One question I have is why not return a lambda which instead evaluates ALL the matching rules and not just the last one? - -- DeronMeranda 2006-01-12 17:25:08

That is, the permission is granted only if ALL the rules testing that permission type grant it. - -- DeronMeranda 2006-01-12 17:25:08

   1     def __getattr__(self, attr):
   2         ...
   3         request = self.request
   4         Page = self.Page
   5         if attr in request.cfg.acl_rights_valid:
   6             return lambda pagename, Page=Page, request=request, attr=attr: Page(request, pagename).getACL(request).may(request, self.name, attr)
   7         else:
   8             raise AttributeError, attr

   1 return lambda pagename, Page=Page, request=request, attr=attr: Page(request,    
   2            pagename).getACL(request).may(request, self.name, attr)


CategoryFeatureRequest

MoinMoin: FeatureRequests/SecurityRules (last edited 2007-10-29 19:08:54 by localhost)