Oracle EXPDP/IMPDP und NetACLs von Applikationen

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.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

This site uses Akismet to reduce spam. Learn how your comment data is processed.