If you're developing for the web (or something else) and you need to connect to an Oracle database, such as an Oracle Autonomous Database that comes for free with oracle cloud free tier, you may run to the typical problem of storing db connection credentials in configuration files and scripts. Nevertheless, Oracle has, since ages, a functionality called Oracle Wallet that can help you manage these connections more securely. Keep in mind that Oracle migrates away from Wallets, but my understanding is that this is a response to usability concerns, as the security standard is not maintained in the new set-up.
An Oracle Wallet is a container that stores authentication and signing credentials and in short, can be used by your application to retrieve the authentication credentials needed to access your database. You can create a Wallet from scratch, or you can download one from your Database's configuration page, which is the suggested way.
Adding Credentials in a Wallet
Although a Wallet can store multiple types of credentials, I'll focus on the most common use case (in my oppinion) which is a typical username / password pair that provides access to the database.
Important files
After you download the Wallet, you will see multiple files in there, but there are four files involved in that process:
tnsnames.ora
People familiar with Oracle databases know that this is where the connection definitions are. You need to take notice of the first part in the entries you want to access using the wallet; the connection name. In the case of autonomous databases in the oracle cloud, multiple names are defined based on their priority (low, high etc). If you create a database, it will be named as dbYYYYMMDDXXXX with XXXX being some random numbers (and potentially more digits of course).
For this post, I will use the fictional name db20220205X
sqlnet.ora
In this file you define some parameters for network applications; the important line for this case is this:
WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="?/network/admin")))
in the "DIRECTORY" setting, you need to write the location where the two wallet files will be found.
eWallet.p12 and cwallet.sso
These are the actual wallet files, and the data is registered in these.
Executing the commands
That should be easy, right? Well, yes, with the exception that if you want to add credentials to the files, you cannot. You need a "special" command from Oracle named mkstore, which, for some reason that I don't know, cannot be found anywhere to be downloaded. A huge mistake I think, but a different subject altogether. In reality it's just three libraries that are freely available: You need the files oraclepki.jar, osdt_core.jar and osdt_cert.jar. In my tests, I have found these to be enough for all switches of the mkstore utility. You can download these here, and to use them, you just call them. I prefer writing simple scripts, so here is a small sample one for linux - modify for your environment:
#!/usr/bin/env bash
LIBPATH=/opt/oracle/lib
PKI=$LIBPATH/oraclepki.jar
OSDT_CORE=$LIBPATH/osdt_core.jar
OSDT_CERT=$LIBPATH/osdt_cert.jar
/usr/bin/java -cp $PKI:$OSDT_CORE:$OSDT_CERT oracle.security.pki.OracleSecretStoreTextUI "$@"
Call it mkstore, make it executable, and you're good to go:
Let's say you extracted the Wallet zip file in the directory ~/oracle, in that case adding credentials for the user prod_user to access the database that is defined with the connection string db20220205X_high, is as easy as:
mkstore -wrl ~/oracle -createCredential db20220205X_high prod_user password_for_prod_user
When you downloaded the Wallet, you were asked for a password. All modifications of the Wallet, such as addition and deletions of credentials, but also the listing of existing credentials, will require this password.
You can list the credential sets you have stored in the wallet (but not the credentials themselves) with:
mkstore -wrl ~/oracle -listCredential
As you can imagine, one may add more credentials to this wallet. Such as for example credentials for a test schema in the same database.
mkstore -wrl ~/oracle -createCredential db20220205X_low dev_user password_for_dev_user
If your test database is in a different server altogether (as it should be in proper environments), you can merge the TNSNAMES.ORA files you receive, while keeping one wallet.
Creating a Wallet from Scratch
In case you do not want to download the Wallet or do not have a Wallet already, which as a reminder are just the files ewallet.p12 and cwallet.sso, you can just create the wallet using the same libraries.
mkstore -wrl ~/oracle -create
One last thing
An Oracle Wallet has some interesting functionality. By default, the wallet one can download from the Oracle Cloud database, as well as any wallet that is created manually, is created to allow auto login. Meaning, you don't have to provide a password to open the wallet, or to login to the database. One can understand why this is troublesome, as the simple copy of the wallet would allow anyone to login to the database, without knowing the password.
Local user only
A small little fact, is that Oracle Wallet supports what is known as auto_login_local. In this mode, the wallet can be used only on the same machine where it was created, and only from the same user. Typical security minds will state that if one renames their machine and uses the same username, this limitation is bypassed. I agree, nevertheless it's a nifty little improvement.
But how do you convert the downloaded Wallet to be auto_login_local? With the undocumented feature that you can, actually, use the create command to modify a wallet.
mkstore -wrl ~/oracle -createLSSO
There are three modes of create and, as far as I know, they all create auto login wallets:
- The one is createSSO (which is the default, and is the one used when one calls "create"). This mode creates an auto login wallet that can be copied everywhere, can be used by anyone, but cannot be modified without its password.
- The second one is createLSSO which creates wallets that auto login, by the same user in the same machine. This, too, cannot be modified without its password.
- The third option is createALO which is supposed to create a Wallet that can be even modifed without a password, but the conversion from a LSSO or a SSO wallet to an ALO doesn't work.
You need not worry, the createLSSO switch doesn't mess up with your existing wallet, it just "transforms" it to auto_login_local. Switching back to auto_login (i.e., anyone in any machine), you can just run the command.
mkstore -wrl ~/oracle -createSSO
Security considerations
If you wonder if wallets are secure, there are multiple ways to look at it. Wallets store the passwords in a container that is triple-des encrypted. Not bad, not the best option either. A conversion to use AES instead is possible, but requires a different script with some additional libraries so I'll skip this.
The major concern of course is the auto_login_local reliance on username and machine name, and indeed, this is evidently bypassable. Obviously proper O/S level access control rules are useful but they should be there anyway, regardless of the auto_login_local.
Finally, we need to keep in mind that an auto_login wallet (local or not) is opened without a password, so if one writes an application to use this wallet for connection, at some point this someone will have a way to extract the credentials.
All these are valid concerns, but they raise the attack complexity and this is always a good thing. Comparing to storing credentials in configuration files, I believe this is a far better option.