Tuesday, April 9, 2013

Modifying the "supported" attributes of embedded ldap users/groups

WLS Admin console provides limited access to modify the attributes of users and groups that are located in its embedded ldap. This is primarily because embedded ldap is not supposed to hold any application users/groups on a large scale and probably this is one of the reasons why WLS does not provide any dedicated GUI to to modify the user/group attributes inside embedded ldlap. Neverthless, we can store these users/groups and we can modify the attributes as well. There are two approaches:

1) Using an external LDAP browser utility. My favorite as of today is jxplorer . I use such a utility against WLS embedded ldap for various purposes - testing the connectivity, the bind operation, search queries, etc

Using such ldap browser utilities against WLS embedded ldap requires one to explicitly open embedded ldap for "outside WLS" access.This involves resetting the password of embedded ldap's super user "Admin" to a known value. Note that when WLS domain is created, the password for this user is set randomly.



Restart the Administration server for changes to take effect.

Next, we use jxplorer to access the embedded ldap externally:



Once a successful connection is made, open of the user/group of choice and just do it:


2. Using a piece of JMX code

package examples.wls.jmx;

import javax.management.Descriptor;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.MBeanException;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.remote.JMXConnector;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;


//supportedUserAttributes = { "displayname", "employeenumber", "employeetype", "givenname", "homephone", "mail", "title", "preferredlanguage", "departmentnumber", "facsimiletelephonenumber", "mobile", "pager", "telephonenumber", "postaladdress", "street", "l", "st", "postofficebox", "c", "homepostaladdress" }

public class UserUtil {
 
 public static void main(String args[]) throws Exception{
  (new UserUtil()).doWork();
 }
 
 public void doWork() throws Exception{
  JMXConnector jmxConnector = getJMXConnector("192.169.0.100","17001","weblogic","weblogic1");
  MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
  //createNewUser(mBeanServerConnection, "weblogic.security.providers.authentication.DefaultAuthenticatorMBean", "JavaUser","weblogic1","Created from JAVA via JMX");
  modifyUserAttribute(mBeanServerConnection, "weblogic.security.providers.authentication.DefaultAuthenticatorMBean", "JavaUser", "mail", "javauser@examples.com");
  jmxConnector.close();
 }
 
 private void modifyUserAttribute(MBeanServerConnection mBeanServerConnection, String atnClassName, String userName, String userAttributeName, String userAttributeNewValue) throws Exception {
  ObjectName atnProvider = getATNProvider(mBeanServerConnection, atnClassName);
  ObjectName MBTservice = new ObjectName("com.bea:Name=MBeanTypeService,Type=weblogic.management.mbeanservers.MBeanTypeService");  
  
  //check whether the atnProvider implements UserAttributeEditorMBean, otherwise we cannot modify the attributes for the user in this provider
  String[] mba =  (String[]) mBeanServerConnection.invoke( MBTservice,
       "getSubtypes", new Object[] {
       "weblogic.management.security.authentication.UserAttributeEditorMBean" }, 
       new String[] { "java.lang.String" });
  boolean isEditor = false;
  for (int i = 0; i < mba.length; i++) {
   if (mba[i].equals(atnClassName)){
    isEditor = true;
    break;
   }   
  }
  if (isEditor == false)
   throw new Exception("*** The Provider does not support attribute modification");
  else
    System.out.println("*** This provider supports user attribute modification");  
  
  String userAttributeOldValue = null;
  String userAttributeNewlySetValue = null;
  
  
  //check what value we already got for the attribute
  userAttributeOldValue = (String) mBeanServerConnection.invoke( atnProvider,
    "getUserAttributeValue", new Object[] {userName, userAttributeName}, new String[] {"java.lang.String", "java.lang.String"});
  System.out.println("*** userAttributeOldValue>>" + userAttributeOldValue);
  
  //set new value
  System.out.println("*** Attempting to modify user attribute>>"+userAttributeName + ", with new value as>>" +userAttributeNewValue);
  mBeanServerConnection.invoke( atnProvider,
    "setUserAttributeValue", new Object[] {userName, userAttributeName, userAttributeNewValue}, new String[] {"java.lang.String", "java.lang.String", "java.lang.Object"});
  
  //get newly set value
  userAttributeNewlySetValue = (String) mBeanServerConnection.invoke( atnProvider,
    "getUserAttributeValue", new Object[] {userName, userAttributeName}, new String[] {"java.lang.String", "java.lang.String"});
  
  if(userAttributeNewValue.equals(userAttributeNewlySetValue))
   System.out.println("*** value succesfully set to>>" + userAttributeNewlySetValue);
 }

 public JMXConnector getJMXConnector(String hostname, String portString, String username, String password) throws IOException, MalformedURLException {
  JMXConnector jmxConnector = null;
  String protocol = "t3";
  Integer portInteger = Integer.valueOf(portString);
  int port = portInteger.intValue();
  String jndiroot = "/jndi/";
  String mserver = "weblogic.management.mbeanservers.domainruntime";
  JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname,port, jndiroot + mserver);
  Hashtable h = new Hashtable();
  h.put(Context.SECURITY_PRINCIPAL, username);
  h.put(Context.SECURITY_CREDENTIALS, password);
  h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,"weblogic.management.remote");
  jmxConnector =  JMXConnectorFactory.connect(serviceURL, h);  
  System.out.println("*** Created JMXConnector instance and now returing from getJMXConnector");
  return jmxConnector;
 }
 
 
 public void createNewUser(MBeanServerConnection mBeanServerConnection, String atnClassName, String userName, String userPass, String userDescription) throws  Exception {
  ObjectName atnProvider = getATNProvider(mBeanServerConnection, atnClassName);
  ObjectName MBTservice = new ObjectName("com.bea:Name=MBeanTypeService,Type=weblogic.management.mbeanservers.MBeanTypeService");  
  
  //check whether the atnProvider implements UserEditorMBean, otherwise we cannot create the user for this provider
  String[] mba =  (String[]) mBeanServerConnection.invoke( MBTservice,
       "getSubtypes", new Object[] {
       "weblogic.management.security.authentication.UserEditorMBean" }, 
       new String[] { "java.lang.String" });
  boolean isEditor = false;
  for (int i = 0; i < mba.length; i++) {
   if (mba[i].equals(atnClassName)){
    isEditor = true;
    break;
   }   
  }
  if (isEditor == false)
   throw new Exception("*** The Provider does not support user creation");
  else
    System.out.println("*** This provider supports user creation");
  
  
  try {
   System.out.println("*** Attempting to create user");
   mBeanServerConnection.invoke(atnProvider, "createUser", new Object[] {userName, userPass, userDescription},
    new String[] {"java.lang.String", "java.lang.String", "java.lang.String"}
   );
     System.out.println("*** User created");
  }catch (MBeanException ex) {
   Exception e = ex.getTargetException();
   e.printStackTrace();
  }
  
  try {
   System.out.println("*** Attempting to add user to group"); 
   mBeanServerConnection.invoke(
     atnProvider, "addMemberToGroup",
    new Object[] {"Administrators", userName},
    new String [] {"java.lang.String", "java.lang.String"}
     );
   System.out.println("*** Added user to group"); 
  }catch (MBeanException ex) {
   Exception e = ex.getTargetException();
   e.printStackTrace();
  }
 }
 
 private ObjectName getATNProvider(MBeanServerConnection mBeanServerConnection, String atnClassName) throws Exception{
  ObjectName[] atnProviders = getAllATNProviders(mBeanServerConnection);
     System.out.println("*** Going to traverse through auth providers");
  for (int p = 0; atnProviders != null && p < atnProviders.length; p++) {
      System.out.println("*** Provider number>>"  +p);
   ModelMBeanInfo info = (ModelMBeanInfo) mBeanServerConnection.getMBeanInfo(atnProviders[p]);
   Descriptor desc = info.getMBeanDescriptor();
   String className = (String)desc.getFieldValue("interfaceClassName");
   if(atnClassName.equals(className)){
    System.out.println("*** Requested provider found, and will return. atnProvider>>"+atnProviders[p]);
    return atnProviders[p];
   }
   }
  System.out.println("*** Requested provider not found, and will return null");
  return null;
 }
 
 private ObjectName[] getAllATNProviders(MBeanServerConnection mBeanServerConnection) throws Exception{
  ObjectName service = new ObjectName("com.bea:Name=DomainRuntimeService,"+ "Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
  ObjectName domainMBean = (ObjectName) mBeanServerConnection.getAttribute(service, "DomainConfiguration");
  ObjectName securityConfiguration = (ObjectName) mBeanServerConnection.getAttribute(domainMBean, "SecurityConfiguration");
  ObjectName defaultRealm = (ObjectName) mBeanServerConnection.getAttribute(securityConfiguration, "DefaultRealm");
  return (ObjectName[]) mBeanServerConnection.getAttribute(defaultRealm, "AuthenticationProviders");
 }
 
}



You can also grab the source code of this sample JAVA class from here


!!!

1 comment:

  1. Nice! I was looking for group assignment which I found in this, thanks for posting.

    ReplyDelete