Adding self-signed certificates to a wallet became a one-liner in SQLcl 26.1

Before Oracle AI Database 26ai, anyone wanting to make a REST call from the database to an external service needed the external service’s certificate chain to be present in a wallet. The same applied to any other network call.

This situation has greatly improved: Oracle Database releases 19c and 26ai trust the operating system’s certificate store. In other words, if you can access a web resource from curl and it doesn’t complain about an insecure connection, you’re good to access the same resource from the database. This is great news and the subject of an earlier article.

Sometimes this isn’t enough though. For example, if you deployed an Oracle REST Data Services (ORDS) server in your internal network and force TLS connectivity based on self-signed certificates, chances are that your browser/the operating system doesn’t trust the self-signed certificate. As a result, REST calls from the database still require a wallet.

This is of course just one of many examples, there are many more.

Let’s make this more concrete

OK, this sounds abstract, let’s demonstrate the concept with an example. Here’s an excerpt from my compose file that starts ORDS:

YAML
services:
oracle:
image: docker.io/gvenzl/oracle-free:23.26.1
...
ords:
depends_on:
oracle:
condition: service_healthy
image: container-registry.oracle.com/database/ords:25.4.0
environment:
DBHOST: oracle
DBPORT: 1521
DBSERVICENAME: freepdb1
ORACLE_PWD: ${ORACLE_PASSWORD:?Please provide a password for the Oracle DBA accounts}
DEBUG: FALSE
FORCE_SECURE: TRUE
JDK_JAVA_OPTIONS: "-Xms1024M -Xmx1024M"
networks:
- backend
ports:
- 8080:8080
- 8443:8443
- 27017:27017
volumes:
- ords-config-vol:/etc/ords/config
- ./certs:/etc/ords/config/ssl:Z

The most important bit can be found in line 17: secure communication is enforced. The directive in line 27 maps the (local) certs directory containing the self-signed certificate and key into the required location within the ORDS container. You can read more about the ORDS container image and its configuration options in the docs.

If you try to access any ORDS-related resource without any additional configuration steps, you will fail:

$ curl https://ords:8443/ords/emily/t1/
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

This is expected. The same is true if you try to access the resource from the database. The URI targets a REST-enabled table, named t1.

SQL
create or replace function fetch_me_if_you_can
return JSON
as mle language javascript
{{
await import ("mle-js-fetch");
const response = await fetch('https://ords:8443/ords/emily/t1/');
if (response.ok) {
const data = await response.json();
return data;
} else {
throw new Error(
`unexpected network error: ${response.status}`
);
}
}};
/
SQL> select
2* fetch_me_if_you_can;
Error starting at line : 1 in command -
select
fetch_me_if_you_can
Error report -
ORA-04161: TypeError: ORA-29024: Certificate validation failure

Same problem … the certificate isn’t trusted by the database. Which is a good thing and exactly what you want.

By the way, the code you see in the example above demonstrates how easy it is to use the popular JavaScript fetch (web) API in Oracle AI Database 26ai. You may also have to call DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE() to allow outgoing network traffic in the first place.

So how do we fix this?

Just as before Oracle AI Database 26ai, in situations like this you require a wallet to enable network connection backed by the self-signed certificate. Thankfully that process has been greatly simplified with SQLcl version 26.1.0. It’s orapki command now allows you to create a wallet and add a (self-signed) certificate in 2 simple steps.

The following commands are executed on the database server. SQLcl 26.1.0 has been installed and configured.

SQL
$ /opt/oracle/sqlcl/bin/sql /nolog
SQLcl: Release 26.1 Production on Thu Apr 09 21:40:34 2026
Copyright (c) 1982, 2026, Oracle. All rights reserved.
SQL> orapki wallet create -wallet /opt/oracle/mywallet -auto_login_local -pwd <your password>
Oracle PKI Tool Release 23.0.0.0.0 - Production
Version 23.0.0.0.0
Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved.
Operation is successfully completed.
SQL> orapki wallet add -wallet /opt/oracle/mywallet -trusted_cert -from_uri https://ords:8443 -pwd <your password>
Downloading certificates from https://ords:8443 ...
Found 1 certificate(s) in the chain.
[1/1] Adding: CN=ords,O=acme,L=Frankfurt,ST=RPL,C=DE
Added successfully.
Done. 1 of 1 certificate(s) added to wallet at /opt/oracle/mywallet

That’s it! The command in line 7 creates the wallet. The command on line 15 adds the certificate to the wallet. And that’s all there is to do.

Let’s verify that this actually works

Next, let’s use the wallet and check if worked. Connect to the database, set the wallet path, and re-run the fetch call.

SQL
SQL> exec utl_http.set_wallet('file:/opt/oracle/mywallet', 'your password')
PL/SQL procedure successfully completed.
SQL> select
2* fetch_me_if_you_can;
FETCH_ME_IF_YOU_CAN
----------------------------------------------------------------------------
{"items":[{"modified_vsnid":null,"last_ddl_time":"2026-01-17T03:00:42Z"

Many more rows were returned but are omitted here. The main point is that you can successfully access the REST endpoint.

Summary

SQLcl 26.1 and later add a super useful option to pull a certificate (chain, if needed) from a URI and add it into an existing wallet. No more exporting browser certificates from a workstation, ensuring they are in the correct format, installing the database client, finding orapki, and so on and so forth. SQLcl is all you need.

Accessing REST endpoints protected by self-signed certificates just got a lot easier if you need them. In many cases you are probably better off relying on certificates signed by trustworthy CAs. Until then, this is a very welcome simplification.