How to Allow Network Access with DBMS_NETWORK_ACL_ADMIN

Allow a database user to reach specific hosts and ports for HTTP, connections, or name lookups, and fix ORA-24247.

PL/SQL network packages such as UTL_HTTP, UTL_TCP, UTL_SMTP, and UTL_INADDR cannot reach any host until a DBA allows it. Access control entries, added with DBMS_NETWORK_ACL_ADMIN, name the user, the host, the ports, and the kind of access. Without one, calls fail with ORA-24247.

Code for This Guide

The main examples are in the examples/pkg-files-network folder of the Oracle Database 26ai code repository on GitHub, each with its output. They use NIMBUS, the sample schema of a fictional airline, which you can install with the scripts in the setup/nimbus folder.

They come from Oracle Database 26ai SQL and PL/SQL Book.

Syntax

dbms_network_acl_admin.append_host_ace(
  host       => 'host name, IP address, or wildcard',
  lower_port => null, upper_port => null,      -- null: all ports
  ace        => xs$ace_type(privilege_list => xs$name_list('http'),
                            principal_name => 'USER',
                            principal_type => xs_acl.ptype_db));

The privileges are http for UTL_HTTP, connect for UTL_TCP, UTL_SMTP, and UTL_MAIL, and resolve for name lookups with UTL_INADDR.

Grant Access to NIMBUS

Run this as a DBA, such as SYS, in the pluggable database. It allows HTTP and plain connections to a local test server on ports 8099 and 2525, HTTP to example.com, and name lookups for every host.

Example:

begin
  -- HTTP to the test server, and to example.com over HTTPS
  dbms_network_acl_admin.append_host_ace(
    host => 'host.docker.internal', lower_port => 8099, upper_port => 8099,
    ace  => xs$ace_type(privilege_list => xs$name_list('http'),
                        principal_name => 'NIMBUS', principal_type => xs_acl.ptype_db));
  dbms_network_acl_admin.append_host_ace(
    host => 'example.com',
    ace  => xs$ace_type(privilege_list => xs$name_list('http'),
                        principal_name => 'NIMBUS', principal_type => xs_acl.ptype_db));
  -- plain TCP connections (UTL_TCP, UTL_SMTP, UTL_MAIL) to the test server's ports
  dbms_network_acl_admin.append_host_ace(
    host => 'host.docker.internal', lower_port => 2525, upper_port => 2525,
    ace  => xs$ace_type(privilege_list => xs$name_list('connect'),
                        principal_name => 'NIMBUS', principal_type => xs_acl.ptype_db));
  dbms_network_acl_admin.append_host_ace(
    host => 'host.docker.internal', lower_port => 8099, upper_port => 8099,
    ace  => xs$ace_type(privilege_list => xs$name_list('connect'),
                        principal_name => 'NIMBUS', principal_type => xs_acl.ptype_db));
  -- name lookups (UTL_INADDR) for any host
  dbms_network_acl_admin.append_host_ace(
    host => '*',
    ace  => xs$ace_type(privilege_list => xs$name_list('resolve'),
                        principal_name => 'NIMBUS', principal_type => xs_acl.ptype_db));
end;
/
select host, lower_port as lport, upper_port as uport, privilege
from   dba_host_aces
where  principal = 'NIMBUS'
order  by host, privilege;

Output:

PL/SQL procedure successfully completed.

HOST                       LPORT    UPORT PRIVILEGE
_______________________ ________ ________ ____________
*                                         RESOLVE
example.com                               HTTP
host.docker.internal        8099     8099 CONNECT
host.docker.internal        2525     2525 CONNECT
host.docker.internal        8099     8099 HTTP

DBA_HOST_ACES lists the five entries. The test server is the small Node.js program setup/netlab/server.mjs in the repository, which the database container reaches as host.docker.internal.

Check Access as the User

Users see their own entries in USER_HOST_ACES. DBMS_NETWORK_ACL_UTILITY.DOMAINS lists every host pattern that would match a host name, from the most specific to *.

Example:

select host, lower_port, upper_port, privilege, status from user_host_aces order by 1, 4;

select column_value as matching_acl_hosts
from   dbms_network_acl_utility.domains('api.flights.example.com');

Output:

HOST                       LOWER_PORT    UPPER_PORT PRIVILEGE    STATUS
_______________________ _____________ _____________ ____________ __________
*                                                   RESOLVE      GRANTED
example.com                                         HTTP         GRANTED
host.docker.internal             8099          8099 CONNECT      GRANTED
host.docker.internal             2525          2525 CONNECT      GRANTED
host.docker.internal             8099          8099 HTTP         GRANTED

MATCHING_ACL_HOSTS
__________________________
api.flights.example.com
*.flights.example.com
*.example.com
*.com
*

Access Denied

Example:

-- port 8100 has no access control entry for NIMBUS
select utl_http.request('http://host.docker.internal:8100/') from dual;

Output:

Error starting at line : 2
In command -
select utl_http.request('http://host.docker.internal:8100/') from dual
Error at Command Line : 2 Column : 8
Error report -
SQL Error: ORA-29273: HTTP request failed
ORA-06512: at "SYS.UTL_HTTP", line 1594
ORA-24247: network access denied by access control list (ACL)
ORA-06512: at "SYS.UTL_HTTP", line 380
ORA-06512: at "SYS.UTL_HTTP", line 1534
ORA-06512: at line 1

Port 8100 is not in any entry for NIMBUS, so the request fails with ORA-24247 inside ORA-29273.

Things to Know

  • Grant the narrowest access that works: one host, the ports needed, and only the privileges used.
  • The most specific matching host entry decides, so an entry for api.example.com takes precedence over *.example.com.
  • REMOVE_HOST_ACE takes an entry away again.

Related Guides

Conclusion

DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE opens specific hosts and ports to specific users for HTTP, connections, or name lookups. Grant as little as possible, and check what a user can reach in USER_HOST_ACES.

Get more Vinish.dev tutorials on Google

See my articles more often when you search Google.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted