Advertisements
RSS

Tag Archives: WLST

How to implement permissions on your activities with Oracle Adaptive Case Management ?

When our Oracle Adaptive Case Management project started we initially used the default permissions on the case (Public, Restricted) to make sure our activities where available to the correct BPM application roles. A complex authorization model of roles, with LDAP groups, with users to allow access to the activities, but also custom UI and human tasks.

default_acm_permissions

An important concept of knowledge worker automation (on which off course our whole case is based) is that the users should not be locked into rigid BPM processes (and access constraints I would like to add) which the IT department came up with. So activities on one hand would be allowed access to by all internal knowledge workers anyway, because: “hey .. they are knowledge workers and know best, right ?”

The first exception

However for some exceptions we got the requirements to only allow a specific role to a specific activity. So what we did was adding a new permission for that role and made sure that the activity was only available for that role.

Screen Shot 2016-07-29 at 11.08.18

new permission for role Senior Employee

Screen Shot 2016-07-29 at 11.08.35

set the permission on the activity

And all was good, for a while …

Challenge accepted

This went pretty well for some time, until we ran into a new requirements which made us rethink our design:

  • We had the requirement that on a specific activity where currently only permRoleSeniorEmployee had access now, we had to add the role Medior Employee. Therefor the original design thought that all activities are available for all employees OR for just 1 specific role (senior) for quality assurance was no longer valid.

So we looked at our options :

  1. We allowed the application role Medior to the permRoleSenior permission for a quick win for now, but looking at our naming convention this would be a bit confusing in the long run. All other options below required a code change, build and deploy so we tried to be smart to prevent this from ever happening again.
  2. The activity sadly doesn’t have a multi-select (both 11g and 12.2.1) so it is not possible to select both permRoleSenior and permRoleMedior
  3. We could add a new permission like permRoleMediorAndSenior, but still limiting ourselves to the code base
  4. In future identical requirements we do not want to change the codebase of our ACM project and permissions should be able to change on runtime. So both option 2 and 3 are not smart in the long run.

Our “Best Practice”

We have long running cases (like, really long) and redeployment of a new version will not fix any new permissions requirements on running instances. However since we have 50+ activities in our case where most of them are (currently) allowed access to by all employee levels (the example here just uses 2, but in reality we have much more roles). So the idea of creating a separate permission for each activity was not appealing, we eventually decided that we just had to. So for each activity we created a unique permission and configured in on the activity.

Screen Shot 2016-07-29 at 11.41.15

new unique permission for the activity

Screen Shot 2016-07-29 at 11.41.20

set the permission on the activity

 

Scripted Configuration

Because know we have a LOT of permissions and roles we are gratefull for having a WLST script to make sure these are automatically configured through our environments. Scripts have some customization, but the main logic was found on the big WWW (sorry, not sure where and who to give credits).

So first we need a property file


permission.total=2

# permActMyProcess2
permission.1.appstripe=OracleBPMProcessRolesApp
permission.1.principalclass=oracle.security.jps.service.policystore.ApplicationRole
permission.1.principalname=RubixCasus_1.0.MediorEmployee
permission.1.permclass=oracle.bpm.casemgmt.permission.CasePermission
permission.1.permtarget=RubixCasus_1.0.PERMACTMYPROCESS2.ACTIVITY
permission.1.permactions=INVOKE
permission.2.appstripe=OracleBPMProcessRolesApp
permission.2.principalclass=oracle.security.jps.service.policystore.ApplicationRole
permission.2.principalname=RubixCasus_1.0.SeniorEmployee
permission.2.permclass=oracle.bpm.casemgmt.permission.CasePermission
permission.2.permtarget=RubixCasus_1.0.PERMACTMYPROCESS2.ACTIVITY
permission.2.permactions=INVOKE

And the WLST script


from java.util import Properties
from java.io import FileInputStream
from java.io import File
from oracle.security.jps.mas.mgmt.jmx.policy import PortablePrincipal
from oracle.security.jps.mas.mgmt.jmx.policy import PortablePermission
from oracle.security.jps.mas.mgmt.jmx.policy.PortablePrincipal import PrincipalType
import os, sys

PROPERTIES = sys.argv[1]

propInputStream = FileInputStream(PROPERTIES)
configProps = Properties()
configProps.load(propInputStream)
propInputStream.close()
pmTotal=configProps.get("permission.total")
print '... property permission.total:',pmTotal

connect('weblogic', 'welcome1', 't3://myserver:7001')

print '============================='
print 'Granting permissions...'
print '============================='
print '... property permission.total:',pmTotal
i=1
while (i <= int(pmTotal)) :

  pmAppStripe=configProps.get("permission."+str(i)+".appstripe")
  pmPrincipalClass=configProps.get("permission."+str(i)+".principalclass")
  pmPrincipalName=configProps.get("permission."+str(i)+".principalname")
  pmPermClass=configProps.get("permission."+str(i)+".permclass")
  pmPermTarget=configProps.get("permission."+str(i)+".permtarget")
  pmPermActions=configProps.get("permission."+str(i)+".permactions")

  domainRuntime()
  jpsBean = ObjectName('com.oracle.jps:type=JpsApplicationPolicyStore')

  print 'INFO - Index:',str(i),'| Name:',pmPrincipalName,'| Target:',pmPermTarget,' |Action:',pmPermActions

  principal = PortablePrincipal(pmPrincipalClass, pmPrincipalName,PrincipalType.CUSTOM)
  params = [pmAppStripe, principal.toCompositeData(None)]
  sign = ["java.lang.String", "javax.management.openmbean.CompositeData"]
  perms = mbs.invoke(jpsBean, "getPermissions", params, sign)

  permExists = false
  for perm in perms:
    p = PortablePermission.from(perm)
    if(p.target==pmPermTarget and p.permissionClassName==pmPermClass and pmPermActions in p.actions):
      permExists = true
      print 'INFO - Permission',pmPermTarget,'(',pmPermActions,') already set for ',pmPrincipalName
      break

    if(permExists==false):
    try:
      grantPermission(appStripe=''+pmAppStripe,principalClass=''+pmPrincipalClass,principalName=''+pmPrincipalName, permClass=''+pmPermClass, permTarget=''+pmPermTarget,permActions=''+pmPermActions)
      print 'INFO - Permission',pmPermTarget,'(',pmPermActions,') set for ',pmPrincipalName
    except:
      print 'ERROR - Failed adding permission ',pmPermTarget,'(',pmPermActions,') to',pmPrincipalName
      dumpStack()
      print sys.exc_info()
      os._exit(1)

  i = i + 1

Conclusion

The longer we thought about this the more we think the current permission solution lacks some maintainability. It would (for instance) be nice if the BPM WorkSpace would allow some graphical interface where all activities could be easily connected to the (already their) BPM Application Roles. So hopefully in the near future ?

Advertisements
 
Leave a comment

Posted by on 29-07-2016 in BPM, Oracle

 

Tags: , , , , ,

How to Configure WebLogic Server to Send a Notification When Its Configuration is Changed

My former collegue, Java maven (no not that one, this one) and friend Pierluigi contacted me about my post regarding the Weblogic Security Audit Provider. As always Pier is very political correct ;)

Comment

To my positive surprise he found a great solution for the limitation of the security audit provider. He discovered a way to configure WebLogic server to send a notification when it’s configuration is changed [Knowledge Base ID 1377733.1].

Which is awesome if you have a large Oracle environment and maintenance team and want to keep track of all the changes. Wish we knew this last year at the huge envuironment I was working then.

His blogpost contains all the code, scripts, etc so go and check it out!!! :)

And to end with his favourite quote:

Failure is not an option

References:

 
Leave a comment

Posted by on 21-02-2013 in Java, Oracle, Weblogic, WLST

 

Tags: , , , ,

Why is there no Weblogic WLST Node Manager nmShutdown command ?

The great thing about the Weblogic Nodemanager is that you can control your Weblogic Admin and Managed servers through Weblogic Scripting Tool (WLST) without the AdminServer being online. Simply said, with a few basic WLST commands you can perform important administrative tasks to your Weblogic domain and don’t need a running AdminServer(!).

For instance, starting a server:


nmConnect('weblogic', 'welcome1', 'myserver3', '5555', 'rbx_dev_domain', 'd:/oracle/projects/domains/rbx_dev_domain')
nmStart('rbx_dev_soa_ms01')
nmDisconnect()

The problem arises when you want to gracefully shutdown a server through the Node Manager. As shown here there is no nmStop/nmShutdown or nmSuspend command, only a very blunt knife called nmKill. I tried nmKill to experiment with it, and concluded that it does exactly what it claims. However applications (and administrators) might not like this forcefully termination.

So how can we stop a Managed Server through WLST then ? The answer is simple, we need to connect with WLST to the running AdminServer and execute our commands in online mode:


# connect to the Admin running on server01, port 7001
wls:/offline> connect("weblogic","welkome1","t3://server01:7001")

# shutdown MS01, ignoreSessions=false, timeout=300sec, force=false, block=false
wls:/rbx_dev_domain/serverConfig> shutdown('rbx_dev_soa_ms01','Server','false',300000,'false','false')

wls:/rbx_dev_domain/serverConfig> disconnect()

The online (meaning you need to connect to a running Admin) WLST life cycle commands are all there: shutdown, start, suspend, resume and even migrate. Creating a powerful toolset to WLST script against your Weblogic domain.

Conclusion:

I personally think this is a limitation of the Weblogic Node Manager. The power of the NodeManager should be exactly what it name claims to be, managing a certain ‘node’. And I think that both starting and stopping should be a very basic requirement.

In this case I think it fails, since you can not perform this administrative tasks to your domain without connecting to a running AdminServer. Which is a shame if you don’t want/need your AdminServers to be running constantly. Yes you can script around it, using the nmStart() command to start the AdminServer if not running, then nmDisconnect() and connect() to the now running AdminServer but it’s a lot of effort if you could simply succeed with a nmShutdown.

Links:

 
3 Comments

Posted by on 13-12-2011 in Weblogic, WLST

 

Tags: , ,

Creating Weblogic JMS components with WLST

The previous post explained the different Weblogic JMS components. As promised I would share some WLST scripts which I use to create the different JMS components as an example.

The example set of scripts exist of 3 files:

  • a generic import.properties file which hold the connection settings
  • JMSCreateInfra.jy which configures the JMS persistent stores, servers, modules and CF
  • JMSCreateQueue.jy which creates a queue and configures redirect
The very basic import.properties
##################################################################
# Weblogic connection parameters                                 #
##################################################################
adminUrl=t3://localhost:7001
importUser=weblogic
importPassword=weblogic1

And the WLST script to configure the Persistent Store, JMS Server, JMS Module and CF on your environment. The script is based upon a Weblogic domain containing a Weblogic cluster with 2 Managed Servers. If you want to use these scripts make sure to change the:

– path for persistent store
– cluster name (rbx_dev_wls_cluster)
– managed server name (rbx_dev_wls_0*)
– persistent store name (FileStore_wls0*)
– jms server name (JmsServer_wls0*)
– jms module name (JmsModuleRubix)
– CF name (ConnFactoryGenericRubix*)
– queue names (SR01.getMyData.*)
– sub deployment name (RBX.myDivision)

Execute the script:  java weblogic.WLST scriptname.jy import.properties

#================================
from java.io import FileInputStream
import sys

#================================
# Generic definitions
#================================

def loadProps(configPropFile):
propInputStream = FileInputStream(configPropFile)
configProps = Properties()
configProps.load(propInputStream)
return configProps

#==========================================================================
# Load properties and connect to Weblogic server
#==========================================================================

importConfigFile = sys.argv[1]
exportConfigProp = loadProps(importConfigFile)
adminUrl = exportConfigProp.get("adminUrl")
importUser = exportConfigProp.get("importUser")
importPassword = exportConfigProp.get("importPassword")

#===============================
# Start the script
#===============================

connect(importUser, importPassword, adminUrl)
edit()
startEdit()

#================================
# Build JMS Filestores
# Filestores store the messages
#================================

cd('/')
cmo.createFileStore('FileStore_wls01')
cd('/FileStores/FileStore_wls01')
cmo.setDirectory('D:/oracle/projects/domains/rbx_dev_domain/filestores')
set('Targets', jarray.array([ObjectName('com.bea:Name=rbx_dev_wls_01,Type=Server')], ObjectName))
cd('/')
cmo.createFileStore('FileStore_wls02')
cd('/FileStores/FileStore_wls02')
cmo.setDirectory('D:/oracle/projects/domains/rbx_dev_domain/filestores')
set('Targets', jarray.array([ObjectName('com.bea:Name=rbx_dev_wls_02,Type=Server')], ObjectName))

#================================
# Build JMS Server(s)
# For every MS in cluster define a JMSserver and target a single MS server
#================================

cd('/')
cmo.createJMSServer('JmsServer_wls01')
cd('/Deployments/JmsServer_wls01')
cmo.setPersistentStore(getMBean('/FileStores/FileStore_wls01'))
set('Targets', jarray.array([ObjectName('com.bea:Name=rbx_dev_wls_01,Type=Server')], ObjectName))

## Threshold (values are default)
# cmo.setBytesThresholdHigh(-1)
# cmo.setBytesThresholdLow(-1)
# cmo.setMessagesThresholdHigh(-1)
# cmo.setMessagesThresholdLow(-1)
## Quotas (values are default, except MaxMsgSize set to 10MB)
# cmo.setBytesMaximum(-1)
# cmo.setMessagesMaximum(-1)
# cmo.setBlockingSendPolicy('FIFO')
cmo.setMaximumMessageSize(10000000)
cd('/Deployments/JmsServer_wls01/JMSMessageLogFile/JmsServer_wls01')
cmo.setRotationType('byTime')
cmo.setRotateLogOnStartup(false)
cmo.setRotationTime('00:00')
cmo.setFileTimeSpan(24)
cmo.setFileCount(30)
cmo.setNumberOfFilesLimited(true)
cmo.setFileName('D:/oracle/projects/domains/rbx_dev_domain/servers/rbx_dev_wls_01/logs/jmsServers/JmsServer_wls01_messages.log')

cd('/')
cmo.createJMSServer('JmsServer_wls02')
cd('/Deployments/JmsServer_wls02')
cmo.setPersistentStore(getMBean('/FileStores/FileStore_wls02'))
set('Targets', jarray.array([ObjectName('com.bea:Name=rbx_dev_wls_02,Type=Server')], ObjectName))
## Threshold (values are default)
# cmo.setBytesThresholdHigh(-1)
# cmo.setBytesThresholdLow(-1)
# cmo.setMessagesThresholdHigh(-1)
# cmo.setMessagesThresholdLow(-1)
## Quotas (values are default, except MsgMaxSize is 10MB)
# cmo.setBytesMaximum(-1)
# cmo.setMessagesMaximum(-1)
# cmo.setBlockingSendPolicy('FIFO')
cmo.setMaximumMessageSize(10000000)
cd('/Deployments/JmsServer_wls02/JMSMessageLogFile/JmsServer_wls02')
cmo.setRotationType('byTime')
cmo.setRotateLogOnStartup(false)
cmo.setRotationTime('00:00')
cmo.setFileTimeSpan(24)
cmo.setFileCount(30)
cmo.setNumberOfFilesLimited(true)
cmo.setFileName('D:/oracle/projects/domains/rbx_dev_domain/servers/rbx_dev_wls_02/logs/jmsServers/JmsServer_wls02_messages.log')

#================================
# Build JMS Module
# target preferrable cluster, single-server DEV domain use server
#================================

cd('/')
cmo.createJMSSystemResource('JmsModuleRubix')
cd('/SystemResources/JmsModuleRubix')
set('Targets',jarray.array([ObjectName('com.bea:Name=rbx_dev_wls_cluster,Type=Cluster')], ObjectName))

#================================
# Build JMS Connection Factory
#================================

cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix')
cmo.createConnectionFactory('ConnFactoryGenericRubix')
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/ConnectionFactories/ConnFactoryGenericRubix')
cmo.setJNDIName('jms/cf/RubixGeneric')
cmo.setDefaultTargetingEnabled(true)
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/ConnectionFactories/ConnFactoryGenericRubix/SecurityParams/ConnFactoryGenericRubix')
cmo.setAttachJMSXUserId(false)

#================================
# Build JMS Connection Factory XA
#================================

cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix')
cmo.createConnectionFactory('ConnFactoryGenericRubixXA')
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/ConnectionFactories/ConnFactoryGenericRubixXA')
cmo.setJNDIName('jms/cf/RubixGenericXA')
cmo.setDefaultTargetingEnabled(true)
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/ConnectionFactories/ConnFactoryGenericRubixXA/SecurityParams/ConnFactoryGenericRubixXA')
cmo.setAttachJMSXUserId(false)
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/ConnectionFactories/ConnFactoryGenericRubixXA/TransactionParams/ConnFactoryGenericRubixXA')
cmo.setTransactionTimeout(3600)
cmo.setXAConnectionFactoryEnabled(true)

#==========================================================================
# Finalize
#==========================================================================

save()
activate()
disconnect()

#================================
# End
#================================

Create 3 queues, a request, response and a error queue.
Failure is configured to use redirect to the error queue.
A read service (hence the SR naming) mechanism I like to combine for the Oracle Service Bus

Execute the script:  java weblogic.WLST scriptname.jy import.properties


#================================================================
# Build JMS Subdeployment
#================================================================

cd('/SystemResources/JmsModuleRubix')
cmo.createSubDeployment('RBX.myDivision')
cd('/SystemResources/JmsModuleRubix/SubDeployments/RBX.myDivision')
set('Targets',jarray.array([ObjectName('com.bea:Name=rbx_dev_wls_cluster,Type=Cluster')], ObjectName))

#================================================================
# Build Queues: SR01.getMyData
#================================================================

# Error Queue
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix')
cmo.createUniformDistributedQueue('SR01.getMyData.Error')
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/UniformDistributedQueues/SR01.getMyData.Error')
cmo.setJNDIName('jms/queue/SR/getMyData/Error')
cmo.setLoadBalancingPolicy('Round-Robin')
cmo.setSubDeploymentName('RBX.myDivision')

# Request queue
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix')
cmo.createUniformDistributedQueue('SR01.getMyData.Request')
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/UniformDistributedQueues/SR01.getMyData.Request')
cmo.setJNDIName('jms/queue/SR/getMyData/Request')
cmo.setLoadBalancingPolicy('Round-Robin')
cmo.setSubDeploymentName('RBX.myDivision')
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/UniformDistributedQueues/SR01.getMyData.Request/DeliveryFailureParams/SR01.getMyData.Request')
cmo.setRedeliveryLimit(3)
cmo.setExpirationPolicy('Redirect')
cmo.setErrorDestination(getMBean('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/UniformDistributedQueues/SR01.getMyData.Error'))

# Response Queue
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix')
cmo.createUniformDistributedQueue('SR01.getMyData.Response')
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/UniformDistributedQueues/SR01.getMyData.Response')
cmo.setJNDIName('jms/queue/SR/getMyData/Response')
cmo.setLoadBalancingPolicy('Round-Robin')
cmo.setSubDeploymentName('RBX.myDivision')
cd('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/UniformDistributedQueues/SR01.getMyData.Response/DeliveryFailureParams/SR01.getMyData.Response')
cmo.setRedeliveryLimit(3)
cmo.setExpirationPolicy('Redirect')
cmo.setErrorDestination(getMBean('/JMSSystemResources/JmsModuleRubix/JMSResource/JmsModuleRubix/UniformDistributedQueues/SR01.getMyData.Error'))
 
3 Comments

Posted by on 01-12-2011 in Weblogic, WLST

 

Tags: , ,

Setting up the Weblogic Security Audit Provider for your domain

Imagine a huge landscape with multiple Weblogic domains where each domain has multiple administrators, operators and deployers working with the Weblogic console. Wouldn’t it be great if you could audit the changes that where made during each Lock & Edit session. Especially when your business requires this due to strict regulations.

The good news is: You can, but there are some small details you should be aware of.

Auditing with Weblogic logging:

In the Weblogic console click on the domain to the left, and then on the right select the Advanced section in Configuration -> General. One of the settings here is the Configuration Audit Type.

The setting has 4 values, where None is the default:

  • None = Configuration events will neither be written to the server log or directed to the Security Audit Framework.
  • Change Log = Configuration events will be written to the server log.
  • Change Audit = Configuration events will be directed to the Security Audit Framework.
  • Change Log and Audit = Configuration events will be written to the server log and directed to the Security Audit Framework.
The easiest part is to use the Change Log option, the audited changes will be written to the Weblogic server log. The following example is copied from the AdminServer.log. It shows the audit trail of a simple change to the environment where 2 ports are changed for a Managed Server.
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=rbx_dev_osb_01,Type=Server METHOD isSet PARAMS ListenAddress>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=rbx_dev_osb_01,Type=Server METHOD isSet PARAMS ListenPortEnabled>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=rbx_dev_osb_01,Type=Server METHOD isSet PARAMS ListenPort>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159904> <USER weblogic MODIFIED com.bea:Name=rbx_dev_osb_01,Type=Server ATTRIBUTE ListenPort FROM 8010 TO 9010>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=rbx_dev_osb_01,Type=Server METHOD isSet PARAMS JavaCompiler>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=rbx_dev_osb_01,Type=Server METHOD isSet PARAMS ClientCertProxyEnabled>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159904> <USER weblogic MODIFIED com.bea:Name=rbx_dev_osb_01,Type=SSL,Server=rbx_dev_osb_01 ATTRIBUTE Enabled FROM true TO true>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159904> <USER weblogic MODIFIED com.bea:Name=rbx_dev_osb_01,Type=SSL,Server=rbx_dev_osb_01 ATTRIBUTE ListenPort FROM 8011 TO 9011>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=rbx_dev_osb_01,Type=WLDFServerDiagnostic,Server=rbx_dev_osb_01 METHOD isSet PARAMS WLDFDiagnosticVolume>
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=ConfigurationManager,Type=weblogic.management.mbeanservers.edit.ConfigurationManagerMBean METHOD save PARAMS >
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=ConfigurationManager,Type=weblogic.management.mbeanservers.edit.ConfigurationManagerMBean METHOD haveUnactivatedChanges PARAMS >
####<someDate> <Info> <Configuration Audit> <someNode> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <...> <BEA-159907> <USER weblogic INVOKED ON com.bea:Name=ConfigurationManager,Type=weblogic.management.mbeanservers.edit.ConfigurationManagerMBean METHOD haveUnactivatedChanges PARAMS >

As you can see, it’s a lot of logging for such a simple change. The second bad part here is that the Weblogic log files are already cluttered with information, and it might be hard to find such specific information. Another problem might be that the log level is apparently fixed set to INFO. In most production domains I don’t want such a low log level due to log files getting to huge and containing to much non-information. So in general situation the Logger Severity is set to Notice or even Warning (located under each Admin / Managed Server at Logging -> General -> Advanced ).

Auditing with the Weblogic Auditing Provider:

The solution for the cluttered Weblogic server logging is to use the “Change Audit” option. The information will be redirected to the Weblogic Security Audit Provider (if configured) and send to a separate DefaultAuditRecorder.log file.

An auditing provider is collects, stores, and distributes information about operating requests and the outcome of those requests for the purposes of non-repudiation. An Auditing provider can also handle information about configuration changes for auditing purposes. You can configure multiple Auditing providers in a security realm, but none are required. The default security realm does not include an Auditing provider. (source: Weblogic Console)

First we set the Configuration Audit Type option to Change Audit and secondly we will need to configure a Security Audit Provider in the Weblogic Security realm.

You can add the default Audit Provider under Providers -> Auditing.

The Default Auditor is limited in it’s configuration so we can only configure the Log Severity, Log Rotation Level and the Begin and End Markers shown in the log file example below. When we change the configuration from a Managed Server again (the ListenPort) we can find the following lines in the DefaultAuditRecorder.log.

#### Audit Record Begin <someDate>
<Severity =SUCCESS>  <<<Event Type = SetAttribute Configuration Audit Event>
<Subject = Subject: 4
	Principal = class weblogic.security.principal.WLSUserImpl("weblogic")
	Principal = class weblogic.security.principal.WLSGroupImpl("Administrators")
	Principal = class weblogic.security.principal.WLSGroupImpl("IntegrationAdministrators")
	Principal = class weblogic.security.principal.WLSGroupImpl("AdminChannelUsers")>
<Object = com.bea:Name=rbx_dev_osb_01,Type=Server>
<Attribute = ListenPort><From = 6010><To = 7010>>>
Audit Record End ####

As we can see the modification has a SUCCESS severity, so again we don’t leave the default settings for the Security Audit Provider because the DefaultAuditRecorder.log is growing very rapidly. For now my conclusion is that it is more wise to set the Severity option to CUSTOM and use the Error, Success and Failure Audit Severity. Information Audit Severity will fill up your disks very fast.

However, the Default Audit Provider is connected to your security realm. So during startup of your domain many information is send to this file regarding roles, policies and deployments. Again it’s possible to find configuration changes, this time easier then in the general Weblogic log files, but still it might take some time to find specific settings and changes over time. Another detail is that the DefaultAuditRecorder.log is located in the default server log folder. So we might have to guarantee strict access to these files if we need them for legal audit purposes.

WLST Script Recording:

This might sound as a strange alternative, but WLST script recording could help us in some way. Of course WLST (Weblogic Scripting) is very cool for setting up complete new Weblogic environments in seconds. And besides that it’s also very handy for releasing configuration changes to your domains from development all the way to production.

You can of course start hardcore coding your scripts, but another helpful tool is the Record option the Weblogic console has to offer. This feature will record the changes you make in your configuration and save them as a generated Jython script which you can then (if necessary) modify and run on other environments.

If you check the preferences of your Weblogic domain you can find a WLST Script Recording tab


Which has an option called “Automatic Recording”

By enabling this option you actually get what you want, all changes are automatically written to disk in the location configured by the “Base Script Directory” option. However for some weird reason the “Script File Name” option which states that the filename is generated dynamically every time you Lock & Edit, is now a static value. So if you don’t realize this, the file “Script1316….” will be overwritten every time you make changes. To avoid this you could enable the “Append to File” option, but my opinion is that this is just a workaround and you would rather have:

  • A random generated output file name, instead of the static value you create by enabling the “Automatic Recording” option.
  • It would be a nice-to-have to be able to use parameters in the output file, like %date% or %username%.
There is another “problem” if you are the highest Weblogic Administrator in the domain and the business wants a feature for “audit and proof”. The problem is the fact that the setting is not set for the whole domain, as I would have hoped but for every user independantly. So right now we only set this configuration for the user “Weblogic”
For instance, when I log on with a new user called “Test” (which is member of the Operators and Deployers groups) we can see that the settings were not inherited.

The Base Script Directory is configured with the default (the domain home) and the Automatic Recording is disabled. While we do create users with WLST scripts it’s quite easy to configure both these settings correctly. But for audit purposes it has no use if the user itself is able to disable the whole setting.

It would be great to have this feature “improved” in feature Weblogic versions (this was tested with Weblogic 10.3.5). So that the whole Automatic Recording functionality is extended to be more like an internal security audit mechanism as the Weblogic Security Audit Provider.
Conclusion:

It looks like the Security Audit Provider in combination with the Configuration Audit Changes option is still the best solution for auditing a Weblogic domain. During the first period you configure it monitor the outcome to see if you audit to much or to less of details.

WLST Script Recording is very cool, but we can not guarantee to record all changes in the domain. So I would advise to use it, but more for the cases where you are debugging some issues in you domain. At any time you can check what changes you made and if necessary roll them back. So handle it more as a helpful reminder option.
 
4 Comments

Posted by on 26-09-2011 in Weblogic, WLST

 

Tags: , ,

Weblogic Security Realm WLST import and export

>This is just a reminder for myself, the code is not mine but can be found at multiple places on the web so I have no idea who the initial owner is and who to give credits.

export configuration:

java weblogic.WLST
connect('weblogic','weblogic', 't3://somedomain:7001')
domainRuntime()
cd('/DomainServices/DomainRuntimeService/DomainConfiguration/FirstDomain/SecurityConfiguration/FirstDomain/DefaultRealm/myrealm/AuthenticationProviders/DefaultAuthenticator')
cmo.exportData('DefaultAtn','/tmp/export.ldif', Properties())

import configuration:

java weblogic.WLST
connect('weblogic','weblogic', 't3://someotherdomain:7001')
domainRuntime()
cd('/DomainServices/DomainRuntimeService/DomainConfiguration/SecondDomain/SecurityConfiguration/SecondDomain/DefaultRealm/myrealm/AuthenticationProviders/DefaultAuthenticator')
cmo.importData('DefaultAtn','/tmp/export.ldif', Properties())
 
Leave a comment

Posted by on 18-06-2011 in Oracle, Weblogic, WLST

 

Tags: , , ,

WLST for creating Weblogic domain with RDBMS Security Store

I often use WLST scripts to quickly build a Weblogic or OSB domain for development and testing. However this time I wanted to configure the RDBMS security store which you normally can configure as one of the 1st steps in the wizard GUI.

So this example code creates a Weblogic 10.3 domain with a configured RDBMS security store.

In this case a local OracleXE database is used since it’s on my development machine.
Dont forget to run the rdbms_security_store_oracle.sql script in the Oracle database to make sure all the required tables are present.

#=================================
# Open Weblogic 10.3 template.
#=================================</pre>
readTemplate('c:/osb/wlserver_10.3/common/templates/domains/wls.jar')

#=================================
# Configure Admin settings
#=================================

print('Set default settings for osb_dev_admin')
cd('/Servers/AdminServer')
cmo.setName('osb_dev_admin')
set('ListenAddress','localhost')
set('ListenPort', int('7001'))

#=================================
# Configure User settings
#=================================

print('Start creating OSBadmin user')
delete('weblogic','User')
create('OSBadmin','User')
cd('/Security/base_domain/User/OSBadmin')
cmo.setIsDefaultAdmin(true)
cmo.setPassword('ChangeME01')
cmo.setDescription('OSBadmin created by WLST script')

#=================================
# Configure RDBMS Security Store settings
#=================================

print 'Configure RDBMS security store'
create('base_domain','SecurityConfiguration')
cd('/SecurityConfiguration/base_domain')
realm=get('DefaultRealm')
cd('Realm/myrealm')
rdbms = create("myRDBMSSecurityStore", "RDBMSSecurityStore")
rdbms.setUsername('system')
rdbms.setPasswordEncrypted('password')
rdbms.setConnectionURL('jdbc:bea:oracle://localhost:1521')
rdbms.setDriverName('weblogic.jdbc.oracle.OracleDriver')
rdbms.setConnectionProperties('user=system,portNumber=1521,SID=XE,serverName=localhost')

#=================================
# Write domain and finalize
#=================================

print ('Write domain in: c:/osb_shared/osb_dev_domain')
setOption('OverwriteDomain', 'true')
writeDomain('c:/osb_shared/osb_dev_domain')
closeTemplate()

 
6 Comments

Posted by on 05-08-2009 in Oracle, OSB, Weblogic, WLST

 

Tags: , ,