Friday, April 17, 2009

Securing a Coherence Cache

Coherence is a data source and the question is if we can secure it so that only authorized users/applications can access it. A sample custom named cache based solution is already available Here. Based on this example I have streamlined and simplified it's integration a little so that cache configuration is simpler and scope of security provider is taken out of Coherence. The entire project is available at Securing a Coherence Cache. [Part II is at http://ezsaid.blogspot.com/2009/10/integrating-ldap-with-coherence.html]

Following are some simplifications:

  1. Add a new XML Element (<entitled>) to enable a cache scheme for security. The configuration will look like the following:
    <distributed-scheme>
    <scheme-name>distributed-scheme</scheme-name>
    <service-name>DistributedCache</service-name>
    <backing-map-scheme>
    <local-scheme></local-scheme>
    </backing-map-scheme>
    <autostart>true</autostart>
    <entitled>
    <security-provider>MySecurityProvider</security-provider>
    </entitled>

    </distributed-scheme>
  2. A new ConfigurableCacheFactory. It's setConfig looks like:
        public void setConfig(XmlElement xmlConfig) {
    // -- Find all the caches for which entitled is set to true
    // -- Fild all cache names that has the scheme for which
    // -- entitled tag is defined
    // -- Replace the scheme name to a class-scheme with Entitled
    // -- cache
    // -- Find all the cache schemes with entitled set to true
    Map map = findEntitledSchemes(xmlConfig);
    XmlElement csM =
    xmlConfig.findElement("caching-scheme-mapping");
    Iterator cMs = csM.getElements("cache-mapping");
    XmlElement cM = null;
    while (cMs.hasNext()) {
    cM = (XmlElement) cMs.next();
    String schemeName =
    cM.findElement("scheme-name").getString();
    if (map.containsKey(schemeName)) {
    cM.findElement("scheme-name").setString("entitled-scheme");
    XmlElement iPs = cM.addElement("init-params");
    XmlElement iP = iPs.addElement("init-param");
    iP.addElement("param-name").setString("security-provider");
    iP.addElement("param-value").setString(map.get(schemeName));
    }
    }

    XmlElement rCS =
    XmlHelper.findElement(xmlConfig, "//caching-schemes");
    XmlElement cS = rCS.addElement("class-scheme");
    cS.addElement("scheme-name").setString("entitled-scheme");
    cS.addElement("class-name").setString(
    EntitledNamedCache.class.getName());
    XmlElement iPs = cS.addElement("init-params");

    XmlElement iP = iPs.addElement("init-param");
    iP.addElement("param-type").setString("string");
    iP.addElement("param-value").setString("{cache-name}");

    XmlElement iP2 = iPs.addElement("init-param");
    iP2.addElement("param-type").setString("string");
    String cache_config =
    System.getProperty("tangosol.coherence.cacheconfig");
    if (cache_config == null) {
    cache_config = FILE_CFG_CACHE;
    }
    iP2.addElement("param-value").setString(cache_config);

    XmlElement iP3 = iPs.addElement("init-param");
    iP3.addElement("param-type").setString("string");
    iP3.addElement("param-value").setString("{security-provider}");

    super.setConfig(xmlConfig);
    }
  3. A new interface to implement. Implement SecurityProvider interface and configure it as a security-provider in the cache configuration.
    public interface SecurityProvider {
    public boolean checkAccess (Subject subject);
    }
And thats all you need. Download the complete code from Securing a Coherence Cache. Enjoy!

15 comments:

Vichars said...

http://www.thesavvyguideto.com/gridblog/2009/04/securing-a-coherence-cache/

SMKurup said...

Hi Ashish,
I'm a bit confused with the implementation side. Does securityprovider mean that when i access my cache by the name EntitledCache it will access the class MySecurityProvider?

SMKurup said...

Hi Ashish,
I'm a bit confused with the implementation side. Does securityprovider mean that when i access my cache by the name EntitledCache it will access the class MySecurityProvider?

ashish said...

This pattern protects proxy servers from unauthorized access. One of the challenges in implementing security is to provide a pluggable component that provides a certain implementation of how you would like to secure the cache. security-provider in the cache-scheme allows you to customize it. EntitledNamedCache is a custom NamedCache implementation that gets deployed when a tag is present in a cache scheme. You will remain unaware of this runtime change in the cache configuration. If a secured cache is accessed, the request is trapped by the EntitledNamedCache which then calls the security provider that you have configured to authorize the access. All classes defined in security-provider has to implement SecurityProvider interface. Your security implementation could be as simple as validating the subject with some locally managed credentials or as complex as you want. You may be interested in looking at Integrating LDAP for more practical implementation.

SMKurup said...

Thanks Ashish for the explanation. I went thru the LDAP link too. However, the code that i dwnloded for Securing a Coherence Cache is not performing any runtime cache configuration. Thats why the DisAllowSecurityProvider & AlloSecurityProvider classes are not being accessed. Is this understanding correct? Could you please provdie the main java class which invokes EntitledNamedCache & the setConfig() method ? Shud the XML Element () be placed inside the proxy and the client cache configs ?

ashish said...

Hi SMKurup,
The code protects the proxy service and the codebase that you downloaded is meant for *Extend protection. The runtime change only happens on the node with proxy service and will only happen when you run it with proxy-override.xml. Its the ExtendedCacheFactory that manipulates the configuration. The Entitler.zip is a very scaled down implementation but it provides some insight on how you could do it.

pooja said...

hi ashish..
i have very big doubt... can u give me your contact number please so tat i can clarify my doubts....

ashish said...

Hi Pooja,
You can send me an email at ashish.srivastava@oracle.com. Please include the customer name, your Oracle's Account manager and a little bit about the project you are working on. Will try to help you in the best way possible

-Ashish

Aravinda said...

Hi Asish,
First of all thank u for posting nice article about coherence security. I hope we can't check the functionality of security using the standalone application. I am using the weblogic server,in my application i am accessing the cache.I have implemented coherence security using u r code in my application, but still my application is not invoking the AllowSecurityProvider or DisAllowSecurityProvider class it's still using Default Security provider available in coherence. jar. I have added all the configuration files in my class path. Plz let me know do i need to change any configuration file in coherence.jar as well to make this work.

Thanks & Regards,
Aravind

ashish said...

Hi Aravind,
As there are some custom XML elements in the cache configuration, it requires a custom tangosol-override file too. Please check if you have that in the classpath too and if it is getting loaded. Looks like it is not reading the correct override.

-Ashish

Aravind said...

Hi Ashish,

Thank you for your quick reply. Yup there was a configuration file names mismatch what i am setting in the class path and coherence.jar, i corrected the file names on the class path.Now it is working as expected. Thank you.

Regards,
Aravind

Aravind said...

Hi Asish,

I implemented coherenc security in my weblogic EAR application, my ear contains one utlity.jar this jar contains all my security related code. When i deployed this ear in weblogic and tried accessing cache application was throwing classnotfound exception EntitlerCacheFactory. But all these classes for bundled with my utility jar. When i added utility jar as part of class path it is working fine. Is it like all the CoherenceSecurity related class should be made available to the class path?

Waiting for your reply, thanks in advance.

Regards,
Aravind

ashish said...

Depends which classloader is loading the classes and whats its visibility to your application. EARs when deployed are run in its own context classloader.

Aravind said...

Hi Asish,

I have implemented coherence Access control in MDB application, to access coherence cache reference in my application i need to pass subject with proper subject Name, if not i will get exception. This is fine at MDB application level.

I have one stand alone utility in which i will try to access the same cache reference with out passing any subject. Here it is not throwing any exception. Is the scope of the access control implementation is with in my MDB application. Is it not applicable to OutSide of my MDB application? If it is not applicable to outside of my application then there is no point in implementing security, please clarify me.

Thanks & Regards,
Aravind

ashish said...

Hi Aravind,
With the information provided so far I can't say for sure why you are seeing such a behavior outside MDBs. I did not use MDBs and its all have been standalone apps that I test with. One thing to keep in mind is the solution as published is more targeted towards *Extend clients and for cluster members you may need a little bit of more work. For production grade solution there is much more to this API than whats in the blog. I need to better understand your environment before be able to definitely pin point the problem. If this task is on a critical path of your project then I would also recommend to get some help from Oracle consulting and they can reach me directly to help you better.

-Ashish