Oracle MVA

Tales from a Jack of all trades

Archive for the ‘security’ Category

Online Master Key with Oracle Key Vault on a Consolidated Platform

leave a comment »

Seems I am writing a series. In part 2 on Oracle Key Vault (OKV): having 2 databases using the same OKV.

In part 1 I mentioned an open item: what happens if you run this okvclient on a consolidated environment? Here are my notes.

Please mind: this is written with my little knowledge of Oracle Key Vault. It is likely that I will find out more in the (near) future and have to update this series as a consequence.

If you want to create the master key for TDE in the same virtual wallet for both databases, you can simply create a symbolic link that links the configurations together

ln -s $ORACLE_BASE/okv/saucer $ORACLE_BASE/okv/alien

Yes my databases have names that match the db_domain (area51).

The downside to this, is that you only have one endpoint and therefore both databases can read each others keys. I can imagine this being a problem if you ever decide to move your database to another server. Also there is a security risk, if one database is compromised, then the second database is automatically compromised also. So this was a no-go.

Snapshots of VMs rock, rollback and proceed with a second okvclient installation.

I created a second endpoint in OKV for a database and enrolled the endpoint. Furthermore I scp-ed the okvclient.jar file that was downloaded with enrolment and copied this to my database server.

When you run the okvclient.jar file as described in documentation and point to the same installation directory as used for the first okvclient.

java -jar okvclient_alien.jar -d /u01/app/oracle/product/12.2.0/okv -v
Oracle Key Vault endpoint software installed successfully.

For the reader that is familiar with the client an immediate problem occurs: no endpoint password is requested! Further investigation showed that only the installation logfile was updated and configuration was not changed. This means that you do not have any configuration for the new endpoint, basically you are the scenario where you share keys.

Since I don’t know how to create configuration manually, I rolled back to the snapshot again. (did I already mention that VirtualBox snapshots rock?)

So, I re-enrolled the endpoint and ran the installer again, only now pointing to a new directory

java -jar okvclient_alien.jar -d /u01/app/oracle/product/12.2.0/okv_alien -v
Detected JAVA_HOME: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.111.x86_64/jre
Enter new Key Vault endpoint password (<enter> for auto-login):
Confirm new Key Vault endpoint password:
Oracle Key Vault endpoint software installed successfully.

This is not the situation I want, I prefer to have one set of software and multiple configurations. A very short investigation of the configuration setup suggested that there are exactly 2 differences between the two okv client installations:

  1. okvclient.ora, where most prominent is the difference CONF_ID and SSL_WALLET_LOC
  2. ewallet.p12, the password is the registration password and showed different keys

So, copying these files to the local configuration directory should get my desired result: 1 software tree with multiple configurations. First the setup of saucer:

rm /u01/app/oracle/okv/saucer/okvclient.ora
cp /u01/app/oracle/product/12.2.0/okv/ssl/ewallet.p12 /u01/app/oracle/okv/saucer/
cp /u01/app/oracle/product/12.2.0/okv/conf/okvclient.ora /u01/app/oracle/okv/saucer/

Turns out that if you move the files okvutil does not function anymore. Also you have to update okvclient.ora and point the SSL_WALLET_LOC to the new location (/u01/app/oracle/okv/saucer). Then check the configuration:

SQL> conn/as sysdba
Connected.
SQL> show parameter db_name

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_name 			     string	 saucer

SQL> select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
FILE		     NOT_AVAILABLE
HSM		     CLOSED

2 rows selected.

SQL> ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY Welcome01;

keystore altered.

SQL> select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
FILE		     NOT_AVAILABLE
HSM		     OPEN

2 rows selected.

Super duper. Proceed with the second okvclient:

mkdir /u01/app/oracle/okv/alien
mv /u01/app/oracle/product/12.2.0/okv_alien/ssl/ewallet.p12 /u01/app/oracle/okv/alien/
mv /u01/app/oracle/product/12.2.0/okv_alien/conf/okvclient.ora /u01/app/oracle/okv/alien/

Now the /u01/app/oracle/product/12.2.0/okv_alien install is obsolete.

Proceed with setting the encryption key

SQL> conn/as sysdba
Connected.
SQL> show parameter db_name

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_name 			     string	 alien

SQL> select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
HSM		     CLOSED

1 row selected.

SQL> ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY Welcome01;

keystore altered.

SQL>  select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
HSM		     OPEN_NO_MASTER_KEY

1 row selected.

SQL> ADMINISTER KEY MANAGEMENT SET ENCRYPTION KEY IDENTIFIED BY "Welcome01";

keystore altered.


SQL> select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
HSM		     OPEN

1 row selected.

Presto!. Hope this helps.

Written by Jacco H. Landlust

December 20, 2016 at 2:03 am

Oracle Key Vault: Migrating an Existing TDE Wallet to Oracle Key Vault

with one comment

Currently I am evaluating Oracle Key Vault (OKV) by setting it up in a VirtualBox environment on my laptop. I have run into some small issues that might be specific to me (in which case this post is just a personal reminder), or it can be more generic.

My testing environment consists out of a single instance 12c database running on ASM. Before I investigated OKV I already tested with transparent database encryption and the wallet was located in ASM. Therefore the scenario described in the OKV documentation for migrating an existing TDE wallet to Oracle Key Vault applies to me.

Registration of the end-point (database) in OKV went perfectly, I was able to download a jar file and install the OKV software. The jar file writes configuration and also the OKV client software to disk. It is on my open items to investigate what happens if you register a second database on the same server, the way the software and configuration is installed makes me wonder if this will fly in a consolidated environment.

First issue I hit is the action to be performed at bullet 4. Documentation suggests to update the encryption_wallet_location in sqlnet.ora to

ENCRYPTION_WALLET_LOCATION=(SOURCE=(METHOD=HSM)(METHOD_DATA=(DIRECTORY=wallet_location))) 

It turns out you should leave this at the current wallet_location, in my case +DATA. This is required for the migration at step 8 to run successfully.

When you query V$ENCRYPTION_WALLET as suggested in step 6, you actually get two rows returned whereas you only had one row before you configured HSM as source method. I think the documentation could use an example there.

Since I am running on 12c, I can directly pass to step 8 and run the command

ADMINISTER KEY MANAGEMENT SET ENCRYPTION KEY IDENTIFIED BY "<endpoint password>" MIGRATE USING "<wallet password>" WITH BACKUP;

This took me a little longer to work on too. Turns out that you enter an when you register the endpoint. But only if you did not select auto-login. And that is exactly what I did… Only after re-enroling the endpoint I realized that I could have passed null as described in the 11R2 instruction some 2 lines above the 12c instructions. So after re-enroling and setting a password, I was able to migrate the encryption key into the OKV.

Now all that is left is opening up the keystore using the command

ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY "Key_Vault_endpoint_password";

The command execute successfully given the feedback

SQL> ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY Welcome01;

keystore altered.

However when I checked v$encryption_wallet it showed that the wallet was still closed:

SQL> select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
ASM		     CLOSED
HSM		     CLOSED

2 rows selected.

Now this was somewhat annoying. On to the alert.log This showed the following lines

kzthsmcc1: HSM heartbeat check failed to cache
object handle. Error code: 1014
HSM connection lost, closing wallet

Time to hit documentation. And it showed a clue: “Ensure that the ORACLE_BASE environment variable is set before you start the oracle process manually. This is very important.” And important it is indeed. Because without the ORACLE_BASE environment variable OKV cannot find the configuration. And that will break your connection to HSM. So I added ORACLE_BASE to the database configuration in crs:

srvctl setenv database -db saucer -env ORACLE_BASE=/u01/app/oracle

This requires a restart of the database (via srvctl!!!!) and:

SQL> ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY Welcome01;

keystore altered.

SQL> select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
ASM		     CLOSED
HSM		     OPEN

2 rows selected.

So now there is only one problem left: the wallet in ASM still exists and currently has the current keys. OKV documentation does not describe what to do next. My suggestion would be to remove the wallet from ASM and update sqlnet:

ENCRYPTION_WALLET_LOCATION=
 (SOURCE=
   (METHOD=HSM))

Because that would leave the encryption_wallet view in the following state

SQL> select wrl_type, status from v$ENCRYPTION_WALLET;

WRL_TYPE	     STATUS
-------------------- ------------------------------
FILE		     NOT_AVAILABLE
HSM		     OPEN

2 rows selected.

Hope this helps.

Written by Jacco H. Landlust

December 19, 2016 at 12:43 am

storeUserConfig caveats

with 5 comments

While creating a small startup script for nodemanager on my test setup (to prevent me from having to start nodemanager manually all the time) I figured storing the clear text password in the script was a bad practice. Therefore I wanted to use the storeUserConfig command in WLST to store the username and password in a user configuration file and an associated key file.

You would expect that to be not too exciting, but some caveats arose. First you have to connect nodemanager

wls:/offline> nmConnect('nodemanager','Welkom01','wls1.area51.local',5556,'hs_test');
Successfully Connected to Node Manager.

Then you can store the configuration:

wls:/nm/hs_test> storeUserConfig(userConfigFile='/u01/app/oracle/admin/nodemanager/nodemanager.config', userKeyFile='/u01/app/oracle/admin/nodemanager/nodemanager.keyfile');
Currently connected to Node Manager to monitor the domain hs_test.
You will need to be connected to a running WLS or Node Manager to execute this command

mmmm… that was unexpected. Seems you have to pass an extra argument to mention that you are only connected to the nodemanager

storeUserConfig(userConfigFile='/u01/app/oracle/admin/nodemanager/nodemanager.config', userKeyFile='/u01/app/oracle/admin/nodemanager/nodemanager.keyfile',nm='true');
Currently connected to Node Manager to monitor the domain hs_test.
Creating the key file can reduce the security of your system if it is not kept in a secured location after it is created. Do you want to create the key file? y or ny
The username and password that were used for this WebLogic NodeManager connection are stored in /u01/app/oracle/admin/nodemanager/nodemanager.config and /u01/app/oracle/admin/nodemanager/nodemanager.keyfile .

Now that is all cool, next if you should be able to connect to nodemanager without specifying a username and password:

wls:/offline&gt; nmConnect(userConfigFile='/u01/app/oracle/admin/nodemanager/nodemanager.config', userKeyFile='/u01/app/oracle/admin/nodemanager/nodemanager.keyfile', host='wls1.area51.local', port=5556, domainName='hs_test');
Connecting to Node Manager ...
Traceback (innermost last):
File "", line 1, in ?
File "", line 123, in nmConnect
File "", line 648, in raiseWLSTException
WLSTException: Error occured while performing nmConnect : Cannot connect to Node Manager. : Access to domain 'hs_test' for user 'weblogic' denied
Use dumpStack() to view the full stacktrace

Ehhrmm… that sort of sucks. Seems that the username is defaulted to weblogic all of the sudden. Well that sucks, that implies that you cannot use the stored configuration if your username is not weblogic (like in my case). Bummer… (I just hope I am wrong)

Hope this helps.

And thanks to Peter van Nes to learn me how to use the sourcecode setting in wordpress.

Written by Jacco H. Landlust

January 9, 2013 at 1:16 pm

Posted in security, Weblogic

setting mBean attributes after securing OIM with SSL

with 2 comments

When you setup SSL for Oracle Identity Manager, you have to click through a pretty complicated mBean path. Since I am all about scripting deployments, I created a small WLST script that sets the appropriate mBean attributes for me. Creating this script was easier because of one of Edwin Biemond’s posts.

The specific attributes are:

  • OimFrontEndURL: The URL the end-user uses to access the OIM application, usually a VIP on a http-loadbalancer
  • Rmiurl: The URL the OIM application uses to contact SOA over RMI. This is a comma separated list of SOA servers available to OIM
  • Soapurl: The URL on which the OIM application can invoke services on SOA, usually a VIP on a http-loadbalancer

Please keep in mind that you might have to set up mod_wl_ohs on an http server. Also keep in mind that you have to choose the correct ports, in my case default https for OIM and SOA SOAP (with mod_wl_ohs in place) plus 8002 for t3s for SOA RMI.

Anyway, here’s the script (and yet again: sorry for the fubar layout):

connect('weblogic','Welkom01','t3s://oim.area51.local:7002')

domainRuntime()

oimBean = ObjectName('oracle.iam:Location=oim_server1,name=Discovery,type=XMLConfig.DiscoveryConfig,XMLConfig=Config,Application=oim,ApplicationVersion=11.1.1.3.0')
fUrl=Attribute('OimFrontEndURL','https://oim.area51.local')
mbs.setAttribute(oimBean,fUrl)

soaBean = ObjectName('oracle.iam:Location=oim_server1,name=SOAConfig,type=XMLConfig.SOAConfig,XMLConfig=Config,Application=oim,ApplicationVersion=11.1.1.3.0')

soaConfigRmiURL=Attribute('Rmiurl','t3s://oim1.area51.local:8002,t3s://oim2.area51.local:8002')
soaConfigSoapUrl=Attribute('Soapurl','https://oim.area51.local')

mbs.setAttribute(soaBean,soaConfigRmiURL)
mbs.setAttribute(soaBean,soaConfigSoapUrl)

disconnect()

After you have configured SSL correctly, I suggest you also enable the SSL port for OIM. How this can be done I explained here.

P.S. if you would setup OIM on a cluster, you would need to setup these attributes too.

Hope this helps.

Written by Jacco H. Landlust

July 5, 2012 at 9:05 pm

WLST: setup ssl for servers

leave a comment »

Since everyone seems to be posting these cool WLST snippets nowadays, I figured I should share some of my stuff 🙂 Here’s a little script that I wrote to enable SSL for servers. For those of you that don’t know much about SSL for WebLogic yet, Simon Haslam has a great post about it.

Please keep in mind that certain Fusion Middleware products need additional configuration. Also keep in mind that NodeManager needs to be configured for SSL too.

I stole part of the code from David M. Karr, all credits for the parameter parsing should be his. Also I made some assumptions about the keystore name (you can deduct that from the script).

I’m no fulltime jython coder, so please don’t kill me over stupid constructs. Also WordPress should be severely punished for having these broken code tags. Copying the script to vi (or your editor of choice) is easiest.

Finally: please don’t run this script on your production environment without testing it thoroughly first!

#!/bin/python
#

import os, sys, re, getopt
# Usage function
def usage():
     print "Usage: setup_ssl_for_servers.py -u adminuser -c password -t protocol -a adminserver -p port -k path_to_keys -x identityKeyPass -y trustStoreKeyPass -z privateKeyPass"

# Function that sets the keystore and key passphrases
# if SSL is not enabled, it will enable it now
# Also the SSL port is set
def setSSLSettings(serverObj, keypath, identitykey, truststorekey, privatekey):
     cd('/Servers/' + serverObj)
     # Get the relevant information (listen address, port and name)
     strListenAddress=cmo.getListenAddress()
     if strListenAddress == "":
          strListenAddress = java.net.InetAddress.getLocalHost().getHostName();
          print "the listen address of the server is empty, set it to " + str(strListenAddress)
     else:
          print "listen address of the server is : " + strListenAddress
          intListenPort=cmo.getListenPort()
          svrName=cmo.getName()
          # Set the Keystore Information
          cmo.setKeyStores('CustomIdentityAndCustomTrust')
          cmo.setCustomIdentityKeyStoreFileName( keypath + "/" + str(strListenAddress) + '.jks')
          cmo.setCustomIdentityKeyStoreType('JKS')
          set('CustomIdentityKeyStorePassPhrase', identitykey)
          cmo.setCustomTrustKeyStoreFileName(keypath + '/truststore.jks')
          cmo.setCustomTrustKeyStoreType('JKS')
          set('CustomTrustKeyStorePassPhrase', truststorekey)
          # Create SSL Port
          try:
               create(svrName,'SSL')
               cd('SSL/' + svrName )
          except:
               cd('SSL/' + svrName )
          portList = (intListenPort,100)
          cmo.setListenPort(sum(portList))
          print "SSL port was set to " + str(sum(portList))
          cmo.setEnabled(true)
          # Set private key settings
          cmo.setServerPrivateKeyAlias(strListenAddress)
          set('ServerPrivateKeyPassPhrase', privatekey)

# Process parameters
try:
     opts, args = getopt.getopt(sys.argv[1:], "u:c:t:a:p:k:x:y:z:",["adminuser=", "credential=", "adminProtocol=", "adminServer=","adminserverPort=", "keyPath=", "identityKeyPass=","trustStoreKeyPass=", "privateKeyPass="])
except:
     print "unknown argument passed"
     usage()
     sys.exit(2)

# Initialize variables
adminuser=""
credential=""
adminProtocol=""
adminServer=""
adminserverPort=""
identityKeyPass=""
trustStoreKeyPass=""
privateKeyPass=""
keyPath=""

# Get the parameters
for opt, arg in opts:
if opt == "-u":
     adminuser = arg
elif opt == "-c":
     credential = arg
elif opt == "-t":
     adminProtocol = arg
elif opt == "-a":
     adminServer = arg
elif opt == "-p":
     adminserverPort = arg
elif opt == "-k":
     keyPath = arg
elif opt == "-x":
     identityKeyPass = arg
elif opt == "-y":
     trustStoreKeyPass = arg
elif opt == "-z":
     privateKeyPass = arg

# Do some checking on the parameters
if adminuser == "":
     print "Missing \"-u adminuser\" parameter."
     usage()
     sys.exit(2)
elif credential == "":
     print "Missing \"-c password\" parameter."
     usage()
     sys.exit(2)
elif adminProtocol == "":
     print "Missing \"-t adminProtocol\" parameter."
     usage()
     sys.exit(2)
elif adminServer == "":
     print "Missing \"-a adminServer\" parameter."
     usage()
     sys.exit(2)
elif adminserverPort == "":
     print "Missing \"-p adminserverPort\" paramerer."
     usage()
     sys.exit(2)
elif keyPath == "":
     print "Missing \"-k keyPath\" parameter."
     usage()
     sys.exit(2)
elif identityKeyPass == "":
     print "Missing \"-x identityKeyPass\" parameter."
     usage()
     sys.exit(2)
elif trustStoreKeyPass == "":
     print "Missing \"-y trustStoreKeyPass\" parameter."
     usage()
     sys.exit(2)
elif privateKeyPass == "":
     print "Missing \"-z privateKeyPass\" parameter."
     usage()
     sys.exit(2)

print "Got all the required parameters"

# Connect
connectString= str(adminProtocol) + "://" + str(adminServer) + ":" + str(adminserverPort)
connect(adminuser,credential,connectString)

# Start Edit
edit()
startEdit()

# Loop through servers
cd('/Servers')
redirect('/dev/null','false')
servers=ls(returnMap='true')
redirect('/dev/null','true')

for svr in servers:
     # Do some SSL magic
     setSSLSettings( svr, keyPath, identityKeyPass, trustStoreKeyPass, privateKeyPass )

cd('/Clusters')
redirect('/dev/null','false')
clusters=ls(returnMap='true')
redirect('/dev/null','true')

for cls in clusters:
     cd('/Clusters/' + cls)
     # Set replication to secure
     cmo.setSecureReplicationEnabled(true)

# Activate
save()
activate()

Hope this helps.

Written by Jacco H. Landlust

July 2, 2012 at 11:20 pm

Posted in security, Weblogic

Securing embedded ldap access with a connection filter

leave a comment »

Numerous people have written about the embedded ldap (see here). These blog posts show that access to the embedded ldap is always enabled, just the username and password is unknown.

Others have posted about connection filters (see here). A connection filter allows the server to reject unwanted connections based on some filter criteria.

Since the embedded ldap is probe to brute force attacks, one should secure the ldap (and ldaps) port using a connection filter. When constructing the connection filter, you should remember that the managed servers use each others embedded ldap, therefore you should only block remote traffic.

For single server setups this rule would suffice:


0.0.0.0/0 * * deny ldap ldaps

Breakdown:
For all remote IP’s deny access to any server running on any local IP adres and any port for protocols ldap and ldaps

For clustered setups I would advice to allow local addresses in your server backbone and block all remote addresses. If your local server backbone would run on 172.16.X.X these two rules would be applicable:


172.16.0.0/0 * * allow
0.0.0.0/0 * * deny ldap ldaps

Breakdown:
Allow access to any server running on any port for all protocols if the originating IP address is in the 172.16.0.0 range. If the originating IP address is in any other range, deny access to any server running on any port for protocols ldap and ldaps.

Hope this helps.

Written by Jacco H. Landlust

April 11, 2012 at 11:28 am

Posted in security, Weblogic