How to invalidate security cache?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

How to invalidate security cache?

abtv
I have XWiki and a separate app. I need to use my app permissions in XWiki. XWiki uses security cache and asks my app for a particular permission only once. I need to make XWiki aware about permission changes in my app.

I have several options:
1. sometimes I invalidate cache in my application. I could call xwiki api to invalidate the whole xwiki cache when I invalidate my app cache.
2. from time to time (say, every minute) make a REST call to my app. My app says if cache was invalidated. If it was I would like to invalidate xwiki cache.

My questions are:
1. how to invalidate the whole cache? I implemented CustomSecurityCacheInvalidator, but it seems like I can remove only separate entities there via `remove` call. As I understand I have to call `suspend` and then remove entities from the cache and then call `resume`, right? But SecurityCache has only `get` and `remove` methods for separate entities.
2. should I create a separate `Component` for scheduler which will poll data from my app from time to time? I could start new thread there to ask my app on schedule and Inject CustomSecurityCacheInvalidator. Is it the right approach?

My class is here:

@Component
@Singleton
public class CustomSecurityCacheInvalidator extends DefaultSecurityCacheRulesInvalidator {

    @Inject
    private SecurityCache securityCache;

    @Override
    public void suspend() {
        System.out.println("suspend!");
        super.suspend();

        //I can use securityCache here
    }

    @Override
    public void resume() {
        System.out.println("resume!");
        super.resume();
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: How to invalidate security cache?

Denis Gervalle-2
Hi Andrey,

On Fri, Apr 22, 2016 at 11:34 AM, abtv <[hidden email]> wrote:

> I have XWiki and a separate app. I need to use my app permissions in XWiki.
> XWiki uses security cache and asks my app for a particular permission only
> once. I need to make XWiki aware about permission changes in my app.
>
> I have several options:
> 1. sometimes I invalidate cache in my application. I could call xwiki api
> to
> invalidate the whole xwiki cache when I invalidate my app cache.
> 2. from time to time (say, every minute) make a REST call to my app. My app
> says if cache was invalidated. If it was I would like to invalidate xwiki
> cache.
>
> My questions are:
> 1. how to invalidate the whole cache? I implemented
> CustomSecurityCacheInvalidator, but it seems like I can remove only
> separate
> entities there via `remove` call. As I understand I have to call `suspend`
> and then remove entities from the cache and then call `resume`, right? But
> SecurityCache has only `get` and `remove` methods for separate entities.
>

No you are wrong, the suspend / resume method that you have to implement
will be called by the SecurityCacheLoader to inform your invalidator  to
suspend his work. This happen each time the cache is affected.

When you evict a reference in the cache, you will effectively evict all its
dependencies… for example if you evict a space, all the documents in that
space are evicted as well, if you evict a user, all access decisions made
previously for that user is evicted, if you evict a group, all user of that
group (and therefore access decisions for those users) will be evicted.

Emptying the cache is equivalent to evicting the main wiki (farm). The
reference to the main wiki (farm) is easy to build, just pass a null
reference to the security reference factory.



> 2. should I create a separate `Component` for scheduler which will poll
> data
> from my app from time to time? I could start new thread there to ask my app
> on schedule and Inject CustomSecurityCacheInvalidator. Is it the right
> approach?
>

Well, the best would be that your external service trigger your invalidator
maybe through a REST service that generate events. If you base your work on
events, it is event easier, because you just have to override the
SecurityCacheRulesInvalidatorListener, and the suspend>resume aspect will
be managed for you. You just have to listen to your own event, that your
REST service would generate.
To create a REST service in XWiki, this could be as easy as writing a
scripted XWiki page for example.
Regarding events and listener, you can read:
http://extensions.xwiki.org/xwiki/bin/view/Extension/Observation+Module+Local

Regards,


>
> My class is here:
>
> @Component
> @Singleton
> public class CustomSecurityCacheInvalidator extends
> DefaultSecurityCacheRulesInvalidator {
>
>     @Inject
>     private SecurityCache securityCache;
>
>     @Override
>     public void suspend() {
>         System.out.println("suspend!");
>         super.suspend();
>
>         //I can use securityCache here
>     }
>
>     @Override
>     public void resume() {
>         System.out.println("resume!");
>         super.resume();
>     }
> }
>
>
>
> --
> View this message in context:
> http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138.html
> Sent from the XWiki- Dev mailing list archive at Nabble.com.
> _______________________________________________
> devs mailing list
> [hidden email]
> http://lists.xwiki.org/mailman/listinfo/devs
>



--
Denis Gervalle
SOFTEC sa - CEO
_______________________________________________
devs mailing list
[hidden email]
http://lists.xwiki.org/mailman/listinfo/devs
Reply | Threaded
Open this post in threaded view
|

Re: How to invalidate security cache?

abtv
I haven't found SecurityCacheRulesInvalidatorListener class/interface and implemented it in the following (code below). Can I clean cache like this?

public class CleanCacheEvent extends AbstractWikiEvent {
   public CleanCacheEvent(){
      super();
   }
}

@Component
@Named("SecurityCacheRulesInvalidatorListener")
@Singleton
public class CustomSecurityCacheRulesInvalidatorListener extends AbstractEventListener {
    @Inject
    private SecurityCache securityCache;

    @Inject
    private SecurityReferenceFactory securityReferenceFactory;

    public CustomSecurityCacheRulesInvalidatorListener() {
        super("SecurityCacheRulesInvalidatorListener", new CleanCacheEvent());
    }

    public void onEvent(Event event, Object source, Object data) {
        System.out.println("on invalidator listener event");
        SecurityReference root = securityReferenceFactory.newEntityReference(null);
        securityCache.remove(root);
        System.out.println("cache was cleaned");
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: How to invalidate security cache?

Denis Gervalle-2
Hi Andrey,

Here it is:
https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultSecurityCacheRulesInvalidatorListener.java

This is the listener you need to replace, and you need to care about
the readWriteLock mechanism in place in the original version.
For the rest, your implementation looks ok, but it is harsh to clean the
whole cache, and it would be better to be more granular if possible (at
least per wiki, per user, per group, per space‚Ķ,  regarding the per group
case, be careful of the special case adding a user to a group introduce,
since you also need to drop that new user in addition to the group it
joins).

Regards,


On Mon, Apr 25, 2016 at 6:37 PM, abtv <[hidden email]> wrote:

> I haven't found SecurityCacheRulesInvalidatorListener class/interface and
> implemented it in the following (code below). Can I clean cache like this?
>
> public class CleanCacheEvent extends AbstractWikiEvent {
>    public CleanCacheEvent(){
>       super();
>    }
> }
>
> @Component
> @Named("SecurityCacheRulesInvalidatorListener")
> @Singleton
> public class CustomSecurityCacheRulesInvalidatorListener extends
> AbstractEventListener {
>     @Inject
>     private SecurityCache securityCache;
>
>     @Inject
>     private SecurityReferenceFactory securityReferenceFactory;
>
>     public CustomSecurityCacheRulesInvalidatorListener() {
>         super("SecurityCacheRulesInvalidatorListener", new
> CleanCacheEvent());
>     }
>
>     public void onEvent(Event event, Object source, Object data) {
>         System.out.println("on invalidator listener event");
>         SecurityReference root =
> securityReferenceFactory.newEntityReference(null);
>         securityCache.remove(root);
>         System.out.println("cache was cleaned");
>     }
> }
>
>
>
> --
> View this message in context:
> http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138p7599203.html
> Sent from the XWiki- Dev mailing list archive at Nabble.com.
> _______________________________________________
> devs mailing list
> [hidden email]
> http://lists.xwiki.org/mailman/listinfo/devs
>



--
Denis Gervalle
SOFTEC sa - CEO
_______________________________________________
devs mailing list
[hidden email]
http://lists.xwiki.org/mailman/listinfo/devs
Reply | Threaded
Open this post in threaded view
|

Re: How to invalidate security cache?

abtv
Hi Denis!

Did you inserted code example to show how to use ReadWriteLock in place? Or I should override the default class? I just added ReadWriteLock, is it ok?

There is my final solution with Listener and it works on my machine:

I added the following to components.txt:
0:com.myproject.xwiki.cache.CustomSecurityCacheRulesInvalidatorListener

@Component
@Named("SecurityCacheRulesInvalidatorListener")
@Singleton
public class CustomSecurityCacheRulesInvalidatorListener extends AbstractEventListener {
    @Inject
    @Named(DefaultSecurityCacheRulesInvalidator.NAME)
    private ReadWriteLock readWriteLock;
    @Inject
    private SecurityCache securityCache;

    @Inject
    private SecurityReferenceFactory securityReferenceFactory;

    public CustomSecurityCacheRulesInvalidatorListener() {
        super(DefaultSecurityCacheRulesInvalidator.NAME, new CleanCacheEvent());
    }

    public void onEvent(Event event, Object source, Object data) {
        System.out.println("invalidating xwiki cache");
        readWriteLock.writeLock().lock();
        try {
            SecurityReference root = securityReferenceFactory.newEntityReference(null);
            securityCache.remove(root);
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: How to invalidate security cache?

Denis Gervalle-2
Hi Andrey,

Looks good to me.
Regards,


On Wed, Apr 27, 2016 at 5:53 PM, abtv <[hidden email]> wrote:

> Hi Denis!
>
> Did you inserted code example to show how to use ReadWriteLock in place? Or
> I should override the default class? I just added ReadWriteLock, is it ok?
>
> There is my final solution with Listener and it works on my machine:
>
> I added the following to components.txt:
> 0:com.myproject.xwiki.cache.CustomSecurityCacheRulesInvalidatorListener
>
> @Component
> @Named("SecurityCacheRulesInvalidatorListener")
> @Singleton
> public class CustomSecurityCacheRulesInvalidatorListener extends
> AbstractEventListener {
>     @Inject
>     @Named(DefaultSecurityCacheRulesInvalidator.NAME)
>     private ReadWriteLock readWriteLock;
>     @Inject
>     private SecurityCache securityCache;
>
>     @Inject
>     private SecurityReferenceFactory securityReferenceFactory;
>
>     public CustomSecurityCacheRulesInvalidatorListener() {
>         super(DefaultSecurityCacheRulesInvalidator.NAME, new
> CleanCacheEvent());
>     }
>
>     public void onEvent(Event event, Object source, Object data) {
>         System.out.println("invalidating xwiki cache");
>         readWriteLock.writeLock().lock();
>         try {
>             SecurityReference root =
> securityReferenceFactory.newEntityReference(null);
>             securityCache.remove(root);
>         } finally {
>             readWriteLock.writeLock().unlock();
>         }
>     }
> }
>
>
>
> --
> View this message in context:
> http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138p7599252.html
> Sent from the XWiki- Dev mailing list archive at Nabble.com.
> _______________________________________________
> devs mailing list
> [hidden email]
> http://lists.xwiki.org/mailman/listinfo/devs
>



--
Denis Gervalle
SOFTEC sa - CEO
_______________________________________________
devs mailing list
[hidden email]
http://lists.xwiki.org/mailman/listinfo/devs
Reply | Threaded
Open this post in threaded view
|

Re: How to invalidate security cache?

abtv
Great thanks!