Monday, November 6, 2023

Transport Layer Security (TLS) Connections without a Client Wallet in Oracle Database 23c

Transport Layer Security (TLS), Oracle Database 23c, Oracle Java Guides, Java Prep, Java Tutorial and Materials, Java Certification, Java Preparation

Operating systems usually have a certificate store containing the root certificates of popular certificate authorities. This allows the operating system to make trusted connections to sites using those root certificates. These certificate stores are kept up to date with operating patches. Oracle 23c allows us to make use of the operating system certificate store, rather than having to use a wallet, which removes the burden of certificate management from us.

◉ Test a URL From the Operating System


The simplest way to test a HTTPS URL is to use the curl command from the operating system command line. If a valid HTTPS connection is possible, we should get a "200 OK" response. We can see it works fine.

$ curl -is https://oracle-base.com/sitemap.xml | grep HTTP
HTTP/1.1 200 OK
$

This means the required root certificate is present in the operating system certificate store.

◉ Create an ACL


In order to do a database callout we need an Access Control List (ACL) for the host. The following example creates an ACL for the host "oracle-base.com" on port 443. The principal is TESTUSER1, which is the user we will make the call from.

conn sys/SysPassword1@//localhost:1521/freepdb1 as sysdba

begin
  dbms_network_acl_admin.append_host_ace (
    host       => 'oracle-base.com', 
    lower_port => 443,
    upper_port => 443,
    ace        => xs$ace_type(privilege_list => xs$name_list('http'),
                              principal_name => 'testuser1',
                              principal_type => xs_acl.ptype_db)); 
end;
/

conn testuser1/testuser1@//localhost:1521/freepdb1

◉ Test a Database Callout Without a Wallet


We create a procedure using the UTL_HTTP package to return the contents of a URL.

create or replace procedure show_html_from_url (
  p_url  in  varchar2
) as
  l_http_request   utl_http.req;
  l_http_response  utl_http.resp;
  l_text           varchar2(32767);
begin
  -- Make a http request and get the response.
  l_http_request  := utl_http.begin_request(p_url);

  l_http_response := utl_http.get_response(l_http_request);

  -- Loop through the response.
  begin
    loop
      utl_http.read_text(l_http_response, l_text, 32766);
      dbms_output.put_line (l_text);
    end loop;
  exception
    when utl_http.end_of_body then
      utl_http.end_response(l_http_response);
  end;
exception
  when others then
    utl_http.end_response(l_http_response);
    raise;
end show_html_from_url;
/

In previous releases attempting to use the procedure without opening a wallet would result in a certificate validation failure. That is not the case in Oracle 23c, as we are using the operating system certificate store by default.

set serveroutput on long 1000000
exec show_html_from_url('https://oracle-base.com/sitemap.xml');

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>

... output removed ...

  <url>
</urlset>

PL/SQL procedure successfully completed.

SQL>

We could have achieved a similar result using HTTPURITYPE.

set serveroutput on long 1000000
select HTTPURITYPE.createuri('https://oracle-base.com/sitemap.xml').getclob();

HTTPURITYPE.CREATEURI('HTTPS://ORACLE-BASE.COM/SITEMAP.XML').GETCLOB()
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>

... output removed ...

  <url>
</urlset>

SQL>

◉ Test a Database Callout With a Wallet


We can still use a wallet containing the relevant root certificate, but once we reference the wallet it takes priority. If the wallet doesn't contain the correct root certificate, the call will fail. To demonstrate this we make a new wallet containing a self-signed certificate, rather than the root certificate of the URL we are calling.

mkdir -p /u01/wallet
orapki wallet create -wallet /u01/wallet -pwd WalletPasswd123 -auto_login

orapki wallet add -wallet /u01/wallet -pwd WalletPasswd123 \
  -dn "CN=`hostname`, OU=Example Department, O=Example Company, L=Birmingham, ST=West Midlands, C=GB" \
  -keysize 1024 -self_signed -validity 365

We connect to a new session, open the wallet, and attempt to run the procedure to make the callout. As expected, this results in a certificate validation failure.

conn testuser1/testuser1@//localhost:1521/freepdb1

set serveroutput on long 1000000
exec utl_http.set_wallet('file:/u01/wallet', null);

exec show_html_from_url('https://oracle-base.com/sitemap.xml');
*
ERROR at line 1:
ORA-29273: HTTP request failed
ORA-06512: at "TESTUSER1.SHOW_HTML_FROM_URL", line 26
ORA-29024: Certificate validation failure
ORA-06512: at "SYS.UTL_HTTP", line 380
ORA-06512: at "SYS.UTL_HTTP", line 1189
ORA-06512: at "TESTUSER1.SHOW_HTML_FROM_URL", line 9
ORA-06512: at line 1
Help: https://docs.oracle.com/error-help/db/ora-29273/

SQL>

We get the same error when we try to use HTTPURITYPE.

conn testuser1/testuser1@//localhost:1521/freepdb1

set serveroutput on
exec utl_http.set_wallet('file:/u01/wallet', null);

select HTTPURITYPE.createuri('https://oracle-base.com/sitemap.xml').getclob();

ERROR:
ORA-29273: HTTP request failed
ORA-06512: at "SYS.HTTPURITYPE", line 38
ORA-29024: Certificate validation failure
ORA-06512: at "SYS.UTL_HTTP", line 380
ORA-06512: at "SYS.UTL_HTTP", line 1189
ORA-06512: at "SYS.HTTPURITYPE", line 23
Help: https://docs.oracle.com/error-help/db/ora-29273/

SQL>

We add the correct certificate to the wallet.

orapki wallet add -wallet /u01/wallet -trusted_cert -cert "/tmp/ISRG Root X1.crt" -pwd WalletPasswd123

Now the previous tests work as expected.

conn testuser1/testuser1@//localhost:1521/freepdb1

set serveroutput on long 1000000
exec utl_http.set_wallet('file:/u01/wallet', null);

exec show_html_from_url('https://oracle-base.com/sitemap.xml');

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>

... output removed ...

  <url>
</urlset>

PL/SQL procedure successfully completed.

SQL>

select HTTPURITYPE.createuri('https://oracle-base.com/sitemap.xml').getclob();

HTTPURITYPE.CREATEURI('HTTPS://ORACLE-BASE.COM/SITEMAP.XML').GETCLOB()
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>

... output removed ...

  <url>
</urlset>

SQL>

Source: oracle-base.com

Related Posts

0 comments:

Post a Comment