6

I want to connect to an Oracle database using a wallet stored in memory instead of having the wallet stored on disk.

I tried using Apache Common VFS to read/write files in memory. The wallet is written to memory (to be sure I even wrote the wallet folder from the ram to my disk).

properties.put("oracle.net.tns_admin", "ram://my_wallet");
properties.put("oracle.net.wallet_location",
          String.format("(SOURCE=(METHOD=file)(METHOD_DATA=(DIRECTORY=%s)))", "ram://my_wallet"));

When I try to make a connection using those properties I get the error:

java.sql.SQLRecoverableException: IO Error: could not resolve the connect identifier DB_1222

PS: My code works fine if I put the wallet on disk.

Michiel Haisma
  • 786
  • 6
  • 17
Nabila
  • 191
  • 4
  • 19
  • There is no adapter from the VFS API to java.io.File, so Oracle which does not know about VFS FileObjects can’t use those URLs. I am not sure if Oracle can read resources from the class loader, then you could provide them with one which does that interface. I am also not sure if Oracle can read from URLConnection, but the same applies, it’s normally not provided by VFS. Funny site note, when you use oracles sqlcl tool which has a option to read wallet ZIPs it will expand them to a temp directory and pass that to the tnsadmin parameter in the URL. – eckes Nov 05 '20 at 21:50

4 Answers4

2

One workaround might be to leverage in-memory file-system support of the OS, so it looks like a normal file to JDBC but the OS is actually storing it in memory. On Unix-like systems, tmpfs would be such a file-system: https://en.m.wikipedia.org/wiki/Tmpfs

Korbi
  • 1,438
  • 4
  • 15
  • 22
2

I know this is an old question but you can now set a SSLContext to an OracleDatasource and have the context read the wallet from any input stream:

        TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyManagerFactory keyManagerFactory =
                KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        KeyStore keyStore = KeyStore.getInstance("SSO", new OraclePKIProvider());


        // ** Read wallet in-memory here **
        keyStore.load(new ByteArrayInputStream(your_wallet_in_memory), null);


        keyManagerFactory.init(keyStore, null);
        trustManagerFactory.init(keyStore);

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(
                keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

        Properties info = new Properties();

        info.put(OracleConnection.CONNECTION_PROPERTY_USER_NAME, userName);
        info.put(OracleConnection.CONNECTION_PROPERTY_PASSWORD, userPassword);

        OracleDataSource ods = new OracleDataSource();
        ods.setURL(dbUrl);
        ods.setConnectionProperties(info);
        ods.setSSLContext(sslContext);

I have posted a Sample Service using that approach as well as tests using different types of wallets in this repo: https://github.com/nomisvai/oracle-in-memory-wallet-samples

Simon V
  • 21
  • 1
  • I can confirm this approach definitely works. I replaced the "your_wallet_in_memory" with raw bytes from a wallet file (e.g. "wallet.sso") and the "dbUrl" with something like "jdbc:oracle:thin:@tcps://server:1522/service" – Peter Jan 24 '23 at 00:38
0

Unfortunately, the Oracle JDBC does not currently support getting the wallet from memory.

Kuassi Mensah
  • 274
  • 1
  • 4
0

I have written a blog on this topic... https://dzone.com/articles/how-to-use-vaults-and-wallets-for-simple-secure-connectivity

A number of frameworks now have convenience features to bring the wallet folder in memory particularly for the OCI autonomous database case where you can dynamically download the wallet, allowing for rotation, etc. which are nice from a manageability and security viewpoint.

Eg in Helidon...

oracle:
  ucp:
    jdbc:
      PoolDataSource:
        atp:
          connectionFactoryClassName: oracle.jdbc.pool.OracleDataSource
          userName: "ADMIN"
          password: "HelidonATP123"
          serviceName: "helidonatp"
oci:
  atp:
    ocid: "ocid1.autonomousdatabase.oc1.iad.anuwasdfasfdasdfasdfadfcebvb5ehmxlu22xpfwq"
    walletPassword: HelidonTest1

and in Micronaut...

micronaut:
  config-client:
    enabled: true
oci:
  config:
    profile: DEFAULT 
  vault:
    config:
      enabled: true
    vaults:
      - ocid: ocid1.vault..aaaaaaaatafcasdfadf3xq24hbqvq
        compartment-ocid: ocid1.compartment.oc1..aaaaaaaatafcasdasdfasdfrzwzjxgn3xq24hbqvq