Wednesday, April 21, 2010

User Lockout & WLST

WebLogic server provides an option to lockout users to protect accounts from password guessing attack. It is implemented with a realm-wide Lockout Manager. This feature can be used with custom authentication provider also. But if you implement your own authentication provider and wish to implement your own lockout manager that is possible too.

If your domain is configured to use the user lockout manager the following WLST script will help you to:
- check whether a user is locked using a WLST script
- find out the number of locked users in the realm


#Define constants
url='t3://localhost:7001'
username='weblogic'
password='weblogic'
checkuser='test-deployer'

#Connect
connect(username,password,url)

#Get Lockout Manager Runtime
serverRuntime()
dr = cmo.getServerSecurityRuntime().getDefaultRealmRuntime()
ulmr = dr.getUserLockoutManagerRuntime()

print '-------------------------------------------'
#Check whether a user is locked
if (ulmr.isLockedOut(checkuser) == 0):
islocked = 'NOT locked'
else:
islocked = 'locked'
print 'User ' + checkuser + ' is ' + islocked

#Print number of locked users
print 'No. of locked user -> ', Integer(ulmr.getUserLockoutTotalCount())

print '-------------------------------------------'
print ''

#Disconnect & Exit
disconnect()
exit()

Friday, February 26, 2010

WLDF Browser

WebLogic Diagnostic Framework (WLDF) is a comprehensive framework for diagnosing isuees related to servers, applications, services in WebLogic Server. Image capturing is a component of WLDF which can be used to get a snapshot of all the key information from a server. The WLDF Image gets generated as a zip file with an "img" file for information from each sub-system. For more information regarding WLDF Image capturing refer to the WLS documentation here.

Currently there are no official tools available to view the image or to compare 2 or more images. The attached tool WLDF Browser can help you to view the diagnostic image.

HTTP Session Monitoring in WebLogic Server

Monitoring HTTP sessions on WebLogic Server is a common task when you have web component (WAR) deployed as a part of your enterprise application (EAR). By default WebLogic Server provides a way to access the number of active HTTP sessions for each web application. But if you need more information about the individual sessions like their creation time, last accessed time, maximum inactive interval etc. then you have to enable the session monitoring option in the web component's Deployment Descriptor (DD). If the application is already packaged and deployed you can make use of the deployment plan to enable this attribute. WebLogic Administration Console provide options to modify some of the attribute for the components and application through the interface. Eventually a deployment plan will be generated if there are no deployment plan associated with the application or the existing plan will be modified automatically by Administration Console. This will ease administrators job of enabling session monitoring for a packaged application. You may have to update or redeploy the application with the plan for the monitoring to take effect. No restarting of any server is required for this change.

Administration Console will automatically populate the Session tab under the Monitoring tab with the individual session information for the specific application. By default the following column are displayed on the console page:

  • Context Root
  • Server
  • Creation Time
  • Time Last Accessed
  • Max Inactive Interval

You can also add the following columns to the table by customizing the view:

  • Monitoring ID
  • Application
  • Machine

The Monitoring ID provides a unique ID by default to identify the session. You can also customize the Monitoring ID by specifying a session attribute name which is unique for identifying the session for users. For example you can configure customer_id or user_id or order_id as Monitoring ID for tracking session. I shall talk about Monitoring IDs and finding session size in a different post. Internally WebLogic will concatenate the Monitoring ID with the creation time to make a unique name for each session. The following is an example screen shot of monitoring sessions after customizing the view:



WLST can also be able to retrieve these information from the ServletSessionRuntimeMBeans. The following is an example WLST script to connect to the Administration Server of a domain to retrieve session information for a specific application on a particular server.I had used the deprecated ServletSessionRuntimeMBeans in my WLST example as the session creation time is only available through that runtime mbean. You can also access all the information about the session except the creation time through the WebAppComponentRuntimeMBean. But you will have to use the Monitoring IDs (available through WebAppComponentRuntimeMBean) to get information about a specific session.


from java.util import Calendar

def defineVariables()
#Define all the variables used
username='system'
password='weblogic'
adminurl='t3://localhost:7001'
servername='AdminServer'
appname='CompanyStore'

def connectToAdminServer()
#Connect to Admin Server
connect(username,password,adminurl)

def extractAndPrintSessionInfo(servletSessionRuntime)
#Get session name
session_name=ssession.getName().split('!')[0]
#Creation time is concatinated to the session name. So split it
ct_millis=ssession.getName().split('!')[1]
cal = Calendar.getInstance()
cal.setTimeInMillis(Long(ct_millis))
ct = cal.getTime()
#Get last accessed time
tla_millis=ssession.getTimeLastAccessed()
cal.setTimeInMillis(Long(tla_millis))
tla = cal.getTime()
print ' '
print 'Session Name - ' + session_name
print 'Creation Time - ', ct
print 'Last Accessed Time - ', tla

#Main
defineVariables()
connectToAdminServer()

#Get Runtime for our server
domainRuntime()
cd('/ServerRuntimes/'+servername)

#Get all running applications
apps=cmo.getApplicationRuntimes()
for app in apps:

#We are intersted only on this application
if app.getName() == appname:

print 'Application Name - ', app.getName()

#Get all components in that application
comps=app.getComponentRuntimes()
for comp in comps:

#We are interested in only web components
if comp.getType() == 'WebAppComponentRuntime':
comp_name = comp.getName().split(servername+'_/')
if len(comp_name) == 1:
display_comp_name = '(default web app)'
else:
display_comp_name = comp_name
print 'Component Context Root - ', display_comp_name

#Get all active sessions
sessions=comp.getServletSessions()
print 'Total no. of sessions - ', len(sessions)

#Loop through all the available sessions
for ssession in sessions:
extractAndPrintSessionInfo(session)

#Disconnect and exit
disconnect()
exit()



The output from the above script will look something like this:


[test@mywlssvr-orcl ~]$ java weblogic.WLST sessions.py

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

Connecting to t3://localhost:7001 with userid system ...
Successfully connected to Admin Server 'AdminServer' that belongs to domain 'dizzyworld'.

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.

Location changed to domainRuntime tree. This is a read-only tree with DomainMBean as the root.
For more help, use help(domainRuntime)

Application Name - CompanyStore
Component Context Root - (default web app)
Total no. of sessions - 2

Session Name - dYvLLHgRGxQ8zS0ZYySLZKx1j2KK9Ws2G22nlJXvrQRFv64zsPTm
Creation Time - Fri Feb 26 01:13:21 UTC 2010
Last Accessed Time - Fri Feb 26 01:13:26 UTC 2010

Session Name - nGbTLHgFLnfNjwGT1cpHGQhJZGZynBYRsp2TjC8kC7KFRK1vCCf3
Creation Time - Fri Feb 26 01:13:41 UTC 2010
Last Accessed Time - Fri Feb 26 01:13:45 UTC 2010
Disconnected from weblogic server: AdminServer


Exiting WebLogic Scripting Tool.

Saturday, January 23, 2010

Node Manager as a UNIX Startup Process

Configuring WebLogic Server (WLS) as a startup process was a common administrative process in the past. But after Node Manager (NM) was introduced as an agent to start, stop, restart and monitor WebLogic Server it is now recommended that you start WebLogic Server using NM. But NM has to configured as a startup process on the respective OS so that it is always running to manage the respective WLS instances on that machine. NM can either be Java based NM or Script based NM. Script based NM uses OS services like SSH or RSH to execute the NM script. But Java based NM is a Java process that should be started. So setting up NM as a service will ensure that NM is always running. There is a lot of information in the WebLogic Server documentation about setting up NM. But there is very less or no information about setting NM as a service on a non-Windows environment. For Windows environment there are pre-packged scripts that you can use. These scripts exists under WL_HOME/server/bin folder (installNodeMgrSvc.cmd, uninstallNodeMgrSvc.cmd). But for UNIX based environment you should do this manually or with the help of OS specific utilities like chkconfig etc.

For *nix environment NM should be configured as startup process using rc scripts. Creating rc scripts for configuring NM as a service is even simpler than configuring WebLogic Server as a service. This is mainly because NM doesn't have to be shutdown gracefully. All you have to do is write a simple shell script that starts the NM and create the symbolic link to that script from the right run level folder. The following illustrates the steps to confiure NM as service under LINUX environment. It should be very similar on other *nix environments. You need root permission to peform the following steps.


1. Create a shell script (wlsnmd) under /etc/init.d/ folder:


#! /bin/bash
case "$1" in
start)
WL_HOME = /usr/middleware/11.1.0/wlserver_10.3
$WL_HOME/server/bin/startNodeManager.sh
;;

*)
echo "Usage: $0 {start}"
exit 1
esac

exit_status



2. Assuming that we are going to start NM at run level 5, create a sysmbolic link in /etc/rc.d/rc5.d/ folder. Since it a startup script we should start the symbolic link with "S" and followed by a number which decide the order in which services will be called. As we are fine to start NM after all the other application/services are start let us choose 99 which is the highest number.



ln -s /etc/init.d/wlsnmd S99weblogic



If you don't want to do these manually you can also use utilities like chkconfig (included in Red Hat distributions) for managing your startup scripts. For configuring WebLogic Server as a startup process there are pre-packaged scripts (installSvc.cmd, uninstallSvc.cmd). But you have to create rc scripts similarly for WLS as well in UNIX based environments. Here is an example rc script for configuring a WebLogic Server as a startup process. But here we also need to implement the kill/stop to gracefully shutdown the server.



#! /bin/bash

case "$1" in
start|reload)
DOMAIN_HOME = /usr/middleware/domains/med_analysis
$DOMAIN_HOME/bin/startWebLogic.sh
;;
stop)
$DOMAIN_HOME/bin/stopWebLogic.sh
;;
restart|force-reload)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac

exit_status

Wednesday, November 25, 2009

Understanding WLST built-in variables . . .[WLST scripting Best Practices (Part-5)]

This post is a continuation of my previous post - in a series of posts about WLST scripting best practices.

Managed Beans (MBeans) are used to represent all the configuration and runtime information about WebLogic Domain, Servers, the applications and services deployed on a WebLogic Server Domain. While you can get all the information from WebLogic MBeans, WLST simplifies the task of building scripts by providing some built-in variables. These WLST variables are initialized and/or modified when you change to online mode (connect to a server), start an edit session etc. to appropriate values.

One of the very useful WLST variable is cmo. cmo stands for current management object. When navigating in WLST you can use cmo to reference the current MBean (object) instance you are navigating into. The cmo value is changed when you navigate to different hierarchy of MBeans under different MBean trees in WebLogic (except jndi tree). The following illustrates the use of cmo.



...
connect(username, password, url)
edit()
startEdit()
cd('/Servers/server1')
s1=cmo
cd('/Servers/server2')
s2=cmo
print 'Listenport of server1 -> ' + s1.getListenPort()
print 'Listenport of server2 -> ' + s2.getListenPort()
...


Notice the use of cmo can for invoking operations on the respective MBean object. There are many such variables that will help you to write better and efficient WLST scripts. See here for the list of all the WLST variables.

If you know a variable name you can simply use it in you script. dumpVariables() command can be used to list all the variables and their values.


wls:/testdomain/serverConfig> dumpVariables()
adminHome weblogic.rmi.internal.BasicRemoteRef - hostID: '328889774891021637S:127.0.0.1:[7001,7001,-1,-1,-1,-1,-1]:testdomain:AdminServer',oid: '259', channel: 'null'
cmgr [MBeanServerInvocationHandler]com.bea:Name=ConfigurationManager,Type=weblogic.management.mbeanservers.edit.ConfigurationManagerMBean
cmo [MBeanServerInvocationHandler]com.bea:Name=testdomain,Type=Domain
connected true
domainName testdomain
...



In addition you should also be aware of these WLST variables in order to NOT use them to store your own information. If you do so then WLST will overwrite these variables during your interaction like connect, startEdit etc. So make sure you understand these WLST variables, use them in your scripts and do not use them to store your information.

Monday, November 23, 2009

Force confidentiality for Web Applications

Usually there are requirements for web based applications to use SSL when serving sensitive data between the client browser and WebLogic server. You can enable SSL port for WebLogic Server and disable the plain text port. This will force all the communication through the SSL port enabled on the target server. But if you have a mix of applications that require secured access and that doesn't then you can use the standard JEE web application descriptor to enable confidentiality. If you enable trasport guarantee configuration for the Web Applications, WebLogic Server will force the application or selective URL patternts to be accessed through the SSL port on WebLogic Server.

The following shows an example of transport guaranetee entry from web.xml:


...


CONFIDENTIAL



/*


...


Even if the client is accessing through plain text port, WLS container will automatically redirect the request to the SSL port if enabled or to any other Network Channel enabled with SSL. This will ensure that certain applications or requests to be always accessed through SSL. Setting the transport guarantee to be NONE will relax the requirements and will not force SSL for the applications. But if there are SSL enabled network channels or SSL port is enabled on the server then the application can still be accessed using SSL. If the value for transport guarantee is set to be INTEGRAL then the requirement is that the data sent between the client and server be sent in such a way that it can't be changed in transit.

Needless to say that this configuration can also be configured through deployment plans. If the application you are deploying on WebLogic Server is already packaged for deployment or third-party application then deployment plan will solve the purpose of overriding the application's configuration through external means. See here for more information on deployment plans with WebLogic Server.

Thursday, October 22, 2009

More ways to check the existense of a resource with WLST

In one of my previous post, I discussed a couple of ways with which you can find out whether a particular configuration already exists before you create them. The methods are not just limited to the one on that post. So now I am here to discuss couple more way to do the same check. But just for completeness I shall also include the methods I discussed in my previous post. I am taking a sample use case to check whether a particular WebLogic Server instance exists in the domain or not. But you can extrapolate these technique for any other resource like JDBC Data Source, JMS Server, JMS Queue etc.

Goal - Check whether a server with the name 'mymanagedserver' exists in the domain

Method-1 Using "cd"

A simple approach is to use the "cd" command to navigate into that configuration MBean. If the "cd" command throws an exception then you can safely assume that the resource/configuration doesn't exists and you can continue with your task.


...
mgdServerName = 'mymanagedserver'
### Checking for the server
try:
cd('/Servers/' + mgdServerName)
print '===> Server \"' +mgdServerName+'\" already exists'
print '===> No action was performed'
exit()
except:
pass
### Continue to create the server
...


Method-2 Catch "BeanAlreadyExistsException"

Another approach is to catch the "BeanAlreadyExistsException" when creating the resource and safely exiting the script.


...
mgdServerName = 'mymanagedserver'
### Create the Managed Server
edit()
startEdit()
try:
create(mgdServerName, resourceType)
print '===> Created Managed Server - ' + mgdServerName
pass
except BeanAlreadyExistsException:
print '===> Server \"' +mgdServerName+'\" already exists'
print '===> No action was performed'
cancelEdit('y')
exit()
...


But with this approach you are starting an edit session and creating the server to find out it's existence. So you have to cancel the edit session once you find out that the resource that you are creating already exists if not you might get a warning message similar to the following:

You have an edit session open and you will lose all outstanding changes and your edit session will be stopped if you exit. Are you sure you would like to exit? (y/n)

So canceling the edit session with a response 'y' will make WLST not to prompt for the user response.


Method-3
Using "getMBean"

There is a WLST command called getMBean which will return the MBean object when you specify the appropriate path. If the instance is not found then it will return None. But getMBean command does not throw an exception when an instance is not found. So you have explicitly check result of the getMBean.


...
mgdServerName = 'mymanagedserver'
ref = getMBean('/Servers/' + mgdServerName)
if(ref != None):
print 'Server ' + servername + 'already exists'
disconnect()
exit()
else:
pass
### Continue to create the server
...


Method-4 Using "ls"

You can simply navigate to the resource type and execute ls. This will return the list of all the instances as a string when you assign the output to a variable. Then you can use the find method on that string variable to check whether your server exists. The find method returns a "0" on success or "-1" on failure.


...
mgdServerName = 'mymanagedserver'
cd('/Servers')
servers = ls()
if (servers.find(servername) != -1):
print 'Server ' + servername + ' already exists'
disconnect()
exit()
else:
pass
### Continue to create the server
...