Using the Operating System's certificate store instead of an Oracle wallet in Oracle Database 23c

September 26, 2023 | 4 minute read
Text Size 100%:

Both network and file I/O are a security-sensitive affair. Therefore you cannot simply write to a file, or open a network connection in Oracle Database without doing some setup work up front. Developers wishing to perform network I/O via UTL_HTTP for example must define fine-grained access control settings. Or rather, ask the administrator to perform this operation for them. For network I/O this includes the definition of an Access Control Entry (ACE) by calling DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE().

In case the web-resource to be consumed requires the use of Transport Layer Security (TLS) the addition of the web-resource’s certificate to an Oracle wallet was needed all the way up to Oracle Database 23c. That is, unless you are on Autonomous Database where the friendly engineers provide lots of certificates in the wallet.

Oracle Database 23c Free does away with the requirement to store the certificate in a wallet. Provided the web-service you are connecting to is “trusted” by the operating system, the connection process is greatly simplified. How can you tell? A low-tech solution is to point cURL to the URI you want to connect to. If it doesn’t complain about an unknown certificate, you are most likely fine. Oh and don’t specify the --insecure option, that’s cheating.

You need to be aware of all security and compliance related restrictions for your database. Network I/O is a very sensitive matter and Oracle disables it by default for good reason. Always consult the security, compliance or any other team responsible for that area before deciding on performing network I/O with the database. Have the solution vetted, verified, certified and rubber stamped by the experts in your organisation before even thinking of deploying it. It’s better to be safe than sorry.

Setup

With the warnings out of the way, let’s give the new way of doing things in Oracle Database 23c a try. I’d like to use api.ipify.org to get my current IP address in JSON format. I haven’t found a simpler, more accessible web service to use, it’s not super complex but should be sufficient to demonstrate the concept.

This is what it looks like when you invoke the web service via curl on the command line:

$ curl 'https://api.ipify.org/?format=json'
{"ip":"1.2.3.4"}

No complaint about the certificate from cURL, Oracle should allow me to access that URL as well, using the operating system’s certificate store. I had to allow the developer (demouser) to perform network I/O against this web service first. As per the introduction, this is done by appending an Access Control Entry (ACE) to an Access Control List (ACL). For example:

BEGIN
    DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
        host => 'api.ipify.org',
        ace  =>  xs$ace_type(
            privilege_list => xs$name_list('http'),
            principal_name => 'DEMOUSER',
            principal_type => xs_acl.ptype_db
        )
    );
END;
/

This anonymous PL/SQL block, to be executed by a privileged account, grants demouser the right to issue HTTP requests against api.ipify.org.

Example using UTL_HTTP

The following example demonstrates how to perform a simple lookup using UTL_HTTP.REQUEST to fetch my IP address:

SQL> select
  2    json_serialize(
  3      utl_http.request('https://api.ipify.org/?format=json')
  4      pretty
  5    ) as my_ip_address;

MY_IP_ADDRESS    
________________ 
{
  "ip":"1.2.3.4"
}

I previously established that my operating system trusts api.ipify.org, so there wasn’t an issue reading from it. Note that you can set the wallet_path to system: (including the colon) in most functions/procedures in UTL_HTTP if you want, although it’s not needed.

Example using In-Database JavaScript

Oracle Database 23c Free features Multilingual Engine (MLE), powered by GraalVM. This new feature allows developers to use JavaScript as the database’s third server-side programming language, alongside PL/SQL and Java.

The JavaScript fetch API provides a very popular way for reading information from remote sources. The above call to UTL_HTTP.REQUEST can be written as follows in JavaScript:

create or replace function fetch_me_if_you_can
return JSON
as mle language javascript
q'~
    await import ("mle-js-fetch");
    const response = await fetch('https://api.ipify.org/?format=json');
    if (response.ok) {
        const data = await response.json();
        return data;
    } else {
        throw new Error(
          'unexpected network error trying to query the web server'
        );
    }
~';
/

The above code snippet creates a new function in my schema that I can query next:

SQL> select
  2    json_serialize(
  3      fetch_me_if_you_can
  4      pretty
  5    ) as my_ip_address;

MY_IP_ADDRESS    
________________ 
{
  "ip":"1.2.3.4"
}

It's as simple as that.

Summary

The use of the operating system’s certificate store is a great productivity booster, at least in my opinion. Instead of having to create a wallet to access TLS-protected web resources, you can rely on the operating system’s certificate store instead.

Martin Bach

Martin is a product manager at Oracle helping customers in Europe and around the world address their IT related problems. He is most interested in cloud technology, DevOps and how these can be used best with Oracle technology.


Previous Post

Building a Multi-Tenant Application using Spring Boot, Hibernate with Oracle JDBC/UCP

Bidyadhar Mohanty | 12 min read

Next Post


How to create and RSA sign a JWT in NetSuite to consume an external OAuth2 service

Wilman Arambillete | 5 min read