How to access and change WLS user and roles – access denied

 

By W.ZH Apr 2010

I am not talking about manage user and role from WLS EM UI. I am going to introduce how to access these from the JAVA code.

Oracle has a set of API called OPSS http://www.oracle.com/technology/products/id_mgmt/opss/index.html All oracle product (maybe not include those purchased 🙂 use the OPSS to realize the security control. Based on the OPSS API, you can access the WLS embeded or linked LDAP user and roles storage and security policy configured for WLS. Please read the OPSS dev guide to compose your code. You can do many things about the user, roles, application policies by this API.

After you make your code ready and deploy to the WLS, such as you deploy a set of EJB, which will do some user and roles or policy changes to the WLS embeded LDAP or WLS security policy file. You will find your code sometimes always get the access denied error, as your code does not right permission to do some operations.

Here is the way to go!

1. From the domain EM, we need to the change the permission for your codebase, to let your code can have access right to do something.

  • In the EM (not domain console), go to Farm_base_domain –> Weblogic Domain –>your_domain.
  • Under your domain, right panel click drop down of the WebLogic? Domain–> Security–>System Policies.
  • Search for “codebase” permissions. You will find all codebase permission defines here, you need to add one more item here to let your codebase can have right permission.
  • Create a new codebase permission:
    • set Codebase to “file:${domain.home}/servers/${weblogic.Name}/tmp/_WL_user/YOUR_EJB_APP/-“
    • Add a permission to your codebase:
    • Permission Class: refer to dev guide.
    • Resource name: refer to dev guide.
    • Permission Actions: refer to dev guide. – give as least as it can.

2. In your code, you need to wrap your code to the Previldge scope to let the java security check bypass your code. Something like this :

        AccessController.doPrivileged(new PrivilegedAction<String>() {
                public String run() {
                    your_method();
                    return "ok";
                }
            });

About the how to use the AccessController.doPrivileged, can refer to JDK AccessController. You can also let it return object and throw exception.

3. How to verify your policy is there?

Go to your domain’s config/fmwconfig/system-jazn-data.xml, you will find that a new items of grant is added for your codebase.

4. You might need to restart the WLS to see your code can access or not now.

 

====== for this note i cut and paste part of the chapter from oracle dev guide about this exception =================================================

 

I.13 Security Access Control Exception

This section explains a reason why your code may run into a security access control exception.

Symptom

At run time, your application outputs an error like the following one (only the first few lines are shown):

<Jan 20, 2009 5:45:33 PM PST> <Error> <HTTP> <BEA-101020>
<[weblogic.servlet.internal.WebAppServletContext140cf52
- appName: 'Application2',
name: 'Application2.war',
context-path: '/Application2',
spec-version: '2.5']
Servlet failed with Exceptionjava.lang.RuntimeException:java.security.AccessControlException:access denied
...

Diagnosis

The above error means that a call in your code does not have sufficient permissions to execute a secured operation.

Solution

Your code must be granted the appropriate permissions to execute the secured operation. Depending on the scope of the permission you would like to set, you have two alternatives.

The first one is to grant permission to all application code in the application’s EAR or WAR files; in this case, the call to the secured operation can be inserted anywhere in the application code.

The second one is to grant permission to just a JAR file; in this case, the call to the secured operation must be inside a privileged block.

Each of these solutions is next illustrated by an application attempting to access the credential store.

The following fragment of an applicationjazn-data.xml illustrates how to set permission to read any key within the map MY_MAP in the credential store to any code within the directory BasicAuth:

<jazn-policy>
   <grant>
       <grantee>
           <codesource>
              <url>file:${domain.home}/servers/_WL_user/BasicAuth/-</url>
           </codesource>
       </grantee>
       <permissions>
           <permission>
             <class>
                 oracle.security.jps.service.credstore.CredentialAccessPermission
             </class>
             <name>context=SYSTEM,mapName=MY_MAP,keyName=*</name>
             <actions>read</actions>
          </permission>
      </permissions>
   </grant>
</jazn-policy>

If the permission is to be granted to the code in a particular EAR or WAR file, the url specification above would have to be changed to one like the following:

<url>file:${domain.home}/servers/_WL_user/jpsBasicAuth/.../BasicAuth.ear</url>

In both above cases, the call to read the credential store can be placed anywhere in the application code.

If, however, the permission is to be granted to just the code in a particular JAR file, the url specification above would have to be changed to one like the following:

<url>file:${domain.home}/servers/_WL_user/jpsBasicAuth/myJars/Foo.jar</url>

In this last case, the code in the file Foo.jar that calls a read operation on the credential store must be placed in an AccessController.doPrivileged block, as illustrated in the following code snippet:

import oracle.security.jps.*;
import oracle.security.jps.service.credstore.*;

JpsContextFactory factory = JpsContextFactory.getContextFactory();
JpsContext jpsContext = factory.getContext();
final CredentialStore store = jpsContext.getServiceInstance(CredentialStore.class);
Credential cred = AccessController.doPrivileged(new PrivilegedExceptionAction<PasswordCredential>() {
    public PasswordCredential run() throws JpsException {
        return store.getCredential("MY_MAP", "anyKey");
    }
});

PasswordCredential pwdCred = (PasswordCredential)cred;
...

Note that since our sample grant above allows only read permission, none of the set or reset operations work, even inside a privileged block.

 

Advertisements