Hi Mike, Thanks for the pointer. On 12 September 2013 14:58, Mike Müller <[email protected]> wrote: > Hi > > The common way to solve such an access control for a provider like > the Cassandra resource provider is the new ResourceAccessSecurity > service. This is implemented in the bundle resourceaccesssecurity > (at this time only read rights will be checked).
Incidentally, how will other rights be enforced ? the update pattern is resource.adaptTo(ModifiableValueMap.class) would the adapter factory check that the current user has write access to the resource before they can get their hands on a ModifiableValueMap ? Best Regards Ian All you have to do is to > implement the SPI ResourceAccessGate for the Cassandra provider > and set the provider.useResourceAccessSecurity property to true > for your ResourceProvider. > By time resourceaccesssecurity will also implement create, modify > And delete rights. > > Best regards > mike > >> -----Original Message----- >> From: Dishara Wijewardana [mailto:[email protected]] >> Sent: Thursday, September 12, 2013 2:25 PM >> To: [email protected] >> Subject: Re: [GSoC2013] Access Control for Cassandra ResourceProvider >> >> Hi Ian >> >> >> On Thu, Sep 12, 2013 at 1:50 PM, Ian Boston <[email protected]> wrote: >> >> > Hi Dishara, >> > To make the Cassandra Resource Provider really useful I think we need >> > to add access control. I think the best way of doing this is to borrow >> > some concepts from Jackrabbit access control. >> > >> > >> The following algorithms, and etc does sling already have any >> implementation of it. If so I can reuse them. Since sling has few providers >> I believe they probably have some common interface. >> >> >> > Take a deep breath, and you will see why I left this till last. >> > >> > I think we should provide path base access control, which inherits >> > from parent resources in the path. At every level there is a an >> > ordered list of access control entries each access control entry (ACE) >> > being either an allow entry or a deny entry. What is allowed or denied >> > is defined in a 32bit bitmap with each bit representing 1 permission, >> > so we can have upto 32 permissions. Each ACE specifies a single >> > principal. So an ACL consists of a ordered list of ACE's each one >> > bound to a principal. >> > >> > A user has a set of principals, so to resolve the ACL at any one path >> > for a user the global ACL is filtered to contain only the ACE's with >> > principals that the user has. >> > >> > Computing a final access control bitmap for a user at a location >> > requires ordered processing of all the ACEs relevant to the user at >> > the current path and then all ancestors. >> > >> > The pseudo algorithm to calculate the a grant bitmap and a deny bitmap >> > at any level is: >> > >> > function getCurrentLevelBitmaps(currentPath): >> > int grants = 0; >> > int denies = 0; >> > for all ACEs in the ACL at the currentPath: >> > if the user has the principal of the current ACE: >> > int toGrant = 0; >> > int toDeny = 0; >> > if the ACE is a grant: >> > toGrant = the ACE bitmap; >> > else: >> > toDeny = the ACE bitmap; >> > toGrant = toGrant & ~denies; >> > toDeny = toDeny & ~grants; >> > grants = grants | toGrant; >> > denied = denies | toDenies; >> > return (grants, denies); >> > >> >> - Can you please tell me how to calculate the ACE bitmap ? >> - Also I will be more clear if you can provide a sample value for the input >> and output of this function ? i.e When currentPath= >> /content/cassandra/foo/bar it returns grants=? denies=? some actual values >> just for my understanding. >> >> >> > To combine what is granted at the child level with what is granted at >> > a parent level we need to mask the parent level with the deny at the >> > child level. >> > >> > eg >> > toGrant = grantedAtParent & ~denies; >> > toDeny = deniedAtParent & ~grants; >> > grants = grants | toGrant; >> > denied = denies | toDenies; >> > >> > The simplest way of achieving this is to use recursion again in pseudo >> > code: >> > >> > function buildAtLevel(): >> > if not root level: >> > (grantedAtParent, deniedAtParent) = >> > buildAtLevel(getParentLevel(currentLevel)); >> > (grants, denies) = getCurrentLevelBitmaps(currentLevel); >> > toGrant = grantedAtParent & ~denies; >> > toDeny = deniedAtParent & ~grants; >> > grants = grants | toGrant; >> > denied = denies | toDenies; >> > return (grants, denied); >> > >> > >> > There are some optimisations you can apply here, and there are plenty >> > of opportunities to cache intermediate bitmaps in memory. Just caching >> > the ACL reduces resolution to bitwise operations. >> > >> > Principals >> > ---------------- >> > Initially keep it simple. >> > >> > read = 0x01 >> > write = 0x02 >> > delete = 0x04 >> > >> > Storage of ACLs. >> > ------------------------- >> > I suggest you store ACLs in their own Column Family, where the rowID is >> > base64(sha1(path)) or whatever path -> rowid encoding you have currently. >> > >> > IIRC Cassandra columns come out in the natural order of Strings >> > <order>_<principal>_<allow|deny> and the value is the bitmap of >> > permissions. >> > >> > - If I understand you correctly is <order>_<principal>_<allow|deny> is >> one ACE ? If per row there can be a ACL, there should be one additional >> column by default called "ACL" and it will have a comma separated string >> which are set of ACEs. Correct me if I am wrong. >> - Who stores these ACEs ? any API? >> - i.e <order> is a auto increment number we have to do a additional read >> before storing ACE to check what is the last number for <order>. >> >> Where <order> is 000 to 999 ( I really doubt that a single ACL will >> > have 1000 ACEs ever) >> > >> > Once you have this working, we can wire it into the ResourceProvider >> > or another Sling API. >> > >> > Does that make sense ? >> > Ian >> > >> >> >> >> -- >> Thanks >> /Dishara
