Thursday, October 6, 2011

Giving non-admin users the permission to access MBeans

Sometimes it might be a requirement that a JEE application, deployed on WebLogic, needs an access to MBeans (Server, domain  or custom MBeans). With WebLogic default administrator user and other users who belong to default administrator group “Administrators” such a thing is possible quite easily. However it is not a good practice as the admin credentials would unnecessarily get exposed to application (and it may in-turn have security consequences).

So, the question comes up - can we avoid using these admin credentials and instead use appropriate credentials, in our application, based on role access?

The answer is yes - this requirement involves working with JMX policies. WebLogic provides a way for creating new as well as modifying existing (default) JMX policies. So what you can do is use the JMX policy editor to grant non-admin user/group a write access to the required MBean. JMX policy editor is described here.

Also refer this to enable the JMX policy editor if it is not already enabled for your domain

Above solution is applicable to MBeans that are part of WebLogic “Server” and “Domain” MBean trees. What about the custom MBeans that are not visible/accessible via JMX Policy Editor in the Administration console, but only programmatically using JMX, or using WLST (=WebLogic Scripting Tool)?  Typically if you try to perform any operations on such MBeans (through JMX or WLST) with non-admin user, you would see following type of error:

Error occurred while performing set : Error setting attribute NewUserCount : Access not allowed for subject: principals=[testuser], on Resource CustomMBeanType Operation: set , Target: NewUserCount

We run into this error for custom MBeans because the custom MBeans are not straightway accessible to non-admin users for access when WebLogic domain is running in production mode.
Now I will proceed to discuss one solution for this issue. This solution uses WebLogic auditing provider (to identify what WebLogic level permissions are missing in access attempt) and WLST (to create a policy). However, first  I would advise you to go through following URL to understand more about the application that I am using as an example here. This link has an excellent example discussing how to develop custom MBean:  

Once you have this application ready (or one of your own), here is what you do:

1. Deploy the application

2. We need to figure out what permission policy we need to create to make non-admin accounts access the resource successfully. For this, create Weblogic auditing provider ( more details here ). While configuring this provider, you would need to select severity level “FAILURE”(By mistake I had put this as "SUCCESS" while creating this post for the first time)

3. Now using WLST, perform an MBean operation that is supposed to fail. Like:

wls:/TestDomain3/custom/blog.wls.jmx.appmbean/blog.wls.jmx.appmbean:Type=CustomMBeanType,name=myAppStats> set('NewUserCount',10)
Traceback (innermost last):
File "<console>", line 1, in ?
File "<iostream>", line 581, in set
File "<iostream>", line 1848, in raiseWLSTException
WLSTException: Error occured while performing set : Error setting attribute NewUserCount : Access not allowed for subject: principals=[testuser], on Resource CustomMBeanType Operation: set , Target: NewUserCount
Use dumpStack() to view the full stacktrace

This will populate entries in auditing log (<DOMAIN_HOME>/servers/<ADMIN_SERVER>/log/DefaultAuditRecorder.log). Review this file. It should have entries that failed. Like in our case:

#### Audit Record Begin <Aug 2, 2011 8:26:58 PM> <Severity =FAILURE> <<<Event Type = Authorization Audit Event V2 ><Subject: 1
Principal = class"testuser")
><ONCE><<jmx>><type=<jmx>, operation=set, application=, mbeanType=CustomMBeanType, target=NewUserCount>>> Audit Record End ####

Now, this entry has some important piece of information in it, and that is “resourceid”. “resourceid” is a string that uniquely identifies a resource in WebLogic. In our example, MBean operation “set” is a  resource and WebLogic identifies it using “resourceid”:
type=<jmx>, operation=set, application=, mbeanType=CustomMBeanType, target=NewUserCount
Make a note of this resource id.

4. Using WLST, connect to domain runtime mbean on AdminServer, and cd to 'SecurityConfiguration/TestDomain3/Realms/myrealm/Authorizers/XACMLAuthorizer'

wls:/offline> connect()
Please enter your username :weblogic
Please enter your password :
Please enter your server URL [t3://localhost:7001] :
Connecting to t3://localhost:7001 with userid weblogic ...
Successfully connected to Admin Server 'AdminServer' that belongs to domain 'TestDomain3'.

Warning: An insecure protocol was used to connect to the
server. To ensure on-the-wire security, the SSL port or
Admin port should be used instead.

wls:/TestDomain3/serverConfig> domainConfig()
Location changed to serverRuntime tree. This is a read-only tree with DomainMBean as the root.
For more help, use help(domainConfig)

wls:/TestDomain3/domainConfig> cd('SecurityConfiguration/TestDomain3/Realms/myrealm/Authorizers/XACMLAuthorizer')

Note that “TestDomain3” is the name of WebLogic domain where the application is deployed.

5. Create the policy for non-admin user's access using WLST command:
createPolicy(String resourceId,String expression)

“resourceid”   is the id of your application. We got this by enabling auditing as already discussed (further details on auditing provider can be found here )

“expression”  is the policy expression granting/denying access.

For instance, if we want to grant access to non-admin user “testuser” so that he can execute “set” operation of  the custom MBean, then I will execute following WLST command:
cmo.createPolicy('type=<jmx>, operation=set, application=, mbeanType=CustomMBeanType, target=NewUserCount','{Usr(testuser)}')

Now, verify that policy is created:
cmo.getPolicy('type=<jmx>, operation=set, application=, mbeanType=CustomMBeanType, target=NewUserCount')

6. Same steps can be repeated for other MBean operations, and we are done!

a) Quoting an extract from documentation, if you create an MBean that contains a single attribute named NewUserCount and an operation named clearNewUserCount, and if you register the MBean under the object name blog.wls.jmx.appmbean:Type=CustomMBeanType,name=myAppStats, then the security service creates the following resource IDs:

type=<jmx>, operation=get, application=, mbeanType=CustomMBeanType, target=NewUserCount

type=<jmx>, operation=set, application=, mbeanType=CustomMBeanType, target=NewUserCount

type=<jmx>, operation=clearNewUserCount, application=,mbeanType=CustomMBeanType,target=

So, you need to create the access policies accordingly, of-course with audit log as reference.

Using XACML Documents to Secure WebLogic Resources(Prerequisites, Adding a XACML Role or Policy to a Realm: Main Steps, Creating Roles and Polices for Custom MBeans)

Registering Custom MBeans in the WebLogic Server Runtime MBean Server

1 comment:

  1. Hello.

    I tried to follow these steps, but I still get the same security access error.

    After create the policy using wlst com.createPolicy() I can get it with cmo.getPolicy. But whey I export my security provider data via console the XACML.dat files is empty.

    I'am a bit confused with this kind of Policy to secure custom MBeans. The DOC [1] show how you can create XACML Document to load your policies for Role and Auth XACML providers. But I think deal with XACML doc is too hard. How did you do to create the XACML Role Mapper? You didn't mention about Role policy here.

    Is the XACML provider the only way to create security policies for Custom MBean registered in runtime?