Wednesday, 9 September 2015

Access Control List (ACL)

Create an Access Control List (ACL)

Access control lists are manipulated using the DBMS_NETWORK_ACL_ADMIN package. The CREATE_ACL procedure uses the following parameters to create a new ACL:
  • acl - The name of the access control list XML file, generated relative to the "/sys/acls" directory in the XML DB Repository.
  • description - A description of the ACL.
  • principal - The first user account or role being granted or denied permissions. The text is case sensitive.
  • is_grant - TRUE to grant, FALSE to deny the privilege.
  • privilege - Use 'connect' for UTL_TCPUTL_SMTPUTL_MAIL and UTL_HTTP access. Use 'resolve' for UTL_INADDR name/IP resolution. The text is case sensitive.
  • start_date - Default value NULL. When specified, the ACL will only be active on or after the specified date.
  • end_date - An optional end date for the ACL.
The following code creates two test users to act as principals, then creates a new ACL.
CONN sys/password@db11g AS SYSDBA

CREATE USER test1 IDENTIFIED BY test1;
GRANT CONNECT TO test1;

CREATE USER test2 IDENTIFIED BY test2;
GRANT CONNECT TO test2;

BEGIN
  DBMS_NETWORK_ACL_ADMIN.create_acl (
    acl          => 'test_acl_file.xml', 
    description  => 'A test of the ACL functionality',
    principal    => 'TEST1',
    is_grant     => TRUE, 
    privilege    => 'connect',
    start_date   => SYSTIMESTAMP,
    end_date     => NULL);

  COMMIT;
END;
/
Once created, the ACL is visible in the "http://host:port/sys/acls/" directory.
Additional users or roles are added to the ACL using the ADD_PRIVILEGE procedure. Its parameter list is similar to the CREATE_ACL procedure, with the omission of the DESCRIPTIONparameter and the addition of a POSITION parameter, which sets the order of precedence.
BEGIN
  DBMS_NETWORK_ACL_ADMIN.add_privilege ( 
    acl         => 'test_acl_file.xml', 
    principal   => 'TEST2',
    is_grant    => FALSE, 
    privilege   => 'connect', 
    position    => NULL, 
    start_date  => NULL,
    end_date    => NULL);

  COMMIT;
END;
/
Each principal is defined as a separate access control element (ACE), within the ACL. When multiple principles are defined, they are evaluated in order from top to bottom, with the last relevant reference used to define the privilege. This means a role that denies access to a resource can be granted to a user, but if the user is defined as a principal further down the file, that definition will override the role definition for that user. Use the POSITION parameter to ensure privileges are evaluated in order.
Privileges are removed using the DELETE_PRIVILEGE procedure. If the IS_GRANT or PRIVILEGE parameters are NULL, all grants or privileges for the ACL and principal are removed.
BEGIN
  DBMS_NETWORK_ACL_ADMIN.delete_privilege ( 
    acl         => 'test_acl_file.xml', 
    principal   => 'TEST2',
    is_grant    => FALSE, 
    privilege   => 'connect');

  COMMIT;
END;
/
ACLs are deleted using the DROP_ACL procedure.
BEGIN
  DBMS_NETWORK_ACL_ADMIN.drop_acl ( 
    acl         => 'test_acl_file.xml');

  COMMIT;
END;
/

Assign an ACL to a Network

Access control lists are assigned to networks using the ASSIGN_ACL procedure, whose parameters are listed below:
  • acl - The name of the access control list XML file.
  • host - The hostname, domain, IP address or subnet to be assigned. Hostnames are case sensitive, and wildcards are allowed for IP addresses and domains.
  • lower_port - Defaults to NULL. Specifies the lower port range for the 'connect' privilege.
  • upper_port - Defaults to NULL. If the lower_port is specified, and the upper_port is NULL, it is assumed the upper_port matches the lower_port.
The code below shows the ACL created previously being assigned to a specific IP address and a subnet.
BEGIN
  DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => 'test_acl_file.xml',
    host        => '192.168.2.3', 
    lower_port  => 80,
    upper_port  => NULL); 

  DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => 'test_acl_file.xml',
    host        => '10.1.10.*', 
    lower_port  => NULL,
    upper_port  => NULL);

  COMMIT;
END;
/
Only one ACL can be assigned to a specific host and port-range combination. Assigning a new ACL to a specific host and port-range results in the deletion of the previous assignment. You must take care when making a new assignment that you are not opening ports that were closed by a previous ACL assignment, or you could be opening yourself to attack. When wildcard usage causes overlapping assignments, the most specific assignment will take precedence, so an ACL assigned to 192.168.2.3:80 takes precedence over once assigned to 192.168.2.* etc.
The UNASSIGN_ACL procedure allows you to manually drop ACL assignments. It uses the same parameter list as the ASSIGN_ACL procedure, with any NULL parameters acting as wildcards.
BEGIN
  DBMS_NETWORK_ACL_ADMIN.unassign_acl (
    acl         => 'test_acl_file.xml',
    host        => '192.168.2.3', 
    lower_port  => 80,
    upper_port  => NULL); 

  COMMIT;
END;
/

ACL Views

The DBA_NETWORK_ACLSDBA_NETWORK_ACL_PRIVILEGES and USER_NETWORK_ACL_PRIVILEGES views display the current ACL settings. The expected output below assumes none of the delete/drop/unassign operations have been performed.
The DBA_NETWORK_ACLS view displays information about network and ACL assignments.
COLUMN host FORMAT A30
COLUMN acl FORMAT A30

SELECT host, lower_port, upper_port, acl
FROM   dba_network_acls;

HOST                           LOWER_PORT UPPER_PORT ACL
------------------------------ ---------- ---------- ------------------------------
10.1.10.*                                            /sys/acls/test_acl_file.xml
192.168.2.3                            80         80 /sys/acls/test_acl_file.xml

2 rows selected.

SQL>
The DBA_NETWORK_ACL_PRIVILEGES view displays information about privileges associated with the ACL.
COLUMN acl FORMAT A30
COLUMN principal FORMAT A30

SELECT acl,
       principal,
       privilege,
       is_grant,
       TO_CHAR(start_date, 'DD-MON-YYYY') AS start_date,
       TO_CHAR(end_date, 'DD-MON-YYYY') AS end_date
FROM   dba_network_acl_privileges;

ACL                            PRINCIPAL                      PRIVILE IS_GR START_DATE  END_DATE
------------------------------ ------------------------------ ------- ----- ----------- -----------
/sys/acls/test_acl_file.xml    TEST1                          connect true  02-APR-2008
/sys/acls/test_acl_file.xml    TEST2                          connect false

2 rows selected.

SQL>
The USER_NETWORK_ACL_PRIVILEGES view displays the current users network ACL settings.
CONN test1/test1@db11g

COLUMN host FORMAT A30

SELECT host, lower_port, upper_port, privilege, status
FROM   user_network_acl_privileges;

HOST                           LOWER_PORT UPPER_PORT PRIVILE STATUS
------------------------------ ---------- ---------- ------- -------
10.1.10.*                                            connect GRANTED
192.168.2.3                            80         80 connect GRANTED

2 rows selected.

SQL> 

CONN test2/test2@db11g

COLUMN host FORMAT A30

SELECT host, lower_port, upper_port, privilege, status
FROM   user_network_acl_privileges;

HOST                           LOWER_PORT UPPER_PORT PRIVILE STATUS
------------------------------ ---------- ---------- ------- -------
10.1.10.*                                            connect DENIED
192.168.2.3                            80         80 connect DENIED

2 rows selected.

SQL>

Checking Privileges

In addition to the ACL views, privileges can be checked using the CHECK_PRIVILEGE and CHECK_PRIVILEGE_ACLID functions of the DBMS_NETWORK_ACL_ADMIN package.
CONN sys/password@db11g AS SYSDBA

SELECT DECODE(
         DBMS_NETWORK_ACL_ADMIN.check_privilege('test_acl_file.xml', 'TEST1', 'connect'),
         1, 'GRANTED', 0, 'DENIED', NULL) privilege 
FROM dual;

PRIVILE
-------
GRANTED

1 row selected.

SQL> 

COLUMN acl FORMAT A30
COLUMN host FORMAT A30

SELECT acl,
       host,
       DECODE(
         DBMS_NETWORK_ACL_ADMIN.check_privilege_aclid(aclid, 'TEST2', 'connect'),
         1, 'GRANTED', 0, 'DENIED', NULL) privilege 
FROM   dba_network_acls;

PRIVILE
-------
DENIED

1 row selected.

SQL>


No comments:

Post a Comment