Wednesday, November 7, 2007

Self signed ssl certificates with oracle oc4j and ssl wallets

After beating my head against the wall for about 2 hours I got this to work - the documentation from oracle did not contain one important little gotcha which would have saved me at least an hour! Essentially what I am doing here is creating a self-signed certificate for developers who are making SOAP or access calls to seperate secure web servers AND the secure web server is using Oracle Apache/Webcache and SSL Wallets, since the application has no way of asking if the (self-signed) certificate should be accepted the app will fail with something like this:
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Ok, onto the work:
  • server1 = OC4J containers - application deployed here, making https calls to server2
  • server2 = Oracle Apache/WebCache server, app calls to https://server2/ causing errors
  1. Become your own Certificate Authority
      • In Fedora the package that provides CA.pl (yum whatprovides CA.pl) is openssl-perl from the core repos.
  2. OWM (Oracle Wallet Manager) on server2
    • Start a vnc session (Im sure you could also use X forwarding, but I'm lazy) to server2
      • open a terminal window
      • $ cd $ORACLE_HOME/webcache/wallets/
        • cp -pR defaults backup
      • $ cd $ORACLE_HOME/bin
      • $ ./owm
        • Wallet -> New
        • "Your default wallet directory does not exist. Do you want to create it? NO
        • Create a password for you wallet, click YES
        • Do you want to create a certificate request at this time? YES
        • Enter the information for your cert, remember that the "Common Name" must match the url that is serving https requests, if it does not you will receive certificate errors - example.com and www.example.com are different in this case! Click OK when you have entered all the info and click OK again on the "certificate request has been created" dialog box
        • Under you wallet you should now see an entry like "Certificate:[Requested]", click on this and copy the Certificate request (including the BEGIN NEW CERTIFICATE REQUEST line)
      • open a terminal on the box you created your Certificate Authority on and paste the Certificate Signing Request (csr) into a text file, in my case /home/nate/CA/certs/example.com.csr
      • $ CA.pl -sign after renaming your .csr to newreq.pem
        • enter your CA password
        • Sign the certificate? [y/n]: Y
        • commit? [y/n] Y
        • copy the newly created certificate from the BEGIN CERTIFICATE line to the END CERTIFICATE line
      • Back in the vnc session in the owm application
        • Operations -> Import User Certificate -> Paste the certificate, click OK
        • Paste the the newly created cert in the dialog box and click OK
        • OH NO, an error... we can fix this "User certificate import has failed because the CA certificate does not exist. Do you want to import CA certificate now? YES" -> Paste the certificate, click OK
      • on your CA box look in the CA dirctory for a file called cacert.pem
        • $ cat /home/nate/CA/cacert.pem # copy from BEGIN CERTIFICATE to END CERTIFICATE
      • Back in the vnc session in the owm application
        • paste the CA certificate into the dialog box and click OK
        • At this point your Wallet should say "Certificate:[Ready]" and your CA cert should be listed under the Trusted Certificates
        • Since I am using webcache on the apache box I am going to save this in the webcache directory but if I was using apache then it would be the apache directory and I would also possibly need to modify the SSLWallet directive in the ssl.conf file, if you are using apache without webcache checkout the references to the oracle docs at the end of this document since they cover this part well... what they don't cover - and what I had issues with is using the ssl wallet with webcache so....
        • one of the first steps created a backup of $ORACLE_HOME/webcache/wallets/default so we can overwrite those files without worry
        • Wallet -> Auto Login # this allows apache (and I assume webcache) to startup without asking for the wallet password... very important
        • Wallet -> Save As -> $ORACLE_HOME/webcache/wallets/default
          • Do you want to overwrite it? YES (you made a backup right?)
        • Now in $ORACLE_HOME/webcache/wallets/default on server2 you should have two files: cwallet.sso and ewallet.p12 that contain your certificate, if you want to verify try the orapki command
          • $ORACLE_HOME/bin/orapki wallet display -wallet $ORACLE_HOME/webcache/wallets/default/ewallet.p12
            • enter your wallet password and BAM there is the stuff...
    • You can now bounce WebCace ($ORACLE_HOME/bin/opmnctl stopproc ias-component=WebCache ; $ORACLE_HOME/bin/opmnctl startproc ias-component=WebCache) and navigate to https://server2/ in a web browser and YOUR cert should pop up as untrusted - this is ok, as long as it is your cert and not the default Oracle cert!
  3. Importing your certificate into the cacerts file on server1
    • On your CA server copy the self-signed certificate that was created in the previous steps
    • Logon to server2 and navigate to the OC4J container jdk/jre/bin directory
      • $ cd $ORACLE_HOME/soa1/jdk/jre/bin
      • paste the cert into a text file
      • $ ./keytool -v -import -alias example.com -file ./example.com.crt -keystore ../lib/security/cacerts
        • default password on oracle keystores is: changeit
      • In my case the OC4J containers are clustered so I needed to duplicate this
      • $ cd $ORACLE_HOME/soa2/jdk/jre/bin
      • $ ./keytool -v import -alias example.com -file ../../../../soa1/jdk/jre/bin/example.com.crt -keystore ../lib/security/cacerts
      • Bounce the OC4J containers
  4. Done!
References: