Sunday, September 3, 2023

Few Gotchas! While Making Your Keycloak FIPS compliant

Keycloak is a very popular Java based open source Identity Access Management product. The recent versions (17.x onward) have gone server-less using Quarkus. When dealing with government, your SSO/ IAM system required to be FedRAMP and FIPS compliant.  Keycloak version 21.x+ is FIPS-2 certified, but additional configurations are needed to make the default Keycloak FIPS 140-2 enabled. 

Enabling FIPs mode in Keycloak is documented here. The documentation covers the steps in a greater detail. However, I have not seen any IAM deployed out of box, so the documented steps are not enough. I went thru series of hair pulling hours to make it work in my environment.  I am jotting down those gotchas here hoping this will help someone.

The FIPS standard revolves around the use of approved crypto module. Keycloak uses only FIPS approved crypto algorithm for it's functionalities when fips-mode is enabled.  

Keycloak recommends to use FIPs validated BouncyCastle library when strict fips-mode is enabled.  So the starting step is downloading BouncyCastle-FIPS bits and adding them to the Keycloak distribution as a crypto Service Provider, so BCFIPS bits will be used instead of the default bits.

(1) Download BouncyCastle jars

The Keycloak documentation instructs to download the following BouncyCastle jars and add them to KEYCPLAO_HOME/providers directory.

bc-fips-1.0.2.3.jar, bctls-fips-1.0.14.jar, bcpkix-fips-1.0.7.jar

However, by copying these jars to "providers" directory does not register it as providers unless you build the Keycloak again. Here is an example of the code snippets from my Dockerfile.

:

ENV KC_FEATURES=fips

ENV KC_FIPS_MODE=strict

ENV KC_HTTPS_PORT=8443

ENV KC_HTTPS_KEY_STORE_TYPE=BCFKS

ENV KC_HOSTNAME="sso.poc.abc.com"

:

ARG BOUNCYCASTLE_FIPS_JAR_LOC='https://downloads.bouncycastle.org/fips-java'

RUN curl -qsSL --retry 3 --retry-delay 0 ${BOUNCYCASTLE_FIPS_JAR_LOC}/bc-fips-1.0.2.3.jar -O --output-dir /opt/keycloak/providers &&\

    curl -qsSL --retry 3 --retry-delay 0 ${BOUNCYCASTLE_FIPS_JAR_LOC}/bctls-fips-1.0.14.jar -O --output-dir /opt/keycloak/providers &&\

    curl -qsSL --retry 3 --retry-delay 0 ${BOUNCYCASTLE_FIPS_JAR_LOC}/bcpkix-fips-1.0.7.jar -O --output-dir  /opt/keycloak/providers &&\

    chmod +x /opt/keycloak/providers/*.jar


RUN /opt/keycloak/bin/kc.sh -v build


The build (last line is) needed to register the providers

(2) Use of BouncyCastle Keystore :

By default, Keycloak uses "PKCS12" keystore and the same is also supported for BCFIPS non-approved mode. However "BCFKS" (BouncyCastle key store) is a must when keycloak runs in strict fips mode. BCFKS can be generated various way (from scratch or from existing PKCS12 etc) depending on your use case.

> Use case I: Creating BCfKS from scratch
Set the secure random algorithm. This will be used in the next step.

$ echo "securerandom.strongAlgorithms=PKCS11:SunPKCS11-NSS-FIPS" > kc.keystore-create.java.security


$ keytool -genkeypair -noprompt\

  -sigalg SHA512withRSA \

  -keyalg RSA \

  -alias sso.poc.server \

  -storetype bcfks \

  -dname "CN=sso.poc.volterra.us, OU=f5xc, O=f5, L=San Jose, S=CA, C=US" \

  -keystore server.keystore.bcfks \

  -storepass ChangeMe! \

  -keypass ChangeMe! \

  -providername BCFIPS \

  -providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \

  -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \

  -providerpath ./lib/bc-fips-*.jar \

  -J-Djava.security.properties=kc.keystore-create.java.security


$ cp server.keystore.bcfks /opt/keycloak/conf/server.keystore


> Use case || : Converting an existing PKCS12 file to BCfKS
This is a typical use case when you already have a PKCS12 keystore delivered by your PKI team ot some other means. The PKCS12 may have been generated using opnenssl or java keytool. 

Example of generating PKCS12 using openssl

$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -node -subj "/C=US/ST=CA/L=SanJose/O=security/OU=sso/CN=sso.poc.abc.com"


$ openssl pkcs12 -export -nodes -password pass:"" \

 -inkey key.pem -in cert.pem \

 -name "server" \

 -out server.keystore.pkcs12


Example of generating PKCS12 using Java keytool

$ keytool -genkey -noprompt \

 -keyalg RSA \

 -alias server \

 -storetype PKCS12 -validity 3650 -keysize 2048 \

 -dname "CN=sso.poc.abc.com, OU=sso, O=security, L=San Jose, S=CA, C=US" \

 -keystore server.keystore.pkcs12 \

 -storepass ChangeMe! \

 -keypass ChangeMe!


The aboves are just example of PKCS12 keycstore creation. The assumption here is, you already have a PKCS12 keystore. Now convert the PKCS12 created above to a BCFKS. 

$ keytool -importkeystore -v \

    -srckeystore server.keystore.pkcs12 \

    -srcstorepass "" \

    -srcstoretype PKCS12 \

    -srcalias "server" \

    -srckeypass "" \

    -destkeystore server.keystore \

    -deststoretype bcfks \

    -deststorepass "password" \

    -destalias "server" \

    -destkeypass "password" \

    -providername BCFIPS \

    -providerpath ./lib/bc-fips-*.jar \

    -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \

    -J-Djava.security.properties=kc.keystore-create.java.security


# test the BCFKS Keystore that is just created by listing it"

$ keytool -list -v -keystore server.keystore \

  -storepass "password" -storetype bcfks \

  -providerpath ./lib/bc-fips-*.jar -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider


$ cp server.keystore.bcfks /opt/keycloak/conf/server.keystore


My use case was similar to above, but little twisted.  My PKCS12 file was delivered by another centralized PKI/ Keystore service through a side car, which runs in my container. So my BCFKS keystore was build from this sidecar provided PKCS12 during my Keycloak container building process.  In this scenario, the above code did not work. I get this error while building BCFKS using keytool.

Importing keystore server.keystore.pkcs12 to server.keystore...
Exception in thread "main" java.lang.IllegalAccessError: class org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider$CoreSecureRandom (in unnamed module @0x4f2d995e) cannot access class sun.security.provider.SecureRandom (in module java.base) because module java.base does not export sun.security.provider to unnamed module @0x4f2d995e
	at org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider$CoreSecureRandom.<init>(Unknown Source)
	at org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider$4.run(Unknown Source)
	at org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider$4.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)

The reason is, the Bouncycastle (bc-fips-1.0.2.3.jar) is not certified for JDK 18 (As of Sep 2023,).  So I had to rebuild my image with JDK 11.

:

RUN microdnf install -y java-11-openjdk-headless ....

:    

RUN /opt/keycloak/bin/kc.sh -v build

:


This fix works in Keycloak version 21.X, but may break in version 22.X. I did not cover all detailed steps as the deployment architectures varies. I tried to jot down the critical blockers that slowed me down in this project.  

Thanks for stopping by my blog!

Saturday, September 5, 2020

Painfull process of Renewing IDP's Signing Certificate in SAML Integration

I learned my first SAML integration in 2005 using a product called SHARE-id developed by Oblix that was later part of IAM product suite of Oracle. Last 10 years there is a huge adaption of SAML protocol for a seamless integration with a centralized Authentication service providers like Azure, Ping, Forgerock, Google and so on. You can also write your own Authentication service supporting SAML. Its is easy to find free library to implement a SAML IDP (Identity Provider) or SAML Assertion consumption service for a SP (Service Provider). 


Here is a diagram of a standard SAML flow.
 


I will not describe how SAML integration work as many good articles are already available in the net. This write-up specifically focus on "Certificate Renewal" aspect of SAML integration. It is one of the major pain point in SAML integration. 

Context  :- 
One or many Service-Providers (SP/ web application) tied to a Identity-Provider (IDP/ Azure, Forgerock, ping, home-grown) in a “Circle of Trust”, where IDP shares the certificate with all SPs.  SP uses this certificate to verify the digital signature in SAML-Response that proves that it has indeed come from the chosen IDP.
 
Now the Issue :- 
Just like any other certificate, IDP’s certificate also expires every 3yrs. All the participating SP need to replace the expired cert with the new one.  When you have 100+ SAML apps in production,  co-ordinating with so many AppOwners and getting the cert replaced requires good amount of planning and effort

Possible Solutions :- 
(1) Plan it out in advance :- 
This is the bare minimum an IDP owner can do :-
o  Add a new certificate to each IDP in non-prod env 3 months before the expiry.  Coexistence of “to-be-expired” certificate with “new” certificate ensure no outage.
o The new cert (and/or IDP-metadata) then distributed to each AppOwner. 
o The expired certificate is removed from the IDP once all AppOwners confirm that their app's SAML integration is working with new certificate.  
o Same processes  followed in production. 

(2) Can we improve this process and automate it ?
Yes, all depends on your organization budget though :)  An IDP-Application-dashboard portal can be built where App-Owners can seamlessly onboard their SAML compatible application thru user friendly App registration process. 
o IDP owner proactively add the new certificate to the IDP before the expiry and portal then notify the app-owners.
o App-owners picks up the certificate and DP meta data and test the SAML integration.
o The portal then remove the old certificate from IDP immediately after app-owner certify the successful integration using the new certificate. 

Basically, the portal replace the the manual co-ordination between IDP-Owner and App-Owner by automating the IDP cert renewal process.  

(3) Any other Options?
Yes, switch to OIDC based integration, which is based on light weight token compared to XML heavy SAML response. OIDC token is signed using either a client-secret or jwks (Json Web Key). We will cover this in the next blog.
 
 

Sunday, April 26, 2020

Practical Tips To Stay Focused In An Ever Distracting Environment

The companies are increasingly adapting Agile methodology, Continuous Integration and Development process to make the delivery efficient.  There is also a noticeable increase of productivity among the developers.  The management expectation has gone up and this creates a quite a bit of stress  on engineers to keep the pace. Staying focused on finishing one logical task becoming increasingly challenging for Lead Engineers when they handle multiple modules with a baggage of supporting many of their previous projects.

Here are few practical tips on staying focused on your high priority tasks.

1. Start your day addressing the Critical item only , not reading the email :-
Many of us starts our day going through the new emails and replying them.  I will suggest spending first two hours of your day addressing the P1 items like :-
  • Any P1 follow-up items from yesterday. Note that you will use the email only for this purpose, not reading the new emails.
  • Any P1 technical issues/ code you are working on.
This will give you a grip over all P1 items.  Reading new emails will distract you to new set of works, rather address the issues that bothering you.


2. Allocate specific time for new email :- 
So when should you read your new emails? Allocate two specific times in a day for new emails and replying them. For example :-
  • Around 10am, two hours after you finish your critical items. 
  • Again at 4pm, before winding down. Now you may have a TO-DO list for tomorrow from these emails.

3. Dealing with too many emails :- 
A very simple solution for this is to apply effective email-filter, so only the relevant email stays on the top.  All enterprise email program comes with filter utilities.
Here are some filter examples :-
  • All emails where you are CCed should goes to "NotToMe" folder . The reason is obvious, you don't have to reply it immediately.
  • We receives tons of email system generated email like, "server xxxx restarted", "The Certificate xxx is about to expire", etc.  Carefully choose these regular emails that belongs to trash. 
  • Put a similar filter to all regular blah..blaha email straight to trash.
  • Create sub folder for different subcategories.  For example anything coming from Jira should go to Jira subfolder.
Building a custom list of  email-filter will take time as it need constant adjusting. But this is one of the most critical tools that helps you avoid wasting time on non critical items.


4. Block few hours for Technical works :- 
The Senior Engineers spend more time on co-ordination and techno clerical work, thus loosing the focus on core technical work.  The best way to address this issue is block at least 16 to 20hrs of your calendar for development work.


5. Everything has a home :- 
Many external factor helps you stay focused.  Few examples could be :- A clean desk, decluttered workspace, clean email box etc.  How to have a clean desk ?  I got this key take away statement "Everything has a hone"  from a time-management training. Any object lies on your desk should have a home. The home could be a paper tray, drawer, book shelves, trash can etc.  Same goes for email.  Every email has a home (a rule based folder) .


6. Continuous Planning :- 
This is mostly applicable to Senior / Lead engineers who are very often face the questions like when it will be done? Why it is not done? What taking so much of time ? What is the estimation ? and so on .. So continuous planning is THE critical task, that will provide you the tool that will help you answering these questions.

Some useful tips on planning tools :-
  • TO-DO list for the Month/ Quarter - Use tools like a formula based planning spreadsheet or Jira structure that will be handy in getting a near perfect report on the project status. Particularly, the number of remaining-hours required for your project stories. At-least 2 hrs a week need to be spend in updating the story detail. Usually I reserve 2 hrs every alternative Friday. 
  • Ensure that your Monthly plan match the road map time line done by your manager. 
  • TO-DO list for the Week :- Maintain a sticky note or a working journal for listing every-days TO-DO list.  This takes only 10 mins and can be done in the morning.  Plan your day around this weekly TO-DO list.

Conclusion :- 
I learned these over the years working in a very demanding environment.  I try my best to stick to these rules, though I just do fire fighting in some of the chaotic days. These tips are not new to many of you.  Love to hear your experience on dealing with distractions and how to stay focused. 

Wednesday, April 13, 2016

Mistaking Kerberos as Single Sign On

End users often misinterpret the Kerberos authentication mechanism to mean Single Sign-On (SSO) in corporate world.  Kerberos authentication provides seamless sign on to (web) applications by using the Kerberos ticket generated/ refreshed during the user’s authentication to the network (when user first login to the computer).

For example, if web applications AppX and AppY are configured for Kerberos authentication, the user will not see any credential challenge when both of these apps are accessed in two different tabs of same browser. This gives the impression of SSO between AppX and AppY.

The SSO functionality is much broader in any in premises Enterprise SSO infrastructure like OAM, SiteMinder, ForgeRock. The Kerberos mechanism is just one of several Authentication schemes available in SSO server.  The Other authentication scheme like Form Authenticaiton can also provide single sign on between two different web apps thru a secure cookie generated by sso server when user first login thru the Form in a Web-Agent based SSO architecture.  

Wednesday, July 30, 2014

OAM R2 Persistent Login (Keep Me logged In/ Remember Me) Set up

I remember struggling with this one in OAM R1.  Since this feature was not available in R1, we implemented this by our own custom code.  Finally this is available in R2.  Here is the link (http://docs.oracle.com/cd/E40329_01/admin.1112/e27239/getstarted.htm#CIHBEEAI) to set this up and test in 30 minutes max.

I am just posting the 1st step of exact WLST command taht I ran to enable it in OAM 11g R2.  Follow the rest of the steps from Oracle doc


$ cd ../Middleware/Oracle_IDM1/common/bin
$ ./wlst.sh

wls:/YOUR_DOMAIN/serverConfig> connect()
Please enter your username :weblogic
Please enter your password :
Please enter your server URL [t3://localhost:7001] :t3://YourServer:7001
Connecting to t3://YourServer:7001 with userid weblogic ...
Successfully connected to Admin Server 'AdminServer' that belongs to YOUR_DOMAINr'.

wls:/YOUR_DOMAIN/serverConfig> configurePersistentLogin(enable="true", validityInDays="30",maxAuthnLevel="2", userAttribute="obPSFTID")
SUCCESS

wls:/YOUR_DOMAIN/serverConfig> exit()

Monday, March 10, 2014

Including Custom MANIFEST.MF File in NetBeans jar Building Process

OAM custom authentication module requires a custom manifest.mf file to be included in your custom plugin jar file. It is is easy to include your own manifest.mf file during jar building process in eclipse. But it not that easy if you are using Netbeans .  If you do a clean build using Netbeans, you will end in having a default manifest.mf file in the jar file.

Here are the steps to include your OAM plugin specific manifest.mf file in the jar.
(1)  Keep your custom manifest.mf file in /src/META-INF/ directory.
(2) Open /YourProject/nbproject/project.properties
comment this line
#manifest.file=manifest.mf

add this two lines that will do the magic
manifest.available=true 
manifest.file=${src.dir}/META-INF/manifest.mf 

(3) Now do a NetBean build, the generated jar file should have "/src/META-INF/manifest.mf" included already.

Wednesday, January 15, 2014

Japanese (non-ASCII) Character Issues in OAM headers variable

I have few user records with Japanese character (like 高山) in their attributes. Querying these users in OVD through ODSM displays it correctly . However, the same attributes when passed as OAM header variable through OAM-Authorization-Scheme spit out garbage like '=?UTF-8?B?6auY5bGx?=' .

This happens because the Webgate will encode any non-ASCII characters in header variables according to RFC 2047. It is the receiving OAM-protected application that will decode the encoded characters. The following java sample code will be a quick rescue. This will transform the non-ASCII character to a readable one.
:
import javax.mail.internet.MimeUtility ;
System.out.println("The Actual Value is := " + MimeUtility.decodeText("=?UTF-8?B?6auY5bGx?=")) ;
:

Your result will be =
The Actual Value is := 高山


Tuesday, July 2, 2013

Always Mark Your OAM Cookie as Secure and HttpOnly

It is a good practice to mark all OAM cookie as Secure and Http-only. This can be done in individual authentication scheme. The exact OAM-11g-R1 syntax is "ssoCookie=Secure;httponly" in Challenge-Parameters field.

httponly :- By marking the cookie as httpOnly, you are ensuring that the cookie can only be used for http protocol. It is not accessible via non-HTTP methods like JavaScript ("document.cookie"). Usually hackers can steal cookies via cross-site scripting.

Secure :- This configuration limit the cookie transmission thru the encrypted(https) channel only. This is an additional security on the top of httponly configuration.


Thursday, March 21, 2013

Resolving OIF Error "FED-15132: Unknown refID" when JSP based form login is used for OAM authentication

The Issues :- 
My OIF server is integrated with OAM for authentication. I used a JSP based form login to collect credential when User makes an IntitateSSO call. I started seeing this error in OIF logs. This is very much reproducible in clustered OAM and OIF servers.

FED-15132: Unknown refID
Cause: User previously accessed the Oracle Identity Federation server with a different host name than the one in the current request and cookies were not transmitted.
Action: Use the same hostname and fully qualified domain URL to access the Oracle Identity Federation 

FED-15128: An internal error occurred while processing the credentials Cause: The authentication engine did not return the required refID parameter.
Action: Check that the authentication flow correctly sent the refID parameter to the Oracle Identity Federation server 


Whats Going on under the hood :- 
The OIF servers is a J2EE application runs on weblogic server which creates a JSessionId. My custom jsp based form login is also another J2EE application deployed on OAM server. When this login page is invoked, it also create a JSession Id. To add a pinch of salt to this issue, I am using same load balancer address (e.g. sso.abc.com) to access multiple Weblogic applications. They all try to use the same JSessionId cookie, which is issued to domain=sso.abc.com path=/.  Now my custom form login session is clashing with OIF's session that is created inside OIF after successful authentication.

Solution :-
You may have already guessed it. Open the weblogic.xml file of you custom Login Form war file and add the followings .

<session-descriptor>
<cookie-name> MyJSessionId </cookie-name>
</session-descriptor>


Basically, you are instructing Weblogic server to create a custom JSessionId (MyJessionId) for your Form login to avoid clashing with OIF's session.

Thursday, February 7, 2013

FIXING BLUE SCREEN ERROR WHEN COMING FROM BOOK-MARKED LOGIN PAGE


This issue is very familiar to all OAM experts. End User very often bookmark the OAM-form login page thinking that it is an inseparable piece of their protected application.  So, when User comes from this bookmarked login page , he ends in the OAM default blue screen as OAM does not where to redirect the user after successful authentication.

DETAIL ISSUE DESCRIPTION:-
To understand this issue , lets understand the OAM (Oracle Access Manager) flows that protects web resources in lay man terms.

1     (1) User access the protected resource (say https://MyApp.abc.com) thru browser.

2     (2) The request hits webserver where Webgate examines every URL pass thru it. It checks, if the requested URL is configured as a protected resource in OAM server. If yes, Webgate  takes the instruction from OAM server and show the configured  login page (https://sso.abc.com/oam-form/login.jsp). User then submits his/ her user-id and password thru the login page.

3    (3) OAM server validates the credential .  If authentication is successful,  OAM server then instructs the Webgate to redirect the user to “Originally Requested URL” (https://MyApp.abc.com).

Note that the login page mentioned in step 2 is a generic login page serve many other applications too. User often thinks that the login page is application (MyApp.abc.com) specific and book marks it. Ideally, user should bookmarks the application (MyApp.abc.com) home page only after successful authentication.
When User comes from the book marked login page , it starts the process from step 2 mentioned above. Webgate does not have the “Original Requested URL”, so it does not know where to redirect the user after successful authentication.  Thus,  Webgate fails to redirect to the protected resource after successful authentication and ends in dirty default blue screen.

SOLUTION :-
We cannot educate user about the OAM internal working mechanism. So lets accept the fact that some user will book mark the login page instead of the application home page.  I would like to thanks my colleague Adam Callen (http://idmrockstar.com/blog/) for the original idea.
If a user comes from a book-marked page, do the followings.

      (1)  Identify, if the user is coming from a book marked page.
2    (2) If No, (by checking if “#URL=*” exists)
a.       OAM server sends the “Oiginal Requested URL” as a parameter.
b.      Extract “Originally Requested URL” from request object and add this URL to the end of login page URL.  

Example :
The blue colored one is the default login page URL and we add the red colored URL when user comes for the first time

Now user may bookmark this page. Note that we injected the  additional URL “Original Requested URL” at the end of the login page URL. If user come from the book marked page we can extract this information later.  Note that the additional information added to the URL only after the page loading is complete.

3    (3) If yes,  (by checking if “#URL=*” exists)
a.       Extract “Originally Requested URL” (https://MyApp.abc.com/) from login page URL (https://sso.abc.com/oam-form/login.jsp#URL=https://MyApp.abc.com/)
b.      Now redirect the user to “Originally Requested URL” (https://MyApp.abc.com/) before the login page loads itself.
c.       Since the “Originally Requested URL” (https://MyApp.abc.com) is a protected resource, now the authentication process will go thru normal process as mentioned in step 2 above.

Here is the javascript that does all the above said trick.
function checkIfBookmarked() {    
    var hashString = location.hash ;     // https://sso.abc.com/oam-form/login.jsp#URL=https://MyApp.abc.com/   
    var extractedHash = "NotBookMarked"
    if (hashString.length > 0) {
        var extractedHash = location.hash.substring(0,5) ;               
    }                 

    // If the URL has a '#URL' value, that indicate user is coming from a book marked page.
    // #URL= contain the URL value of originally requested URL.
    // so extract the value and redirect the user to that originally requested URL.
    if (extractedHash == "#URL=") {       
        var remainingURL = location.hash.substring(5, location.hash.length) ;
        //alert("You fool.. You have bookmarked a common login page. Redirecting to " + remainingURL) ;      
        window.location.href = remainingURL ;               
    }
    else { 
       // user is not coming from a book marked page. We are good, but user may book mark it.
       // so embed the Originally Requested URL to as hash.       
        location.hash = 'URL=' + "<%=origRequestedUrl %>" ;                            
    }
}

Wednesday, October 10, 2012

Quick Tips: Finding the IAM component versions

It was little harder than I thought :(  My weblogic expert friend shared it.

For OIF and OAM :-

Assuming that you have installed OIF from Oracle_IDM2
$ export ORACLE_HOME=/opt/apps/Oracle/Middleware/Oracle_IDM2
$ export PATH=$PATH:/opt/apps/Oracle/Middleware/Oracle_IDM2/OPatch
$ opatch lsinventory -detail -invPtrLoc /opt/apps/Oracle/Middleware/Oracle_IDM2/oraInst.loc

For OHS  :-
opatch lsinventory -detail -invPtrLoc /opt/apps/OHS/Oracle_WT1/oraInst.loc

For WEBGATE :-
opatch lsinventory -detail -invPtrLoc /opt/apps/OHS/Oracle_OAMWebGate1/oraInst.loc -jdk /opt/apps/OHS/oracle_common/jdk/




Monday, October 1, 2012

Changing OIF server parameter using WLST

A quick reference on WLST usage. Here is an example of setting of an OIF server parameter (userldapconnectionreadtimeout') using WLST command.

$ export DOMAIN_HOME=..Directory/Oracle/Middleware/user_projects/domains/OIF_DOMAIN  
$ . Directory/opt/apps/Oracle/Middleware/Oracle_IDM2/fed/scripts/setOIFEnv.sh
$ java weblogic.WLST
wls:/offline> setConfigProperty('datastore','userldapconnectionreadtimeout', '120','long')
                   Please enter your username :weblogic
                   Please enter your password :
                   Please enter your server URL [t3://localhost:7001] :t3://oifServer.abc.com:7499

wls:/EPP_STAGE_SECURITY_DOMAIN/serverConfig> disconnect()

wls:offline >exit()

check for your change at :-
$ vi /opt/apps/Oracle/Middleware/user_projects/domains/EPP_STAGE_SECURITY_DOMAIN/config/fmwconfig/servers/wls_oif2/applications/OIF_11.1.1.2.0/configuration/config.xml

Monday, September 24, 2012

Making your OAM custom Login Form XSS safe

In real life OAM implementation we all use fancy login form , which is called from OAM authentication scheme. These custom login screen often use java scripts. The screen also contain at-least two input parameters 'Login-Name' and 'Password'.  So the screen is perfect play ground for XSS (Cross Site Scripting) attack. Here are few tips to make it XSS safe. For more information about XSS venerability check OWASP (https://www.owasp.org/index.php/XSS) website.

1. Make sure your authentication scheme has a challenge parameter called "ssoCookie=httponly". This will ensure that the java-script cannot read the OAM cookies.

2. The user input validation is must. For example evil user may enter "JohnDoe script alert(document.cookie); script" in the username field to test if the login form is venerable to XSS.

3. Always re-encode user output into safe code html, CSS, JS etc.  For example,  after safe encoding, your javascript should look like "<script> alert(document.cookie); <script>"
The OWASP ESAPI library to do this safe encoding.

Tuesday, May 29, 2012

OVD 11g Quick Tips

Finding OVD version :-
Open file ..../Oracle/Middleware/OVD_INST_1/config/OVD/ovd1/server.os_xml .
Look for section  "OVD_INST_1_OVD" .

Setting OVD Log (Alternative to console) :-
You can set OVD log level directly using console UI. But, you may get an error "JAVAX.EL.ELEXCEPTION: JAVA.LANG.NULLPOINTEREXCEPTION AT JAVAX.EL.BEANELRESOLVER" because of an  OVD 11.1.1.5 bug while doing it from em console.

Here is an alternative approach Doc
1. Stop OVD :
$ORACLE_INSTANCE/bin/opmnctl stopproc ias-component=ovd1

2. Open $ORACLE_INSTANCE/config/OVD/ovd1/ovd-logging.xml change such as to have
<loggers>
<logger name='com.octetstring.vde' level='TRACE:32' useParentHandlers='false' >
<handler name='OVDHandler'/ >
</logger >
<logger name='com.octetstring.accesslog' level='TRACE:32' useParentHandlers='false' >
<handler name='OVDAccessHandler'/ >
</logger >
</loggers>

3. Start OVD: $ORACLE_INSTANCE/bin/opmnctl startproc ias-component=ovd1


Setting Worker Tread :-

Does your OVD error log (.../ovd_inst/diagnostics/logs/OVD/ovd1/http-errors.log) shows occasional error message called “Low on Thread” or “Out of thread”. Check $OVD_HOME/config/OVD/listeners.os_xml for at least 50 worker threads in the LDAP listener.

look for entry
10 and change it to 50 
do it for "Admin Gateway", "LDAP Endpoint" and "LDAP SSL Endpoint".


Wednesday, January 11, 2012

OIM 11.1.1.5 User Manager API bug causes double provisioning

I wrote a Post Process Event Handler code, which provide value to a User's attribute during user creation. The event-handler code was using UserManagerment (oracle.iam.identity.usermgmt.api.UserManager) API.

public class GuidGenerationPostProcEventHandler implements oracle.iam.platform.kernel.spi.PostProcessHandler {
:
public EventResult execute(long processId, long eventId, Orchestration orchestration) { 
HashMap params = orchestration.getParameters();
String uid = this.getParamaterValue(params, Constants.USERID); 
oracle.iam.identity.usermgmt.vo.User user = new User(uid);
user.setAttribute("Micam Unique Id", generateUniqueId()); // generateUniqueId is a private method and returns some value 
try {
   usrMgrService = Platform.getService(UserManager.class);    
   usrMgrService.modify(Constants.USERID, uid, user);
catch (...) 
:
:
}
return ( new EventResult() );
    :
    :

The above said code worked as expected. It generated the value and populated the user attributes called "Micam Unique Id".  But, this code did some damage to my auto-provisioning set up to OID. I saw two auto-provisionings are initiated during user creation event instead of one. I could not figure out the cause. so I posted the query to oracle forum ( https://forums.oracle.com/forums/thread.jspa?threadID=2329154 ) and found the following answer from some of our smart users. 

There is a known issue in UserManagement APIs in OIM 11.1.15. Using the UsrMngmt APIs to update a User within an Orchestration will cause another user update orchestration to be initiated. The user update is also causing role membership rules to be evaluated, which in turn is triggering second provisioning. So solution is to use Entity Management (oracle.iam.platform.entitymgr.EntityManager) APIs instead . The new code snippet is given here, which works fine so far. 

public class GuidGenerationPostProcEventHandler implements oracle.iam.platform.kernel.spi.PostProcessHandler {
    :    
 public EventResult execute(long processId, long eventId, Orchestration orchestration) {        
        HashMap mapAttrs = new HashMap() ;
    mapAttrs.put("Micam Unique Id", generateUniqueId()); // generateUniqueId is a private method and returns some value 
    try {
   String userKey;     
   if (!orchestration.getOperation().equals("CREATE")) 
userKey = orchestration.getTarget().getEntityId();
   else {
    OrchestrationEngine orchEngine = Platform.getService(OrchestrationEngine.class);            
    userKey = (String) orchEngine.getActionResult(processID);
            }        
            
            entMgrService = Platform.getService(EntityManager.class);        
            entMgrService.modifyEntity(orchestration.getTarget().getType(), userKey, mapAttrs);                        
    }
    catch (..) {
    :      
    return ( new EventResult() );
     :
     :

As of writing this blog, there is no UserMgmt & EntityMgmt API documentations available from Oracle. So good luck.