Was sind NetACLs überhaupt?
Bei Oracle können Applikationen aus der Oracle Datenbank heraus Verbindungen herstellen, beispielsweise um eine eMail zu versenden oder Informationen von Webservern oder anderen Datenquellen direkt abzurufen. Damit nicht jede Applikation beliebige Zugriffe machen kann, werden NetACLs angelegt. Man kann sich diese als so eine Art Firewall-Regeln für ausgehende (aus der Datenbank heraus) Verbindungen vorstellen.
War ist das Problem beim Oracle EXPDP/IMPDP mit den NetACLs?
Oracle EXPDP nimmt die NetACL-Definitionen nicht mit, weil diese im Schema SYS angelegt sind. Aus diesem Grund müssen die entsprechenden Informationen aus der Quell (EXPDP) Datenbank ausgelesen und in der Ziel (IMPDP) Datenbank wieder eingespielt werden.
Mit folgendem Script kann man auslesen, ob es NetACLs gibt, die in der Datenbank definiert sind.
sqlplus / as sysdba
set pages 300 lines 200 tab off
col acl for a50
col host for a30
col acl_owner for a12
set lines 200 pages 300
col acl for a50
col principal for a20
col start_date for a15
col end_date for a15
col privilege for a30
select HOST, ACL, ACL_OWNER
from dba_network_acls;
SELECT acl
, principal
, privilege
, is_grant
FROM dba_network_acl_privileges;
exit;
Hier ein Beispielergebnis einer Oracle 19c Datenbank:
HOST ACL ACL_OWNER
--------- ---------------------------------------------- ---------
localhost /sys/acls/oracle-sysman-ocm-Resolve-Access.xml SYS
* NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7 SYS
ACL PRINCIPAL PRIVILE IS_G
---------------------------------------------- ----------------- ------- ----
NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7 GSMADMIN_INTERNAL resolve true
NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7 GGSYS resolve true
/sys/acls/oracle-sysman-ocm-Resolve-Access.xml ORACLE_OCM resolve true
Die hier gefundenen NetACLs sind keine ACLs von Applikationen, sondern lediglich die von Oracle selbst angelegten. Die brauchen nicht übernommen werden, da sie beim Anlegen der Datenbank schon erzeugt wurden.
Sollten NetACLs für Applikationen angelegt worden sein, können die mit Hilfe des folgenden SQLPLUS Script ausgelesen werden. Das Script erzeugt dabei gleich die benötigten CREATE Statements.
sqlplus / as sysdba
SET SERVEROUTPUT ON FORMAT WRAPPED LINESIZE 300
DECLARE
l_last_acl dba_network_acls.acl%TYPE := '~';
l_last_principal dba_network_acl_privileges.principal%TYPE := '~';
l_last_privilege dba_network_acl_privileges.privilege%TYPE := '~';
l_last_host dba_network_acls.host%TYPE := '~';
FUNCTION get_timestamp (p_timestamp IN TIMESTAMP WITH TIME ZONE)
RETURN VARCHAR2
AS
l_return VARCHAR2(32767);
BEGIN
IF p_timestamp IS NULL THEN
RETURN 'NULL';
END IF;
RETURN 'TO_TIMESTAMP_TZ(''' || TO_CHAR(p_timestamp, 'DD-MON-YYYY HH24:MI:SS.FF TZH:TZM') || ''',''DD-MON-YYYY HH24:MI:SS.FF TZH:TZM'')';
END;
BEGIN
FOR i IN (SELECT a.acl,
a.host,
a.lower_port,
a.upper_port,
b.principal,
b.privilege,
b.is_grant,
b.start_date,
b.end_date
FROM dba_network_acls a
JOIN dba_network_acl_privileges b ON a.acl = b.acl
ORDER BY a.acl, a.host, a.lower_port, a.upper_port)
LOOP
IF l_last_acl <> i.acl THEN
-- First time we've seen this ACL, so create a new one.
l_last_host := '~';
DBMS_OUTPUT.put_line('-- ---------------------------------------------');
DBMS_OUTPUT.put_line('-- ' || i.acl);
DBMS_OUTPUT.put_line('-- ---------------------------------------------');
DBMS_OUTPUT.put_line('BEGIN');
DBMS_OUTPUT.put_line(' DBMS_NETWORK_ACL_ADMIN.drop_acl (');
DBMS_OUTPUT.put_line(' acl => ''' || i.acl || ''');');
DBMS_OUTPUT.put_line(' COMMIT;');
DBMS_OUTPUT.put_line('END;');
DBMS_OUTPUT.put_line('/');
DBMS_OUTPUT.put_line(' ');
DBMS_OUTPUT.put_line('BEGIN');
DBMS_OUTPUT.put_line(' DBMS_NETWORK_ACL_ADMIN.create_acl (');
DBMS_OUTPUT.put_line(' acl => ''' || i.acl || ''',');
DBMS_OUTPUT.put_line(' description => ''' || i.acl || ''',');
DBMS_OUTPUT.put_line(' principal => ''' || i.principal || ''',');
DBMS_OUTPUT.put_line(' is_grant => ' || i.is_grant || ',');
DBMS_OUTPUT.put_line(' privilege => ''' || i.privilege || ''',');
DBMS_OUTPUT.put_line(' start_date => '||get_timestamp(i.start_date)|| ',');
DBMS_OUTPUT.put_line(' end_date => '||get_timestamp(i.end_date)|| ');');
DBMS_OUTPUT.put_line(' COMMIT;');
DBMS_OUTPUT.put_line('END;');
DBMS_OUTPUT.put_line('/');
DBMS_OUTPUT.put_line(' ');
l_last_acl := i.acl;
l_last_principal := i.principal;
l_last_privilege := i.privilege;
END IF;
IF l_last_principal <> i.principal
OR (l_last_principal = i.principal AND l_last_privilege <> i.privilege) THEN
-- Add another principal to an existing ACL.
DBMS_OUTPUT.put_line('BEGIN');
DBMS_OUTPUT.put_line(' DBMS_NETWORK_ACL_ADMIN.add_privilege (');
DBMS_OUTPUT.put_line(' acl => ''' || i.acl || ''',');
DBMS_OUTPUT.put_line(' principal => ''' || i.principal || ''',');
DBMS_OUTPUT.put_line(' is_grant => ' || i.is_grant || ',');
DBMS_OUTPUT.put_line(' privilege => ''' || i.privilege || ''',');
DBMS_OUTPUT.put_line(' start_date => '|| get_timestamp(i.start_date)||',');
DBMS_OUTPUT.put_line(' end_date => '|| get_timestamp(i.end_date)||');');
DBMS_OUTPUT.put_line(' COMMIT;');
DBMS_OUTPUT.put_line('END;');
DBMS_OUTPUT.put_line('/');
DBMS_OUTPUT.put_line(' ');
l_last_principal := i.principal;
l_last_privilege := i.privilege;
END IF;
IF l_last_host <> i.host||':'||i.lower_port||':'||i.upper_port THEN
DBMS_OUTPUT.put_line('BEGIN');
DBMS_OUTPUT.put_line(' DBMS_NETWORK_ACL_ADMIN.assign_acl (');
DBMS_OUTPUT.put_line(' acl => ''' || i.acl || ''',');
DBMS_OUTPUT.put_line(' host => ''' || i.host || ''',');
DBMS_OUTPUT.put_line(' lower_port => '||NVL(TO_CHAR(i.lower_port),'NULL') || ',');
DBMS_OUTPUT.put_line(' upper_port => '||NVL(TO_CHAR(i.upper_port),'NULL') || ');');
DBMS_OUTPUT.put_line(' COMMIT;');
DBMS_OUTPUT.put_line('END;');
DBMS_OUTPUT.put_line('/');
DBMS_OUTPUT.put_line(' ');
l_last_host := i.host||':'||i.lower_port||':'||i.upper_port;
END IF;
END LOOP;
END;
/
EXIT
Der das Ergebnis aus der gleichen Datenbank:
-- -------------------------------------------------
-- /sys/acls/oracle-sysman-ocm-Resolve-Access.xml
-- -------------------------------------------------
BEGIN
DBMS_NETWORK_ACL_ADMIN.drop_acl (
acl => '/sys/acls/oracle-sysman-ocm-Resolve-Access.xml');
COMMIT;
END;
/
BEGIN
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => '/sys/acls/oracle-sysman-ocm-Resolve-Access.xml',
description => '/sys/acls/oracle-sysman-ocm-Resolve-Access.xml',
principal => 'ORACLE_OCM',
is_grant => true,
privilege => 'resolve',
start_date => NULL,
end_date => NULL);
COMMIT;
END;
/
BEGIN
DBMS_NETWORK_ACL_ADMIN.assign_acl (
acl => '/sys/acls/oracle-sysman-ocm-Resolve-Access.xml',
host => 'localhost',
lower_port => NULL,
upper_port => NULL);
COMMIT;
END;
/
-- -------------------------------------------------
-- NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7
-- -------------------------------------------------
BEGIN
DBMS_NETWORK_ACL_ADMIN.drop_acl (
acl => 'NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7');
COMMIT;
END;
/
BEGIN
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => 'NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7',
description => 'NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7',
principal => 'GGSYS',
is_grant => true,
privilege => 'resolve',
start_date => NULL,
end_date => NULL);
COMMIT;
END;
/
BEGIN
DBMS_NETWORK_ACL_ADMIN.assign_acl (
acl => 'NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7',
host => '*',
lower_port => NULL,
upper_port => NULL);
COMMIT;
END;
/
BEGIN
DBMS_NETWORK_ACL_ADMIN.add_privilege (
acl => 'NETWORK_ACL_86B64B66DF95012EE053F706E80A06B7',
principal => 'GSMADMIN_INTERNAL',
is_grant => true,
privilege => 'resolve',
start_date => NULL,
end_date => NULL);
COMMIT;
END;
/
Daraus brauchen jetzt nur noch die benötigten NetACLs heraus genommen und in der Ziel Datenbank eingespielen werden.