Thursday, August 09, 2012

Configure OAM and WNA with Oracle Middleware (Webcenter/SOA/SES/OBIEE/UCM)

Here is an attempt to summarise my experience configuring the different components of the Oracle middleware with OAM and WNA, there are many post out there with little parts and also some conflicting Oracle documentation, so hopefully this guide will help.....

Lest start with an enterprise implementation of Oracle middleware, in this case, the environment will consist of the following:
  • Oracle HTTP Server 11.1.1.6
  • Oracle WebCenter server (WC Content, WC Portal:Spaces, WC Services) 11.1.1.6
  • SOA Server 11.1.1.6
  • OAM Server 11.1.1.6
  • Oracle DB 11g R2
  • Oracle SES 11g R2 
  • AD Domain Controler Server
  • LDAP Server (OID/OVD/AD)

Pre-Configuration

Virtual Hosts Configuration

Mod_wl is used to proxy all request from the client to the different manage servers in the system being webcenter, discussion server, soa servers, obiee, etc.

Virtual Host are used to allow different configurations of OAM for resources as they are needed, this is based on the standard Oracle Webcenter documentation the following virtual host are needed :
  • Intranet.mydomain.com: this is the main virtualhost for all user request to the system, for example /webcenter will display the spaces application, /search will redirect to the ses servers etc.
  • Intranetnosso.mydomain.com: this is needed for a couple of webcenter components that do not support SSO configurations including the urls used by SES to crawl webcenter and the edit with word functionality
  • Intranetpagelet.mydomain.com: (Only for versions 11.1.1.5 and lower)This is needed for the pagelet producer application, it needs a separate VH because there are references to the “/” context that required to point all resources to the same managed servers. (WC_PORTAL)
  • sso.mydomain.com : This is the Virtual Host used to front the OAM login pages
Some of this is explained in the Oracle documentation for webcenter at http://docs.oracle.com/cd/E15586_01/webcenter.1111/e12405/wcadm_security_sso.htm#autoId56 If you have multiple HTTP servers, a physical LB need to be configured to have a VIP redirecting the request to the 2 HTTP servers, DNS entries are used for all the virtualhosts to point to the same VIP

LDAP Configuration

In this case we will use an OID server as the main Identity Store for the system, this OID needs to be sync with the Active Directory server in order for the WNA authentication to work. This is optional if you are using AD as the identity source ignore this step. There are a couple of things to do if you are using OID:
  1. Create an LDIF file with the following content:
    dn: cn=dsaconfig, cn=configsets,cn=oracle internet directory
    changetype: modify
    add: orclallattrstodn
    orclallattrstodn: cn=orcladmin
  2. Import the LDIF file into OID. To do this, use the following command:
    $LDAP_HOME/bin/ldapmodify -D cn=orcladmin -w -h -p -c -v -f
    
  3. You can verify that the changes you made to the LDIF file by using the following command:
    $LDAP_HOME/bin/ldapsearch -b "cn=dsaconfig,cn=configsets,cn=oracle internet directory" -s base -h -p -w -D "cn=orcladmin" "objectclass=*"
    You should see orclallattrstodn as an attribute of the dsaconfig entry.
  4. Restart OID

Configure AD for Kerberos

First, we need to setup the AD Domain Controller Server, for this we will create a Service Principal Name (SPN) to be used by OAM to authenticate against it, and create a keytab file.

You will need to link an AD user to the server request, this will be the value of the virtual host used for the OAM login pages “sso. mydomain.com” keep in mind that you should requester this DNS entry as a HOST as Kerberos seems to have issues with ALIASES
  1. Create the user in Microsoft Active Directory for example "oracleauthenticator" password "oracle11g"
  2. Run ktpass to create the service principal name and associate it with this user. For example:
    ktpass -princ HTTP/sso. mydomain.com@MYDOMAIN.LOCAL -mapuser oracleauthenticator -pass oracle11g -out C:\temp\sso. mydomain.com.HTTP.keytab
  3. This will create the keytab file "sso. mydomain.com.HTTP.keytab" save it to a temp location as we will needed in the next step.

Configure OAM Server for Kerberos

In this case the OAM server is Linux, before we can configure OAM, we need to setup kerberos at the OS level, to do this, edit the /etc/krb5.conf file and add the following entries, ensure to update the value for the server name of the AD controller.
[libdefaults]
default_realm = MYDOMAIN.COM
default_tkt_enctypes = arcfour-hmac-md5
default_tgs_enctypes = arcfour-hmac-md5
permitted-enctypes = arcfour-hmac-md5
dns_lookup_realm=false
dns_lookup_kdc=false
verify_ap_req_nofail=false
[realms]
MYDOMAIN.COM = {
kdc = DOMAINASSERTER.MYDOMAIN.COM
admin_server = DOMAINASSERTER.MYDOMAIN.COM
default_domain = MYDOMAIN.COM
}
[domain_realm]
.Mydomain.com = MYDOMAIN.COM
Mydomain.com = MYDOMAIN.COM

Now we need to get the kerberos token from AD, to do this:
  1. Create a new folder under the of the Access Manager server, for example: "/fmw/user_projects/domains/iam_domain/sso"
  2. Copy the keytab file you created (sso. mydomain.com.HTTP.keytab) to the OAM Server folder
  3. From the Oracle Access Manager Server, run the following command:
    kinit -k -t sso.mydomain.com.HTTP.keytab  HTTP/sso.mydomain.com@MYDOMAIN.LOCAL
  4. to verify, run the following command:
    klist -e
    Ensure the encryption type match the setting in krb5.conf in the /etc folder.

Install and configure OAM

Install OAM

Please follow oracle documentation to install OAM: http://docs.oracle.com/cd/E21764_01/install.1111/e12002/install.htm#CIHGAEFI

Setup Default Identity Store Connection

From the System Configuration tab, navigation pane, expand the Data Sources node.
  1. Open the OAM Console and login as weblogic
  2. Under the System Configuration Tab, go to Common Configuration ->Data Sources->User Identity Stores
  3. Select the User Identity Stores node, and then click the Add button in the tool bar.
  4. Enter required values for your LDAP (OID/OVD/AD you only need one as long as the users are sync), ensure you add the appropriate base DNs for users and groups
  5. Default Store: Click the Default Store checkbox to make this the default user
  6. identity store for Oracle Access Manager.
  7. Click Apply to submit the changes and dismiss the confirmation window.
  8. Setup an Authentication Module for this LDAP
  9. Restart the Oracle Access Manager Administration Server and managed servers.

Set Up the Kerberos Authentication Module in Oracle Access Manager

  1. Login to the oamconsole
  2. Go to the System Configuration tab
  3. Expand Access Manager Settings
  4. Expand Authentication Modules-> Kerberos Authentication Module
  5. Double Click Kerberos
  6. Enter the values for the keytab created in the previous steps, For example for dev:
    NameKerberos
    Key Tab File/sso/oamssodev.HTTP.keytab
    PrincipalHTTP/sso.mydomain.com@MYDOMAIN.LOCAL
    KRB Config File/etc/krb5.conf
  7. Restart the OAM Server

Disable WebLogic BasicAuth

There are some issues where the basic authentication will display twice for the users, to fix this do the following
  1. Login to the OAM server and go to the $DOMAIN_HOME/config
  2. Edit the config.xml file and add the following entries within the <security-configuration> tag
    <enforce-valid-basic-auth-credentials>false</enforce-valid-basic-auth-credentials>

Configure Authentication Schemes

  • KerberosScheme
    Configure the Kerberos authentication scheme to use WNA as a challenge method
    1. From the Oracle Access Manager Policy Configuration tab, navigation pane, expand the Authentication Schemes node.
    2. Double-click KerberosScheme to display the configuration details.
    3. Change the Challenge Method to WNA, if needed.
    4. Click Apply and close the confirmation window.
    5. Close the page.
  • BasicScheme
    1. From the Oracle Access Manager Policy Configuration tab, navigation pane, expand the Authentication Schemes node
    2. Double-click BasicScheme to display the configuration details.
    3. Change the Challenge Method to the LDAP_OID module created before
    4. Click Apply and close the confirmation window.
  • FormScheme
    1. Double-click FormSchemeto display the configuration details.
    2. Change the Challenge Method to the LDAP_OID module created before
    3. Click Apply and close the confirmation window.


Install and configure WebGate

Install Webgate

Run the Oracle HTTP Server Webgate Installer to install Oracle HTTP Server 11g Webgate for Oracle Access Manager

Oracle reference: http://docs.oracle.com/cd/E21764_01/install.1111/e12002/webgate.htm#CACGIGBB

Configure WebGate Registration Tool

You must complete the following steps after installing Oracle HTTP Server 11 Webgate for Oracle Access Manage
  1. Move to the following directory under your Oracle Home for Webgate:
    $MW_HOME/Oracle_OAMWebGate1/webgate/ohs/tools/deployWebGate
  2. On the command line, run the following command to copy the required bits of agent from the Webgate_Home directory to the Webgate Instance location, the first parameter is the configuration directory for the OHTTP instance, the second is the directory where you installed WebGate:
    ./deployWebgateInstance.sh -w /u01/oracle/11.1.1.6/fmw/Oracle_WT1/instances/instance1/config/OHS/ohs1/ -oh /u01/oracle/11.1.1.6/fmw/Oracle_OAMWebGate1/
    
  3. Run the following command to ensure that the LD_LIBRARY_PATH variable contains the appropiate libraries (replace the path with your MW_HOME):
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/test/oracle/intranet/fmw/Oracle_WT1/lib 
  4. Move to the following directory
    cd $MW_HOME/Oracle_OAMWebGate1/webgate/ohs/tools/setup/InstallTools
  5. Run the following command to copy the apache_webgate.template from the Webgate_Home directory to the Webgate Instance location (renamed to webgate.conf) and update the httpd.conf file to add one line to include the name of webgate.conf:
    ./EditHttpConf -w /u01/oracle/11.1.1.6/fmw/Oracle_WT1/instances/instance1/config/OHS/ohs1 -oh /u01/oracle/11.1.1.6/fmw/Oracle_OAMWebGate1/ –o /tmp/output.txt 

Register WebGate

Run the following from the OAM server
  1. After installing and configuring Oracle Access Manager, navigate to the following location:
    cd $OAM_ORACLE_HOME/oam/server/rreg/client
  2. On the command line, untar the RREG.tar.gz file using gunzip, as in the following example:
    gunzip RREG.tar.gz
    tar -xvf RREG.tar
  3. Set the following environment variables in the $OAM_ORACLE_HOME/oam/server/rreg/client/rreg/bin/oamreg.sh script
    OAM_REG_HOME - Set this variable to the absolute path to the directory where you extracted the contents of the RREG.tar in the setp before($OAM_ORACLE_HOME/oam/server/rreg/client/rreg)

    JDK_HOME - Set this variable to the absolute path to the directory where Java/JDK is installed on your machine.
  4. Create an Agent registration file with all the URLs you need to be protected by OAM, a good starting point can be found at http://docs.oracle.com/cd/E15586_01/webcenter.1111/e12405/wcadm_security_sso.htm#CHDCCHFD
  5. Rename the file for the appropriate environment and update the following entries to reflect the environment
    <serveraddress>http://OAM_SERVER:7001</serveraddress>
    <hostidentifier>intranet</hostidentifier>
    <agentname>Agent_intranet</agentname>
    <agentbaseurl>http://intranet.mydomain.com:7777</agentbaseurl>
    <applicationdomain<intranet_domain</applicationdomain>
    Alternatively, when using 11.1.1.6, each product comes with a pre-build configuration file that you can input when running the script, you can find details of how to do this here http://docs.oracle.com/cd/E25178_01/webcenter.1111/e12405/wcadm_security_sso.htm#BGBHEDHH
  6. After modifying the file, save and close the file. Run the following command on the command line:
    ./bin/oamreg.sh inband input/Agent_intranet_request.xml
    password?(y/n): n                                                                                                                                                                                              Do you want to import an URIs file?(y/n): n
    

  7. The following files and artifacts are generated in the folder: $ORACLE_HOME/oam/server/rreg/client/rreg/output/Agent_XXX_portal (Agent_XXX is the agent name in the Agent_portal-dev_request.xml) directory:
    cwallet.sso
    ObAccessClient.xml
  8. After RREG generates the cwallet.sso and ObAccessClient.xml files, you must manually copy them from the OAM server
    /oam/server/rreg/client/rreg/output/Agent_intranet directory)
    to the Oracle HTTP/Webgate Server directory $OHS_HOME/config/OHS/ohs2/webgate/config.
  9. Restart the Oracle HTTP Server Instance
    opmnctl restartproc process-type=OHS

Update webgate.conf

  1. In the HTTP server go to the $Instance_Home/config/OHS/ohs1/ folder, edit the file webgate.conf
  2. Comment the following entries
    #<LocationMatch "/*">
    #AuthType Oblix
    #require valid-user
    #</LocationMatch>
  3. Restart the Oracle HTTP Server Instance
    opmnctl restartproc process-type=OHS

Configure OAM Domain

Configure Authentication Policies

  • Configure Protected Resource Policy
    1. Go to Application Domains> portal > Authentication Policies >Protected Resource Policy
    2. Ensure the Authentication Scheme is set to the Kerberos Scheme previously setup
    3. Remove all entries starting with /rest.
  • Configure Public resource Policy
    1. Go to Application Domains> portal > Authentication Policies >PublicResource Policy
    2. Ensure the Authentication Scheme is set to the AnonymousScheme
  • Configure WebCenter REST Auth Policy (if you didn't use the OOTB config scripts)
    1. Go to Application Domains> portal > Authentication Policies and create a new policy underneath it called “WebCenter REST Auth Policy”. Choose Authentication scheme as BASIC Scheme
    2. In the new WebCenter REST Auth Policy created above, add all the /rest entries you removed and click Apply. REST needs to follow the BASIC authentication scheme so that external clients, such as the Outlook plugin and iPhone application, can connect to WebCenter REST and be protected with SSO.
      You should be adding the following entries:
      /rest/api/resourceIndex
      /rest/api/spaces
      /rest/api/spaces/.../*
      /rest/api/discussions
      /rest/api/discussions/.../*
      /rest/api/tags
      /rest/api/tags/.../*
      /rest/api/taggeditems
      /rest/api/taggeditems/.../*
      /rest/api/activities
      /rest/api/activities/.../*
      /rest/api/activitygraph
      /rest/api/activitygraph/.../*
      /rest/api/feedback
      /rest/api/feedback/.../*
      /rest/api/people
      /rest/api/people/.../*
      /rest/api/messageBoards
      /rest/api/messageBoards/.../*
      /rest/api/searchresults
      /rest/api/searchresults/.../*
    3. Sometimes, the UCM scripts will create their own exclusion scheme called repeat the steps for the resources in that policy too.
  • Configure Exclusion Scheme
    1. Go to Resources tab and search for resources with their Authentication Policy set to Exclusion Scheme. You should see the following resources:
      /rsscrawl*
      /rsscrawl/.../*
      /sesUserAuth*
      /sesUserAuth/.../*
      /services-producer/portlets*
      /services-producer/portlets*
      /services-producer/portlets/.../*
      /wsrp-tools/portlets
      /wsrp-tools/portlets/.../*
    2. Select the /rsscrawl* resource in the search results and click Edit
    3. Change the Protection Level from Protected to Excluded and click Apply. Note that the resource's authentication policy and authorization policy is removed.
    4. Close the Resources tab and repeat the steps for the remaining Exclusion Scheme resources.
    5. When you now search for resources with their Authentication Policy set to Exclusion Scheme you should see no results

Configure Authorization Policies

  • Configure Protected Resource Policy
    1. Go to Application Domains> portal > Authorization Policies >Protected Resource Policy
    2. Click on the Responses Tab
    3. Add the following entries:
      Name Type Value
      HTTP_USER_NAME Header $user.attr.uid
      HTTP_USER_GUID Header $user.attr.orclguid
      OAM_REMOTE_USER Header $user.attr.uid
  • Configure Public Resource Policy
    Repeat the steps above for the Public Resource Policy

Configure OAM to be accessed via Virtual host

  1. log into the Oracle Access Manager Console at this URL as the weblogic user (http://oamhost1.Mydomain.com:7001/oamconsole)
  2. Click on the System Configuration tab.
  3. Go to Access Manager Settings
  4. Edit the values for load balancing to reflect the Virtual host URL
  5. Modify the following:
    Host: sso.mydomain.com (virtual host configured for login pages)
    Port:7777
  6. Restart OAM managed server

Configure Portal Agent Logout URL to point to the WebTier VH

  1. Go to system Configuration->Access Manager Settings
  2. Expand SSO Agents and double click on OAM Agents
  3. Search for the Agent_intranet and click on it
  4. Modify the logout redirect URL to point to http://sso.mydomain.com:7777/oam/server/logout

Configure WebLogic Security Providers

The following configurations need to be applied to all WLS domains using the web tier, including; Webcenter/UCM Domain,SOA Domain, OBIEE Domain or any other domain configured to be accessed via OAM.
  1. Log into the Weblogic Server Administration Console
  2. From the Domain Structure pane, click on Security Realms
  3. Click on the realm entry to configure the OAM Identity Asserter
  4. In the settings pane, select the Providers tab, then select the Authentication sub-tab
  5. Click the New button to create a New Authentication Provider, and provide a descriptive name.
  6. Select the OAMIdentityAsseter from the list of provider types, then click OK
  7. On the providers tab, select the newly created authenticator, the common settings pane will be displayed
  8. Ensure that the OAM_REMOTE_USER and ObSSOCookie is set for Active Types
  9. Click Save
  10. Repeat the above steps to add the OID or AD LDAP server
  11. Re-order the providers in the list so that the OAM Identity Asserter provider is the first one on the list
    OAMIdentityAsserter (REQUIRED)
    OracleInternetDirectoryAuthenticator (SUFFICIENT)
    DefaultAuthenticator (SUFFICIENT)
    DefaultIdentityAsserter
  12. At the Linux command line, Connect to the WebLogic domain using WLST and run the following command:
    . $ORACLE_HOME/common/bin/wlst.sh
    wls:/offline> connect('weblogic','oracle11g', 'localhost:7001')
    Connecting to t3://localhost:7001 with userid weblogic ...
    
    wls:/webcenter_domain/serverConfig> addOAMSSOProvider(loginuri="/${app.context}/adfAuthentication", logouturi="/oamsso/logout.html")
    Location changed to domainRuntime tree. This is a read-only tree with DomainMBean as the root.
    For more help, use help(domainRuntime)
    
  13. Restart all servers in the domain, including the Admin Server

Post OAM configuration

Webcenter

  • Update Domain Environment settings
    1. Edit the $DOMAIN_HOME/bin/setDomainEnv.sh file
    2. Add the setting “-Doracle.webcenter.spaces.osso=true”
    3. Edit the following settings to reflect the VH:
      EXTRA_JAVA_PROPERTIES="-Doracle.webcenter.spaces.osso=true ${EXTRA_JAVA_PROPERTIES}"
      export EXTRA_JAVA_PROPERTIES

      EXTRA_JAVA_PROPERTIES="-Dnon_sso_protocol=http -Dnon_sso_host=spaces.wcpoc1.oakton.com.au -Dnon_sso_port=80 -Dsso_base_url=http://wcpoc1.oakton.com.au ${EXTRA_JAVA_PROPERTIES}"
      export EXTRA_JAVA_PROPERTIES
    4. Restart all managed servers and Admin Server
  • Update Domain Environment settings
    Using EM console, Update webcenter services to point to the VH URL, this includes Discussion Service, Worklist Service, Search Service

Discussion Server

  1. Create administrator user
    • Log on to the Jive discussions server (http://WC_Collaboration_server_host:WC_Collaboration_server_port/owc_discussions) as user in the LDAP repository (i.e. weblogicadmin)
    • Log on to the database where the schemas for the WebCenter components were created connected as the WCS_DISCUSSIONS user
    • Insert a new record into the table using the SQL below
      INSERT INTO WCS_DISCUSSIONS.JIVEUSERPERM(OBJECTTYPE, OBJECTID, USERID, PERMISSIONTYPE, PERMISSION)SELECT 17, -1, USERID, 1, 59 FROM WCS_DISCUSSIONS.JIVEUSER WHERE USERNAME = ‘weblogicadmin’;
      COMMIT;
  2. Log in to the Oracle WebCenter Discussions Server Admin Console at: http://host:port/owc_discussions/admin
  3. Open the System Properties page and edit (if it already exists) or add the owc_discussions.sso.mode property, setting its value to true.
  4. Edit or add the jiveURL property to point to the appropriate portal base URL of the environment. For example:
    jiveURL = intranet.mydomain.com:7777/owc_discussions

Webcenter Content(UCM)

  • Change HTTP server address
    1. Login to the UCM server via an xSession (VNC)
    2. Go to the folder $DOMAIN_HOME/ucm/cs/bin
    3. Run the SystemProperties applet application
    4. Go to the Internet tab and update the HTTP Server Address to the appropriate portal Virtual Host URL intranet.mydomain.com
    5. Restart UCM managed servers
  • SESCrawlerExport (if you have SES)
    1. Login to the UCM content server as an administrator (weblogic)
    2. Go to Administration/SESCrawlerExport Administration/Configure SESCrawlerExport
    3. Ensure the flag for "Disable Secure APIs" is set to true
    4. Go back to SESCrawlerExport Administration
    5. Take Snapshot

SES

  • Update QueryPlan
    1. To enable OAM SSO authentication, you must configure the following parameters in the QueryPlan.xml file, which is available at $ORACLE_HOME/search/tools/weblogic/deploy/plans/.
      <variable>
      <name>sso_enabled</name>
      <value>true</value>
      <description>Whether SSO is enabled: true or false. The default is false. </description>
      </variable>

      <variable>
      <name>sso_vendor_name</name>
      <value>oam</value>
      <description>The SSO vendor name. Supported values are osso or oam.</description>
      </variable>

      <variable>
      <name>sso_user_guid_header</name>
      <value>HTTP_USER_GUID</value>
      <description>The HTTP header name that the SSO server uses to pass the user GUID to SES. The value in the header should match the value of the users canonical attribute for the active identity plugin.</description>
      </variable>

      <variable>
      <name>sso_username_header</name>
      <value>HTTP_USER_NAME</value>
      <description>The HTTP header name that the SSO server uses to pass the search username to SES. The value in the header should match the value of the users authentication attribute for the active identity plugin. Specify REMOTE_USER to use getRemoteUser in the HTTP request to retrieve the username.</description>
      </variable>

      <variable>
      <name>sso_public_username</name>
      <value>OblixAnonymous</value>
      <description>Specify the username of the public user if the SSO server is configured to send a public user name in the sso_username_header for unprotected or anonymously protected resources.</description>
      </variable>

      <variable>
      <name>sso_logout_return_url</name>
      <value>/oamsso/logout.html?end_url=/search/query/search</value>
      <description>Specify a URL to redirect to after a user logs out.</description>
      </variable>
  • Redeploy the SES Application
    1. Redeploy the query application with the modified deployment plan. To do this, run the following command from $ORACLE_HOME/search/tools/weblogic/deploy/
      ./deployer.sh -serverURL t3://myWlsServer:6666/ -user weblogic -password welcome1 -name search_query -plan $ORACLE_HOME/search/tools/weblogic/deploy/plans/QueryPlan.xml -process redeploy
    2. Restart SES

OBIEE

  • Enabling SSO/Oracle Access Manager for Oracle BIEE
    1. Login to EM Fusion Middleware Control
    2. Click Farm__domain > Business Intelligence > coreapplication
    3. Click the Security tab.
    4. Click Lock and Edit Configuration
    5. Select Enable SSO
    6. Select SSO Provider: Oracle Access Manager.
    7. Enter the login and logoff details
      Loginhttp://sso.mydomain.com:7777/oam/CredCollectServlet/WNA
      Logout http://intranet.mydomain.com:7777/oamsso/logout.html?end_url=/analytics
    8. Click Apply, and then Activate Changes.
    9. Restart the Oracle Business Intelligence components using Fusion Middleware Control.
  • Update SSO details for BI Publisher
    1. Login to OBIEE as an administrator
    2. Go to Administration->Manage BIPublisher->Security Configuration
    3. Update the Single Sign Off URL as previous step
  • Enabling SSO/Oracle Access Manager for Oracle BI Search
    1. Open the BISearchConfig.properties file for editing. You can find this file at $DOMAIN_HOME/config/fmwconfig/biinstances/coreapplication/
    2. Set the value of BIServerSSOUrl to http://intranet.mydomain.com:7777/analytics/saw.dll
    3. Save and close the file
  • Enabling SSO/Oracle Access Manager for Oracle BI for Microsoft Office
    1. Go to the Oracle BI EE Office Server directory. For example
      $DOMAIN_HOME/servers/managed_server/tmp/_WL_user/bioffice_11.1.1/cvsibb/war/WEB-INF
    2. Edit the file bioffice.xml and set the SawBaseURL tohttp://intranet.mydomain.com:7777/analytics/saw.dll
    3. Restart OBIEE

Tuesday, August 07, 2012

Performance Tuning Webcenter Portal

There are so many elements that can impact the portal performance, I tried to compile a list of points and sources you can look at, hopefully it'll be helpful to someone out there...

1) HTTP Resources


WebCenter Portal pages, as well as Webcenter Content and any other web page for that matter, load to the browser, not only the generated HTML of the page, but a set of resources that help display it correctly, this include CSS files, JS libraries, Images, etc. This resources can be big and slow down the page. one of the first things you should do when looking at improving performance, it's to try to minimize the network traffic and latency needed to load these resources, when you thing about it, they seldom change and they are generally common to all the pages, so the best way to approach the issue is to look at three rules:


  • Caching, your browser is capable of caching most of these resources, this will ensure the page is loaded faster and reduce network traffic. you can set headers in the web tier to tune you max-age and tell the browser how long to cache the items.
  • Reduce Size, CSS and JS files often contain spaces , comments and formatting gaps that allows us to understand the files when developing, for production environment however, you should trim all spaces and comments, and produce optimized version of these assets, this will reduce the size of the documents.  Another thing you should consider to reduce the size, is to enable compression at the Web tier level, Apache can do this by using mod_deflate, if you are using Oracle Web Cache you can also configure it to provide compression for your files
  • Avoid unnecessary  resources: ensure you don't load unnecessary CSS or JS files, also try creating a single image for all your icons and use css positioning to display them, another thing to look at is to ensure you don't have nay 404 errors when loading the page, this are mainly pointers to resources removed from the server or misspelled.

A couple of resources to look at, if you want to configure the HTTP server:

https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_performance

If you want to use webcache:
http://www.oracle.com/technetwork/middleware/webcenter/webcenter-webcache-integration-176984.pdf


Here is an example of how the webcenter entry looks after following the compression and caching methods



SetHandler weblogic-handler
WebLogicCluster MYCLUSTER:PORT
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/html
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|bmp|ico)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:pdf|doc?x|ppt?x|xls?x)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.avi$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mov$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mp3$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mp4$ no-gzip dont-vary

for resources caching:


Header unset Last-Modified
Header unset Expires
Header set Cache-Control "max-age=2592000, public"
Header set Surrogate-Control "max-age=2592000"
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/css
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary


2) JVM Memory

Heap Size
First of all you want to ensure the JVM has enough resources to work, this will depend entirely on your implementation, but you will want to allow the heap size to be between 2-3 GB, if your application requires more memory (you will be able to tell by the number of garbage collections and/or if you get the old java.outofmemory in the logs) consider spreading the load to another JVM instead of just increasing the heap size. You can clone the manage server and configure a cluster via weblogic.

Oracle provides a good set of recommendations regarding this at:

http://docs.oracle.com/cd/E17904_01/core.1111/e10108/webcenter.htm#BABEJCDE

To increase the heap size in the JVM to 2gb, for example, add the following to the start arguments of the managed server:

-Xms2048M -Xmx2048M -Xns512M

Weblogic mode

Another thing to consider is to enable the production mode in the weblogic domain, this adds additional security ad disables add-hot deployments from jdev, but also sets internal optimizations to the JVM 
 
-Dweblogic.ProductionModeEnabled=true

3) ADF Resources


ADF creates specific resources in the system for each page, and user, this resources represent the view and control page of the pages, and are loaded into the memory, you need to ensure the size of these memory objects doesn't grow exponentially when you add load to the system, also, when you have a hybrid navigation, for example your site needs to navigate between the webcenter application and static content deliever by another app like UCM site studio, or if you have a WebCenter portal application delievering your pages and Webcenter Spaces delievering the micro sites (you may want to consider this setup as the pages will run faster in the custom portal than in spaces), then the view and state objects are lost and left in the memory and need to be cleaned up by the system.

Cleanup Inactive Objects

To tune the clean up of these objects, you can set a few parameters in the startup arguments of your JVM

-Djbo.ampool.maxinactiveage=180000

This parameter defines how long an object can be inactive in the memory before it is tagged to be removed by the garbage collection

-Djbo.ampool.monitorsleepinterval=90000
This one defines how often to sweep the memory looking for inactive objects

Be aware however that this parameters also govern the pooling of connections to the database and other objects ADF reuses, so you need to find the right balance for your implementation. a good reference of these parameters and overall ADF tuning can be fond here:

http://www.oracle.com/technetwork/developer-tools/jdev/adfbc-perf-and-tuning-095672.html

HTTP Session

Another parameter that governs the re-usage of objects in memory and their life spam is the HTTP session, for your portal application you can modify the time out in the web.xml, the default value is 45 mins, reducing the time will free up memory however the users may get annoyed by the timeout if too low, again you need to find the right valance for your implementation

View and Control States

The view and control states in the memory are also mantain for multiple pages as the user navigates, this allows the back button on the browser to work, the problem is that the more pages the users navigates throught and the more users will increase the memory usage, The number of pages to mainain in memory for the user session can be control by the CLIENT_STATE_MAX_TOKENS in the web.xml of the application, spaces usually defaults to 15, while custom portals to 3. the lower the value the less memory required for each user, this also depends on your implementation and if you need the users to use the back button to navigate, also if you have a hybrid navigation as described before, it's better to set a low value. also consider the points in the following blog note about this setting:

http://andrejusb.blogspot.com.au/2011/07/adf-view-state-tuning-for-large.html


You should also set the view state to be compressed to reduce the size, this is controlled by the COMPRESS_VIEW_STATE setting in the web.xml

Performance Testing

Also, if you are doing performance or stress test for your implementation (and you should), make sure that the test scripts maintain these view and control states, otherwise you will end up with bogus memory leak results, a good reference for stress testing can be found here:

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/adfloadstresstesting-354067.pdf




4) Data Sources


LDAP Tuning

Ensure the communication with your LDAP server, either OID or AD is good and that the server can handle the queries generated by webcenter, there are a couple of settings Oracle recommeds for OID here :

http://docs.oracle.com/cd/E21764_01/webcenter.1111/e12405/wcadm_security_id_store.htm#BGBGIAHC


JDBC pooling for read-only taskflows


For the tasklflows that are display on your portal pages, it is important understand the DB requirements, in most cases, these taskflows haev a read-only behaviour providing a snapshot of information and allowing the users to open another page or application where they can perform more actions, if this is the case, your DB connections don't need to maintain the transactions, and they perform small queries and can be release back to the pool as soon as they finish, usually in a portal scenario you have mainly read-based transactions in a common page displaying simultaneously, so one user calling one page can potentially set hold to more than 5 connections, also there are several performance considerations, so one of the key points for this type of TF in the page is to set the  following JDBC pooling options in the Application Module:

  • jbo.doconnectionpooling = true
  • jbo.txn.disconnect_level = 1

There are a couple of good articles about the benefits and trade-off of this configuration one of the more comprehensive ones is at:

http://andrejusb.blogspot.com.au/2011/10/adf-bc-tuning-with-do-connection.html

Also avoid XA drivers...

Web Services

Web Services are usually expensive transactions that gather data from multiple sources, ensure you cache some of the heavy resources, use coherence it's embed in the SOA suite and can significally reduce the time of the request

5) Taskflows


Only load what you need to


Your page will be as fast as your slowest TaskFlow, with this in mind you need to ensure the page does not need to wait for any taskflows or data sources that will take a long time. a few things to keep in mind:


  • Avoid Loading unnecessary taskflows: It is common to have taskflows in the page that are not loaded to all users or are loaded only upon certain conditions, this will also apply to pages with tabs,  you generally will use the "rendered" option to hide the taskflow, unfortunately, while this hides the taskflow from the View object of the page, the bindings still exists and will need execute before the page is displayed to the user, ensure you also modify the "Activation" flag in the bindings of the page, and set it to "Conditional", and then set the "Active" flag to the same condition as the "rendered" parameter in the jsff. Here is a good document explaining this in more detail:
  • For PopUps, ensure you have the ContentDelievery flag set to  "lazyUncached" this ensures the contents of the popup are not loaded until it is call and the initial page load is not affected

Load View Objects first

As I mentioned before, the page will be as fast as the lowest taskflow, so for example, I recently got across and implementation where the homepage, based on webcenter portal was taking almost 25 seconds to respond, even without any load to the server, upon further investigation, I found that there where 2 taskflows in the page that made web services calls, unfortunately, the way they were build, there was an initial action on the taskflow to call the web service, and then after the results were gather, a success action to display the jsff.

The problem here is that the View Object of the page will not be build until the service returns data, if the taskflow did not have a view object, that meant that the whole page will have to wait for the service to return to display to the user.

There are a number of build-in features within ADF that allow the view components to build and then do PPR to gather data, it is restricted to stamp components, so you should when possible USE TABLES or iterators, under the table's settings, you can find the Content Delivery method, it can be set to immediate, whenavailable or Lazy, use Lazy to force the table to be presented to the user before the data is available, this works for long queries or web services this way the page and other components in the page are shown to the users and the data is rendered once available.

For the above case, we re-build the taskflows so they will only have the view jsff action and call the service via the ADF View model. we managed to reduce the page loading time from 25 to 4 seconds, there were 12 components on the page but only 1 build incorrectly was creating a big impact.

I have to say however that one of the taskflows did still wait to return the view object even after the table and lazy delivery change, we manage to fix this issue but doing a little "hack" with the same concept in mind, we build the taskflow with an empty data-set, and created a PPR using an adf loop (I'll explain this in another post) that called the webservice and refreshed the table, the concept was the same as the Lazy delivery, ADF sometimes requires some persuasion to work as the documentation says it should.....

Cache,Cache,Cache..


Another thing to consider for long running queries and webservices, is to cache the results so the next time the users calls the page, we don't have to use resources again to retrieve the data from database or soa server. This is specially important for frequently visited pages like the portal home page. I mentioned coherance before, it is very simple to create a coherance cache, it's already configured to work in the managed server by default, you just need to use it, I'll post a small example in another post soon.

Hopefully this gives you a general guide to start tuning your implementation, the recommendations here by not means should be taken without considering your own requirements and architecture, this is not a recipe, understand your implementation before changing any configuration.

Wednesday, August 01, 2012

Setting Default Accounts to All Users

When enabling accounts in Webcenter Content for documents that require public access or that need to be view by all users, there is a need to set some default read accounts in order for this to work.

This post assumes that you have a public site with security group "Intranet" and a top account MySite, the guest role has read access to the Intranet SG. We also assume that you are using weblogic security realm to configure LDAP and your accounts and SG are managed as LDAP groups.

The documentation explains the use of default accounts to the annonymous user, which is used when the user has not logged into the content server, this is done by setting a configuration parameter in the config.cfg or via the Amin Server--> General Configuration --> Additional Configuration Variables.

DefaultAccounts=#none(R),MySite(R)

This setting defines the access the guest user will have on the content by default, remember that the access to the content will be a combination of the account and the security group, so the guest role needs to have read access in the SG for this to work.

The value #none(R) defines read access to documents without accounts, the value  MySite(R) sets read access to all documents in the MySite account, this sets read access to all sub accounts, if i only one the user to have access to a section of the documents I can user MySite/MySection1(R).

If you want the annonimos user to have read access to all the accounts in the system you can set the value  #all(R).

The above feature is well documented, however, what happens when the users login, for example, if it is an intranet site and I want all LOGGED users to have read access to the site. as the above setting only applies to anonymous, once logged in the users won't be able to see the site unless they are specifically added to the MySite(R) account. technically they will have more access before they login than after.

To provide a default account to logged users without having to add them all to the LDAP group mapped to the account, you can set the preferences in the JpsUserProvider, this is the default provider UCM users to communicate with the underlining weblogic and the security realm (LDAP).

To access the provider, go to Administration->Providers ->JpsUserProvider ->info

Once on this page, you can edit the provider and user the "Default network Accounts" variable to assign the values for all users that authenticate via the weblogic security (this can be any LDAP server or the internal wls one)

Default Network Accounts: #none(R),MySite(R)





Tuesday, April 24, 2012

Querying the Webcenter Spaces DB tables

While WCS comes loaded with REST services to extract information from the system, sometimes, specially when your application runs in the same backend, it's easier to query the DB directly to extract information from spaces. here is a quick overview of some tables I have used in the past to do just that.

Users' Information

In a standard implementation, all the user information will come from the LDAP server configured as the main Identity Store of the Weblogic Domain. webcenter however, keeps a copy of some user's details that can be reused in your custom applications. remember this information is only populated after the user logs in to the portal, also you need to ensure the GUIDs are maintain across LDAP environments.

The main table to query is  MYPORTAL_WEBCENTER.WC_AS_ACTOR_DETAIL this table contains the user's full name and email addresses, also, it contains the user's ACTOR_ID which is used in other tables and applications to reference the user.

SELECT   ACTOR_ID, DISPLAY_NAME,EMAIL,DEPARTMENT,JOB_TITLE, MANAGER_ID
FROM MYPORTAL_WEBCENTER.WC_AS_ACTOR_DETAIL
WHERE upper(ACTOR_NAME) = 'JSMITH';

Another table that may be useful is
MYPORTAL_WEBCENTER.WC_PEOPLE_CONN_CONNECTION, this table contains the information about the user's friend/connection list, the users are referenced using theri ACTOR_ID. One thing to keep in mind with this table is that the connections are stored unidirectional, which means that you need to search where the user is the person that send the invitation and also when he/she received, here is an example of how to get the list usersnames from the connections of a given username

SELECT CD. DISPLAY_NAME CONNECTIO_NAME
FROM MYPORTAL_WEBCENTER.WC_PEOPLE_CONN_CONNECTION PC, MYPORTAL_WEBCENTER.WC_AS_ACTOR_DETAIL AD, MYPORTAL_WEBCENTER.WC_AS_ACTOR_DETAIL CD
WHERE ((PC.OWNER_ID=AD.ACTOR_ID AND PC.CONNECTEE_ID=CD.ACTOR_ID) OR (PC.CONNECTEE_ID=AD.ACTOR_ID AND PC.OWNER_ID=CD.ACTOR_ID))
AND upper(AD.ACTOR_NAME) = 'JSMITH';

Spaces' Information

The main table to look at is  MYPORTAL_WEBCENTER.WC_SPACE_HEADER  this table stores all the spaces in the system, their status, last updated, and other attributes like parent space and member count.

here is an example of the query including some Oracle XMLDB smarts to retrieve the count of sub-spaces:
SELECT
  DISPLAY_NAME SPACE_NAME,
  DESCRIPTION,
  GS_MEMBER_COUNT MEMBERS,
  SPACE_PUBLIC "IS_PUBLIC",
  DISCOVERABLE SHOW_IN_SEARCHES,
  SPACE_OFFLINE IS_OFFLINE,
  CREATE_DATE CREATED_ON,
  UPDATED_BY,
  LAST_UPDATE_DATE,
  SUB_GS_COUNT SUBSPACES_COUNT,
  (select RTRIM(XMLAGG(XMLELEMENT(e,DISPLAY_NAME || ',')).EXTRACT('//text()'),',')  SUBSPACES FROM MYPORTAL_WEBCENTER.WC_SPACE_HEADER B where B.parent_GUID=A.SPACE_GUID) SUBSPACES
FROM MYPORTAL_WEBCENTER.WC_SPACE_HEADER  A
WHERE CLOSED='N'
order by 2 desc;

Statistics

Also, as webcenter Analytics is keeping record of all activity in the system, those tables can be used if you need a particular report that is not in the OOTB analytics pack.


For example, to get the daily page hits of a particular page in the system, first we need to get the page ID, to do so we check the  MYPORTAL_ACTIVITIES.ASDIM_WC_PAGES_0  table we can query the name of the page or the name of the jspx from the URL as follows:

From page name:

SELECT ID FROM MYPORTAL_ACTIVITIES.ASDIM_WC_PAGES_0 where lower(NAME_)  LIKE '%profile%'

From JSPX:

SELECT ID FROM  MYPORTAL_ACTIVITIES.ASDIM_WC_PAGES_0 where lower(RESOURCEID_)  LIKE '%spacesmainview.jsp%'
Once you have the ID or IDS of the pages you want to query, you can then look at the table  MYPORTAL_ACTIVITIES.ASFACT_WC_PAGES_0 this table stores all the page hits of the system, you can query it as follows:

select ndate, count(*) ntotal from MYPORTAL_ACTIVITIES.asfact_wc_pagevie_0 a where a.page_ in (SELECT ID FROM  MYPORTAL_ACTIVITIES.ASDIM_WC_PAGES_0 where lower(NAME_)  LIKE '%profile%') group by to_char (occurred ,'DD/MM/YYYY')

Friday, December 02, 2011

ADF Mailto - IE Compatibility mode

Hi all,

Recently, I encounter a very strange issue with the mailto functionality in IE8, after looking in the web I found lots of references to the problem but not valid solutions, so I came up with this little hack/workaround for it.

Basically, the problem presents itself when the user clicks in a "mailto" link within a page that is in the "trusted zone" of IE. if the trusted zone has not compatibility mode, and the internet zone does, IE treats the mailto as being part of the Internet zone and does a weird local refresh of the page with causes the IE page to display an error ""Internet Explorer cannot display the webpage"

To add to the picture, I had UCM pages in the same URL domain with mailto links working fine, the issue only presented itself when we were adding the links to ADF taskflows.

The issue could be simply resolved by changing the IE settings, either making both the trusted zone and the internet zone run in compatibility mode or turn it off on both, unfortunately, when you roll-our to a company with mode than 8000 users, changing the IE settings is not as trivial as one may think.

So, after trying multiple things, here is what we ended up with... basically, the idea is to show the mailto in a pop-up, this way the local refresh of IE doesn't impact the page, we also needed to hide the pop-up before the refresh otherwise we end up with 2 outlook windows being open.

First off, at the begining of the JSF page, add the following JS function used to show and close the popup, the function uses the v_popop variable to identify which popup to show in case you need to add more than one link to the page

<af:resource type="javascript">
function showMailerPopup(actionEvent)
{
actionEvent.cancel();
var eventSource = actionEvent.getSource();
var v_popup = eventSource.getProperty("v_popup");
var popup = eventSource.findComponent(v_popup);
popup.show({align:AdfRichPopup.ALIGN_AFTER_START, alignId:eventSource.getClientId()});
popup.cancel();
}
</af:resource>


Then, we add the link using a af:commandLink, to call the JS function when the user clicks the link we add a af:clientListener referencing the JS function and a af:clientAttribute to pass on the v_popup variable with the is of the popup.


<af:commandLink text="Send Email Sample" id="cl3" >
<af:clientListener method="showMailerPopup" type="action" />
<af:clientAttribute name="v_popup" value="mailer1"/>
</af:commandLink>

Then, right after the af:commandLink we add the popup with the id as per the af:clientAttribute in the af:commandLink, the only think in the popup is an af:inlineFramewith the src attribute set to the mailto link


<af:popup id="mailer1" clientComponent="true">
Opening Outlook...
<af:inlineFrame id="if1" inlineStyle="width:2px; height:2px;" visible="false" shortDesc="mailer" source="#{mailto:joe.smith@myemail.com}" clientComponent="true"/>
</af:popup>

Wednesday, December 08, 2010

How to add LDAP users to a UCM role

 Usually, when integrating with an LDAP server you will manage all memberships of users by mapping LDAP groups to UCM roles or accounts.

However, sometimes you don't have control over LDAP to create and modify the roles you need in your UCM application. In 11g there one easy way to do this is to modify the user's type to "Local" allowing you to add the user in to the UCM roles via the old User Applet, check this Oracle blog for more info (https://blogs.oracle.com/kyle/entry/mixed_authentication_and_autho) ...


Alternatively or for older versions like 10g you can use the Extended User Attributes to query and modify user's memberships. You need the Extended User Attributes component, you can find it as part of the CS10gR35UpdateBundle patch. After installing the component, you can add or remove access using the Extended User Attributes Services you can find some information in the Oracle documentation (http://download.oracle.com/docs/cd/E14571_01/doc.1111/e11011/c12_extuserattr002.htm )

Here is a simple example of how to query the external users access:

Parameter received (dName): <!--$dName--><br />

<body>



dName: <!--$dName-->

<br>

Date:<!--$ dateCurrent() -->



<table border=1>

 <tr>

   <td><b>User</b></td>

   <td><b>Application</b></td>

   <td><b>Access</b></td>

  </tr>

  <!--$executeService("QUERY_EXTENDED_USER_ATTRIBUTES")-->

  <!--$loop ExtUserAttribInfo -->

  <tr>

   <td><!--$dUserName--></td>

   <td><!--$dApplication--></td>

   <td><!--$AttributeInfo--></td>

  </tr>

 <!--$endloop-->

<table>


</body>

JDBC to Oracle RAC

Here is a simple example of how to connect to an Oracle RAC DB using JDBC

 url="jdbc:oracle:thin:@(DESCRIPTION=
   (LOAD_BALANCE=on)
    (ADDRESS=(PROTOCOL=TCP)(HOST=node1-vip)(PORT=1521))
    (ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521))
    (ADDRESS=(PROTOCOL=TCP)(HOST=node3-vip)(PORT=1521))
    (CONNECT_DATA=(SERVICE_NAME=MYRACDB)))"