Netzwerkzugriffe mit Application Express und Oracle11g

Im Rahmen dieser Community wurden schon des öfteren Tipps vorgestellt, in welchen die Application Express-Anwendung über das Netzwerk auf externe Informationen zugreift:

Oracle11g bringt hier eine kleine, jedoch folgenreiche Änderung mit: War es bislang ausreichend, dem Application Express Parsing Schema EXECUTE-Privilegien auf Packages wie UTL_HTTP, UTL_SMTP oder DBMS_LDAP zuzuweisen, so reicht dies in Oracle11g nicht mehr aus: Es müssen zusätzlich Zugriffskontrolllisten( Access Control Lists) für das Netzwerk gepflegt werden. Grund dafür ist, dass die einfache Freigabe von bspw. HTTP-Zugriffen auf das gesamte Netzwerk (EXECUTE-Privileg auf UTL_HTTP) den heutigen Sicherheitsansprüchen meist nicht genügt. Oracle11g hilft hier ab, indem es dem Datenbankadministrator die Möglichkeit gibt, den Netzwerkverkehr auf das nötige Maß zu beschränken - so ist es durchaus möglich, den Netzwerkzugriff nur auf einzelne Server im Netzwerk zu erlauben.

Nach Installation sind in Oracle11g noch keine Zugriffskontrolllisten vorhanden, so dass trotz vorhandener EXECUTE-Privilegien keine Netzwerkaktivitäten möglich sind. Setzen Sie in einem normal erzeugten Application Express Workspace im SQL Workshop folgendes SQL-Kommando ab:

select httpuritype('http://localhost:8080/i/').getclob() from dual

Das SQL ruft das Image-Verzeichnis von Application Express ab (es wird davon ausgegangen, dass das PL/SQL Embedded Gateway mit dem Port 8080 verwendet wird; andere URL sind analog möglich). Abbildung 1 zeigt das Ergebnis in einer Oracle11g-Datenbank.

Versuch eines Netzwerkzugriffs (HTTP) in Oracle11g

Abbildung 1: Versuch eines Netzwerkzugriffs (HTTP) in Oracle11g

Die Fehlermeldung besagt, dass der Zugriffsversuch durch die Access Control List (ACL) abgelehnt wurde. Nun geht es also daran, diesen Zugriff zu ermöglichen. Gesteuert werden die Zugriffskontrollisten mit einem PL/SQL-Paket: DBMS_NETWORK_ACL_ADMIN. Folgendes PL/SQL-Skript gibt den Zugriff genau für besagten URL frei:

begin
  if dbms_db_version.ver_le_10_2 then
    null;
  else 
    begin
      dbms_network_acl_admin.drop_acl(
        acl =>         'apex-TEST-network.xml'
      );
    exception 
      when others then null-- ACL existiert noch nicht
    end;
    dbms_network_acl_admin.create_acl(
      acl =>         'apex-TEST-network.xml',
      description => 'Netzwerk-Connects von Workspace TEST',
      principal =>   'TESTIT'-- PARSING SCHEMA der Anwendung
      is_grant =>    true,
      privilege =>   'connect'
    );
    DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
      acl =>         'apex-TEST-network.xml',
      principal =>   'TESTIT'-- PARSING SCHEMA der Anwendung
      is_grant  =>   true,
      privilege =>   'resolve'
    );
    dbms_network_acl_admin.assign_acl(
      acl =>         'apex-TEST-network.xml',
      host =>        'localhost',
      lower_port =>  8080,
      upper_port =>  8080
    );
  end if;
end;
/
sho err
    
commit
/

Lassen Sie das Skript als Datenbanknutzer mit DBA-Privilegien (SYS) laufen. Anschließend versuchen Sie obiges SQL-Kommando nochmals (Abbildung 2).

Durch ACL erlaubter Netzwerkzugriff

Abbildung 2: Durch ACL erlaubter Netzwerkzugriff

ACHTUNG: Diese Netwerk-ACL's gelten auch für die Application Express-Umgebung, also für das Schema FLOWS_030000. Um bspw. den Mailversand auch in Oracle11g bereitzustellen, müssen Sie eine entsprechende ACL für den User FLOWS_030000 einrichten.

Man sieht, dass der Netzwerkzugriff nun funktioniert. Wenn Sie nun einen anderen URL eingeben oder den Port von 8080 auf einen anderen ändern, erhalten Sie sofort wieder die Fehlermeldung, dass der Zugriff durch die ACL abgelehnt wurde. Man sieht daran, dass der DBA die Netzwerkprivilegien nun sehr fein granular und passend zu den Anforderungen einer Applikation setzen kann.

Normalerweise werden stets die Privilegien connect und resolve benötigt. resolve dient zur Auflösung von Rechnernamen in IP-Adressen, verwendet man also keine Rechnernamen, sondern nur IP-Adressen, ist ist resolve nicht unbedingt nötig.

Es ist allerdings kein Muss, die Privilegien feingranular zu vergeben. Lässt man im Aufruf von DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL die Parameter lower_port und upper_port weg, so sind für diesen Host alle Ports erlaubt. Beim Hostnamen können Wildcards verwendet werden. So steht der Hostname *.oracle.com für alle Rechner der Domain oracle.com. Der Stern alleine steht für das gesamte Netzwerk. Somit stellt die folgende ACL das Verhalten der Oracle10g-Datenbank wieder her, in dem es allen Nutzern (PUBLIC) Privilegien für das gesamte Netzwerk einräumt - für produktive Systeme ist dieses Skript allerdings nicht zu empfehlen ...

begin
  if dbms_db_version.ver_le_10_2 then
    null;
  else 
    begin
      dbms_network_acl_admin.drop_acl(
        acl =>         'all-network-PUBLIC.xml'
      );
    exception 
      when others then null; 
    end;
    dbms_network_acl_admin.create_acl(
      acl =>         'all-network-PUBLIC.xml',
      description => 'Netzwerk-Connects fuer ALLE',
      principal =>   'PUBLIC',
      is_grant =>    true,
      privilege =>   'connect'
    );
    DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
      acl =>         'all-network-PUBLIC.xml',
      principal =>   'PUBLIC', 
      is_grant  =>   true,
      privilege =>   'resolve'
    );
    dbms_network_acl_admin.assign_acl(
      acl =>         'all-network-PUBLIC.xml',
      host =>        '*'
    );
  end if;
end;
/
sho err
    
commit
/

Die View USER_NETWORK_ACL_PRIVILEGES gibt Auskünft über die vorhandenen Privilegien.

Vorhandene Netzwerkprivilegien abfragen

Abbildung 3: Vorhandene Netzwerkprivilegien abfragen

Nun kann es in der Praxis vorkommen, dass mehrere ACL zusammenkommen - eine ACL könnte der Rolle NETWORK Zugriffe auf alle Rechner der Domain oracle.com zuweisen. Eine zweite könnte dem User SCOTT jedoch den Zugriff auf geheim.oracle.com. Mit dem folgenden ACL kann man nun feststellen, ob der Zugriff auf einen Server (bspw. www.oracle.com) möglich ist ...

SELECT 
  column_value, 
  lower_port, 
  upper_port, 
  privilege,
  status
FROM 
  user_network_acl_privileges, 
  TABLE(DBMS_NETWORK_ACL_UTILITY.DOMAINS('www.oracle.com'))
ORDER BY 
  DBMS_NETWORK_ACL_UTILITY.DOMAIN_LEVEL(column_value) desc, 
  lower_port,                                              
  upper_port
Netzwerkprivilegien feststellen

Abbildung 4: Netzwerkprivilegien feststellen

Die Abfrage in Abbildung 4 untersucht, gibt die Netzwerkprivilegien ausgehend von einem bestimmten Rechnernamen für die gesamte Domain und alle Unterdomains wieder - sie eignet sich so recht gut zum Untersuchen von Zugriffsproblemen. Übrigens: Die Funktion DBMS_NETWORK_ACL_UTILITY.DOMAINS löst einen Rechnernamen in seine Namens-Bestandteile (Rechnername, Domain, Top-Level-Domain) auf - das ist vielleicht auch an anderer Stelle recht nützlich.

Nach Einrichten der entsprechenden ACL steht die Netzwerkfunktionalität in Oracle11 g wieder wie gewohnt zur Verfügung. Da die Privilegien nun wesentlich feingranularer vergeben werden können, fällt es dem DBA vielleicht sogar leichter, die Netzwerkzugriffe zu erlauben: Er öffnet eben nicht mehr durch eine einfache GRANT-Anweisung das gesamte Netzwerk, vielmehr kann er genau bestimmen, welche Zugriffe möglich sind und welche nicht.

Zurück zur Community-Seite