I'm trying to create users in WebLogic (10.3.4) programmatically from a simple standalone Java client (one class --> two methods: createWeblogicUser() & main()).
public void createWeblogicUser() {
try {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "weblogic");
env.put(Context.PROVIDER_URL, "t3://myserver:7001");
InitialContext ctx = new InitialContext(env);
MBeanServer wls = (MBeanServer) ctx.lookup("java:comp/env/jmx/runtime");
ObjectName userEditor = null;
ObjectName mBeanTypeService = new ObjectName( "com.bea:Name=MBeanTypeService, Type=weblogic.management.mbeanservers.MBeanTypeService");
ObjectName rs = new ObjectName("com.bea:Name=RuntimeService, Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
ObjectName domainMBean = (ObjectName) wls.getAttribute(rs, "DomainConfiguration");
ObjectName securityConfig = (ObjectName) wls.getAttribute(domainMBean, "SecurityConfiguration");
ObjectName defaultRealm = (ObjectName) wls.getAttribute(securityConfig, "DefaultRealm");
ObjectName[] authProviders = (ObjectName[]) wls.getAttribute(defaultRealm, "AuthenticationProviders");
for(ObjectName providerName : authProviders) {
if(userEditor == null) {
ModelMBeanInfo info = (ModelMBeanInfo) wls.getMBeanInfo(providerName);
String className = (String) info.getMBeanDescriptor().getFieldValue("interfaceClassName");
if(className != null) {
String[] mba = (String[]) wls.invoke(mBeanTypeService
, "getSubtypes"
, new Object[] {"weblogic.management.security.authentication.UserEditorMBean"}
, new String[] {"java.lang.String"}
);
for(String mb : mba) {
if(className.equals(mb))
userEditor = providerName;
}
}
}
if(userEditor == null)
throw new RuntimeException("Could not retrieve user editor");
try {
wls.invoke(userEditor
, "createUser"
, new Object[] {"wls_user", "password123","User created programmatically."}
, new String[] {"java.lang.String", "java.lang.String","java.lang.String"}
);
}
catch(Exception e){
e.printStackTrace();
}
ctx.close();
}
}
catch(Exception ex) {
ex.printStackTrace();
}
}
Any ideas on what the context lookup I should be making? "java:comp" throws a javax.naming.NameNotFoundException; looks like I can use that only from w/in a container.
Got it to work.
private void createWeblogicUser(String username) {
try {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "weblogic");
String hostname = "myserver";
int port = 7001;
String protocol = "rmi";
String url= new String("/jndi/iiop://myserver:7001/weblogic.management.mbeanservers.domainruntime");
JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port, url);
JMXConnector connector = JMXConnectorFactory.connect(serviceURL, env);
MBeanServerConnection connection = connector.getMBeanServerConnection();
ObjectName userEditor = null;
ObjectName mBeanTypeService = new ObjectName( "com.bea:Name=MBeanTypeService,Type=weblogic.management.mbeanservers.MBeanTypeService");
ObjectName rs = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
ObjectName domainMBean = (ObjectName) connection.getAttribute(rs, "DomainConfiguration");
ObjectName securityConfig = (ObjectName) connection.getAttribute(domainMBean, "SecurityConfiguration");
ObjectName defaultRealm = (ObjectName) connection.getAttribute(securityConfig, "DefaultRealm");
ObjectName[] authProviders = (ObjectName[]) connection.getAttribute(defaultRealm, "AuthenticationProviders");
for(ObjectName providerName : authProviders) {
System.out.println("Auth provider is: " + providerName) ;
if(userEditor == null) {
ModelMBeanInfo info = (ModelMBeanInfo) connection.getMBeanInfo(providerName);
String className = (String) info.getMBeanDescriptor().getFieldValue("interfaceClassName");
System.out.println("className is: " + className) ;
if(className != null) {
String[] mba = (String[]) connection.invoke(mBeanTypeService
, "getSubtypes"
, new Object[] {"weblogic.management.security.authentication.UserEditorMBean"}
, new String[] {"java.lang.String"}
);
for(String mb : mba) {
System.out.println("Model Bean is: " + mb) ;
if(className.equals(mb)) {
System.out.println("Found a macth for the model bean and class name!") ;
userEditor = providerName;
}
}
}
}
}
if(userEditor == null)
throw new RuntimeException("Could not retrieve user editor");
try {
connection.invoke(userEditor
, "createUser"
, new Object[] {username, "password123","User created programmatically."}
, new String[] {"java.lang.String", "java.lang.String","java.lang.String"}
);
System.out.println("User created successfully") ;
}
catch(Exception e){
e.printStackTrace();
}
connector.close();
}
catch(Exception ex) {
ex.printStacktrace();
}
}
You need only weblogic.jar and wljmxclient.jar in classpath. I ran this against JDK 1.6.0_29. I have to add that I ran this on a machine on which WebLogic was installed as well. So the classpath entries were fully qualified path names to the jar files.
One "gotcha" I came across:
While providing the "com.bea:Name=XXXX,Type=XXXX", DONOT give a space between anything - not the colon; not the comma; nothing - I spent sometime debugging this, before it finally hit it.
Related
I have developed java code using pl/sql for weblogic user creation.
The code is:
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "NewUserCreation31" AS
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBeanInfo;
import java.util.Locale;
import java.util.Hashtable;
import javax.naming.Context;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
public class NewUserCreation31
{
private static ObjectName defaultAuthenticator;
private static String authenticatorName="DefaultAuthenticator";
public static String username=null;
public static String password=null;
public static String user_role=null;
public static String retVal="exception";
public static String createWeblogicUser()
{
try {
Hashtable<String, String> env = new Hashtable<String, String>();
// Connection conn = null;
String url1 = "jdbc:oracle:thin:#191.169.151.13:1521:SER140";
String driver = "oracle.jdbc.driver.OracleDriver";
String userNm = "user1";
String psword = "password1";
Statement stmt=null;
String query=" select user_id,enc_dec.decrypt(passwd) pwd,user_priv from user_data";
try
{
retVal= "return 1";
username="uname1";
password="pwd123";
user_role="A";
retVal= "return all";
String user_grp =
(user_role.equals("A")) ? "A" :
(user_role.equals("P")) ? "P" :
(user_role.equals("PA")) ? "PA" :
(user_role.equals("R")) ? "R" :
(user_role.equals("RA")) ? "RA" :
(user_role.equals("RP")) ? "RP" : (user_role.equals("RPA")) ? "RPA" : "U";
retVal= "return user_role";
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "weblogic123");
retVal= "return env";
String hostname ="192.168.161.17";
retVal= hostname;
int port = Integer.parseInt("8001");
retVal= "port";
String protocol = "rmi";
retVal= protocol;
String url = new String("/jndi/weblogic.management.mbeanservers.runtime");
retVal= url;
JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port, url);
retVal= serviceURL.toString();
JMXConnector connector = JMXConnectorFactory.connect(serviceURL, env);
retVal="connector";
MBeanServerConnection connection = connector.getMBeanServerConnection();
retVal="MBeanServerConnection";
ObjectName userEditor = null;
ObjectName mBeanTypeService =
new ObjectName("com.bea:Name=MBeanTypeService,Type=weblogic.management.mbeanservers.MBeanTypeService");
retVal="mBeanTypeService";
ObjectName rs1 =
new ObjectName("com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
retVal="rs1";
ObjectName domainMBean = (ObjectName) connection.getAttribute(rs1, "DomainConfiguration");
retVal="domainMBean";
ObjectName securityConfig = (ObjectName) connection.getAttribute(domainMBean, "SecurityConfiguration");
retVal="securityConfig";
ObjectName defaultRealm = (ObjectName) connection.getAttribute(securityConfig, "DefaultRealm");
retVal="defaultRealm";
ObjectName[] authProviders =
(ObjectName[]) connection.getAttribute(defaultRealm, "AuthenticationProviders");
retVal="authProviders";
for (ObjectName providerName : authProviders) {
if (userEditor == null) {
ModelMBeanInfo info = (ModelMBeanInfo) connection.getMBeanInfo(providerName);
String className = (String) info.getMBeanDescriptor().getFieldValue("interfaceClassName");
System.out.println("className is: " + className);
if (className != null) {
String[] mba = (String[]) connection.invoke(mBeanTypeService, "getSubtypes", new Object[] {
"weblogic.management.security.authentication.UserEditorMBean" }, new String[] {
"java.lang.String" });
for (String mb : mba) {
System.out.println("Model Bean is: " + mb);
if (className.equals(mb)) {
System.out.println("Found a match for the model bean and class name!");
userEditor = providerName;
}
}
}
}
}
if (userEditor == null)
throw new RuntimeException("Could not retrieve user editor");
try {
for (int i = 0; i < authProviders.length; i++) {
String name =
(String)connection.getAttribute(authProviders[i],
"Name");
System.out.println("name " + name);
if (name.equals(authenticatorName))
defaultAuthenticator = authProviders[i];
}
boolean userExists =
((Boolean)connection.invoke(defaultAuthenticator, "userExists",
new Object[] { username },
new String[] { "java.lang.String" })).booleanValue();
System.out.println("userExists" + userExists);
if(userExists)
{
return "User Already exists";
}
else if(!(userExists))
{
connection.invoke(userEditor, "createUser", new Object[] {
username, password, "User created by LPM admin." }, new String[] {
"java.lang.String", "java.lang.String", "java.lang.String"
});
connection.invoke(userEditor, "addMemberToGroup", new Object[] { user_grp, username }, new String[] {
"java.lang.String", "java.lang.String"
});
connection.invoke(userEditor, "addMemberToGroup", new Object[] { "Administrators", username }, new String[] {
"java.lang.String", "java.lang.String"
});
System.out.println("User created successfully");
}
connector.close();
}
catch (Exception ex) {
ex.printStackTrace();
return "Error";
}
// }
// conn.close();
System.out.println("Disconnected from database");
}
catch (Exception e)
{
e.printStackTrace();
}
}
catch(Exception e3)
{
e3.printStackTrace();
return "Error";
}
return retVal;
}
};
/
Here I will get exception at line
JMXConnectorFactory.connect() as Unsupported protocol : rmi.
If I will change the protocol to t3, then It will through
Unsupported protocol : t3
I have ran the code through java directly. It is working. But whenever I will try to call it through pl/sql I will get the mentioned exception.
Please suggest me on this. Is there any other way to create a weblogic users.
I need to create weblogic users from one of the table resided in my database : user_data.
Is it possible to create weblogic users through PL/SQL?. Can I make my java class to be invoked from weblogic server on some interval? Please suggest on this.
Using LDAPContext class I search for a specific user and try to get whether it exists. But search() method returns an empty response.
private int checkUserOnLDAP() {
String strLDAPServer = "ldap://ldap.forumsys.com:389";
String strLDAPPricipal = "cn=read-only-admin,dc=example,dc=com";
String strPassword = "password";
String strSearchBase = "ou=mathematicians,dc=example,dc=com";
String strUserToSearch = "riemann";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, strLDAPServer);
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, strLDAPPricipal);
environment.put(Context.SECURITY_CREDENTIALS, strPassword);
LdapContext ctxGC = null;
try {
ctxGC = new InitialLdapContext(environment, null);
ctxGC.getAttributes("");
} catch (NamingException e) {
System.err.print("SEARCHER BLOCKED USER");
e.printStackTrace();
} catch (Exception e) {
System.err.print("SEARCHER WRONG PASSWORD");
e.printStackTrace();
}
System.out.println("SEARCHER LOGIN SUCCESSFUL");
System.out.println("NOW TRYING TO SEARCH");
try {
String searchFilter = "(&(objectClass=user)(sAMAccountName=" + strUserToSearch + "))";
String returnedAtts[] = new String[0];
SearchControls searchCtls = new SearchControls();
searchCtls.setReturningAttributes(returnedAtts);
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<?> answer = ctxGC.search(strSearchBase, searchFilter, searchCtls);
if (answer.hasMoreElements()) {
Object a = answer.nextElement();
System.out.println("SUCCESFULLY, FOUND USER");
return 0;
} else {
System.out.println("ANSWER HAS NO ELEMENTS");
}
} catch (Exception e) {
System.out.println("SEARCH FAILED");
e.printStackTrace();
}
return 0;
}
While testing, I use an online ldap service: http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
Considering this online test service how can I check whether user exists?
Your search filter uses the sAMAccountName attribute, but that attribute is not available in the test server. Use uid instead.
My goal is recursive getting all group members from domain and subdomains using only connection to main dc.
I have Active Directory forest containing domain.com, sub.domain.com.
My 'MainGroup' located in domain.com and contains members/groups from domain.com and sub.domain.com.
I'm getting 'member' field strings of MainGroup using ldapContext connection with dc.domain.com. Here is it:
cn=userA,ou=Users,dc=domain,dc=com
cn=userB,ou=Users,dc=sub,dc=domain,dc=com
cn=groupB,ou=Users,dc=sub,dc=domain,dc=com
Can I get subdomain's user/group data (I need ObjectClass to recursive iterate) using current ldapConext?
private LdapContext createLdapContext() {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapHost);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "user#" + domain);
env.put(Context.SECURITY_CREDENTIALS, "******");
try {
ldapContext = new InitialLdapContext(env, null);
} catch (NamingException e) {
e.printStackTrace();
}
return ldapContext;
}
public List getGroupMembers(String groupName) {
List resultList = new ArrayList<String>();
int Start = 0;
int Finish = 1499;
int Step = 1500;
boolean Finished = false;
String Range;
try {
while (!Finished) {
Range = Start + "-" + Finish;
String[] returningAttrs = {"member;range=" + Range};
String searchFilter = "(&(objectClass=group)(sAMAccountName=" + groupName + "))";
SearchControls searchControls = new SearchControls();
searchControls.setReturningAttributes(returningAttrs);
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration answer = ldapContext.search(searchBase, searchFilter, searchControls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
for (NamingEnumeration ae = attrs.getAll(); ae.hasMoreElements(); ) {
Attribute attr = (Attribute) ae.next();
if (attr.getID().endsWith("*")) {
Finished = true;
}
for (NamingEnumeration e = attr.getAll(); e.hasMoreElements(); ) {
resultList.add(e.next().toString());
}
}
}
}
Start = Start + Step;
Finish = Finish + Step;
}
ldapContext.close();
} catch (NamingException e) {
e.printStackTrace();
} finally {
return resultList;
}
}
Edited. Found another solution:
Anyway we should query every domain.
We can make 'recursive one shoot query' using filter (memberof:1.2.840.113556.1.4.1941:=cn=Group1,OU=groupsOU,DC=x)
Related c# question
msdn Search Filter Syntax
I am using JNDI to connect to the LDAP active directory, and I want to search for users where the name contains the search string, so my search method is as follows:
public static List<LDAPUser> searchContactsByName(
ExtendedDirContext extendedDirContext, String name) {
try {
LdapContext ldapContext = extendedDirContext.getLdapContext();
String searchBaseStr = extendedDirContext.getSearchBase();
String sortKey = LDAPAttributes.NAME;
ldapContext.setRequestControls(new Control[] { new SortControl(
sortKey, Control.CRITICAL) });
SearchControls searchCtls = new SearchControls();
searchCtls.setTimeLimit(1000 * 10);
String returnedAtts[] = { LDAPAttributes.USER_NAME,
LDAPAttributes.NAME };
searchCtls.setReturningAttributes(returnedAtts);
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "(&(ObjectCategory=person)(cn=*" + name
+ "*))";
NamingEnumeration<SearchResult> results = ldapContext.search(
searchBaseStr, searchFilter, searchCtls);
List<LDAPUser> users = new ArrayList<LDAPUser>(0);
while (results.hasMoreElements()) {
SearchResult sr = (SearchResult) results.next();
Attributes attrs = sr.getAttributes();
LDAPUser user = new LDAPUser();
user.setName(attrs.get(LDAPAttributes.NAME).toString()
.replace("cn: ", ""));
user.setUserName(attrs.get(LDAPAttributes.USER_NAME).toString()
.replace("sAMAccountName: ", ""));
users.add(user);
}
return users;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
and here is how I am making the connection to LDAP:
public static ExtendedDirContext connectToLdap(MessageSource messageSource) {
try {
log.debug("connectToLdap");
String providerUrl = messageSource.getMessage("provider.url", null,
null);
String securityPrincipal = messageSource.getMessage(
"security.principal", null, null);
String securityCredentials = messageSource.getMessage(
"security.credentials", null, null);
String searchBase = messageSource.getMessage("search.base", null,
null);
boolean ssl = Boolean.parseBoolean(messageSource.getMessage("ssl",
null, null));
LdapContext ldapContext;
Hashtable<String, String> ldapEnv = new Hashtable<String, String>(
11);
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
ldapEnv.put(Context.PROVIDER_URL, providerUrl);
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
ldapEnv.put(Context.SECURITY_PRINCIPAL, securityPrincipal);
ldapEnv.put(Context.SECURITY_CREDENTIALS, securityCredentials);
if (ssl)
ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
// To get rid of the PartialResultException when using Active
// Directory
ldapEnv.put(Context.REFERRAL, "follow");
ldapContext = new InitialLdapContext(ldapEnv, null);
ExtendedDirContext extendedDirContext = new ExtendedDirContext();
extendedDirContext.setLdapContext(ldapContext);
extendedDirContext.setSearchBase(searchBase);
log.debug("success connection to ldap");
return extendedDirContext;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
The LDAP credentials are as follows:
provider.url=ldap://dc.fabrikam.com:389
security.principal=CN=administrator,CN=Users,DC=fabrikam,DC=com
security.credentials=password
search.base=dc=fabrikam,dc=com
Why does the search take so much time to retrieve the data? Is there any change that I can do to make the search faster, since I have only 285 contacts in the AD?
Solution was to change ldapEnv.put(Context.REFERRAL, "follow"); to ldapEnv.put(Context.REFERRAL, "ignore");
Your filter:
"(&(ObjectCategory=person)(cn=*" + name + "*))"
May be an issue.
I would recommend that you download a known LDAP utility (Apache Directory Studio Browser as an example) and try different search filters until you find one that works.
To Start, try
"(&(ObjectCategory=person)(cn= + name ))"
You're right,
ldapEnv.put(Context.REFERRAL, "ignore")
didn't get exception about connection timed out. But when I first try I get a partialexception. After I changed my LDAP configuration port from 389 to 3268 I didn't get any exception, build successfully. 3268 port about global catalog of LDAP. For example Outlook clients query the global catalog to locate Address Book information. You can try global catalog if you get an exception referral type setting.
I want to create a JMX client, which can work with my server. I can connect to my server with jconsole, but how can I do it with java code.
This is my server code:
MBeanServer mbeanServer = ManagementFactory
.getPlatformMBeanServer();
//giving name for service
ObjectName objectName = new ObjectName("bean:name=logService");
RequiredModelMBean mbean = new RequiredModelMBean();
mbean.setManagedResource(logService, "objectReference");
Descriptor logStringDescriptor = new DescriptorSupport(
new String[] { "name=logString",
"descriptorType=attribute",
"getMethod=getLogString", "setMethod=setLogString" });
ModelMBeanAttributeInfo logStringAttribute = new ModelMBeanAttributeInfo(
"logString", "java.lang.String", "String to be logged",
true, true, false, logStringDescriptor);
ModelMBeanOperationInfo getLogStringOperation = new ModelMBeanOperationInfo(
"Get the log string",
LoggerService.class.getMethod("getLogString"));
ModelMBeanOperationInfo setLogStringOperation = new ModelMBeanOperationInfo(
"Set the log string", LoggerService.class.getMethod(
"setLogString", String.class));
ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport(
"LoggerService", "Logger Service",
new ModelMBeanAttributeInfo[] { logStringAttribute }, null,
new ModelMBeanOperationInfo[] { getLogStringOperation,
setLogStringOperation }, null);
mbean.setModelMBeanInfo(mbeanInfo);
mbeanServer.registerMBean(mbean, objectName);
It is very simple :)
MBeanServer mbeanServer = ManagementFactory
.getPlatformMBeanServer();
//giving name for service
ObjectName objectName = new ObjectName("bean:name=logService");
String str = (String) mbeanServer.getAttribute (objectName, "logString");
System.out.println(str);
You have to create a JMX agent which will be a wrapper of your MBeans server and allow connecting to your application by external processes with the usage of special adapter. This adapter will allow your clients to connect to MBean server using certain protocol (SNMP, HTTP etc.) or technology (RMI). You can read about adapters here: http://marxsoftware.blogspot.com/2008/08/remote-jmx-connectors-and-adapters.html
public static <T> T createJmxClient(Class<T> clazz, String objectName, String serviceUrl) {
return createJmxClient(clazz, objectName, serviceUrl, null, null);
}
public static <T> T createJmxClient(Class<T> clazz, String objectName, String serviceUrl, final String user, final String pass) {
try {
JMXServiceURL jmxServiceUrl = new JMXServiceURL(serviceUrl);
Map<String, ?> env = user == null ? null : new HashMap<String, Object>() {{
put(JMXConnector.CREDENTIALS, new String[] {user, pass});
}};
JMXConnector jmxc = JMXConnectorFactory.connect(jmxServiceUrl, env);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName mbeanName = new ObjectName(objectName);
return JMX.newMBeanProxy(mbsc, mbeanName, clazz, true);
} catch (IOException | MalformedObjectNameException e) {
throw new RuntimeException("Can not create client for remote JMX " + serviceUrl, e);
}
}