The online documentation is produced by a web publishing technology created by us to read the documents origins in OpenOffice Writer (ODT) and Microsoft Word (docx) formats and produces native web and PDF versions. In this way we maintain Louder project documentation update and in sync on each of its formats.
La Lista de Control de Acceso ó en inglés (Access Control List) es un componente de Kumbia Enterprise Framework es un concepto de seguridad informática usado para fomentar la separación de privilegios. Es una forma de determinar los permisos de acceso apropiados a un determinado objeto, dependiendo de ciertos aspectos del proceso que hace el pedido. Al igual que otros componentes del framework que están basados en componentes se implementa el patrón Virtual Proxy, una instancia de Acl solo actúa como un Proxy al objeto real instanciado que corresponde al tipo de adaptador utilizado por el mismo.
Estructura del Componente
Kumbia Enterprise Framework ha integrado la siguiente estructura jerárquica de clases que permiten la implementación de este componente:
Tabla: Jerarquia de clases del componente Acl
Clase
Descripción
Acl.php
Es la clase constructora de las listas Acl. Es un Proxy a la funcionalidad implementada en cada adaptador.
Interface.php
Es la interfase que deben utilizar todos los adaptadores Acl .
Adapters/Memory.php
Es el adaptador que permite administrar las listas de acceso en memoria.
Adapters/Xml.php
El Adaptador permite definir listas de acceso en archivos de descripción en XML.
Adapters/Model.php
Es el adaptador permite la administración de la lista de acceso a una base de datos como backend.
Resource/Resource.php
Es la clase que permite administrar cada recurso como una entidad independiente de su backend.
Role/Role.php
Es la clase que permite administrar los roles que tendrán acceso a la lista ACL independientemente de su backend.
¿Que es un Recurso?
Un recurso es cualquier elemento de una aplicación del cual se pueda controlar su acceso. Por conveniencia los controladores de la aplicación son vistos como recursos con el objetivo de generar un modelo de seguridad consistente.
¿Que es un Rol?
Un rol es un nombre abstracto para el permiso de usuarios a un conjunto particular de recursos en una aplicación. Un rol puede ser comparado a la llave que abre un candado, este abre sin importar quien tiene la clave. Los roles están generalmente asociados a los mismos usuarios, a los grupos de estos ó a sus perfiles.
¿Que es un Acceso?
Los accesos son las operaciones ó acciones que se pueden realizar en los recursos. Niveles más profundos de seguridad controlan hasta este nivel lo que se pueda hacer por parte de los usuarios.
Tipos de Reglas
El acceso a un determinado recurso tiene una regla de 'permitir' (allow) ó 'denegar' (deny), no están soportadas otros tipos de reglas de acceso.
ACL en Acción
En el siguiente ejemplo se ilustra como al definir un filtro beforeFilter en la clase ControllerBase en apps/default/controllers/application.php con el que se puede implementar el control de acceso a los recursos de la aplicación en forma programacional:
Ejemplo: Utilizar ACL con modelos para validar el acceso a los recursos de una aplicación
<?php
class ControllerBase {
public function beforeFilter(){
$role = Session::get('role');
if($role==""){
$role = 'Public';
}
$acl = new Acl('Model', 'className: AccessList');
$resourceName = $this->getControllerName();
$operationName = $this->getActionName();
if($acl->isAllowed($role, $resourceName, $operationName)==false){
if($this->getControllerName()!='appmenu'){
$this->routeTo("controller: appmenu");
} else {
throw new ApplicationControllerException("No tiene permiso
para usar esta aplicación");
}
$authLog = new Log("File", "auth_failed.txt");
$authLog->log("Autenticación fallo para el rol '$role' en el recurso '". $this->getControllerName()."/".$this->getActionName()."'");
return false;
}
}
}
Gracias a que el método beforeFilter se encuentra en la jerarquía de todos los controladores este se ejecuta previamente a cualquier acción solicitada. Se obtiene de los datos de sesión, la variable role indica el nombre del rol actualmente logueado, si aun no hay un rol activo es asignado por defecto Public.
Ahora es posible instanciar la clase Acl, y definir como adaptador un Modelo en donde se ha referencia a la clase AccessList quien mapea a la tabla llamada access_list, la cual administra los accesos a los recursos de la aplicación. La tabla contiene un Security Policy Domain de un POS (Point Of Sale):
Ejemplo: Datos de lista ACL basada en Modelos
SQL > select * from access_list order by role;+----+-----------------+-----------------------+--------+-------+| id | role | resource | action | allow |+----+-----------------+-----------------------+--------+-------+| 6 | Public | * | * | Y || 7 | Public | dinein | * | N || 15 | Public | users | * | N || 27 | Public | appmenu | * | Y || 29 | Public | admin | * | Y || 30 | Public | menus | * | N || 9 | Administradores | * | * | Y || 10 | Cajeros | * | * | Y || 11 | Cajeros | ambient_items | * | N || 12 | Cajeros | drop_invoice | * | N || 13 | Cajeros | menus | * | N || 14 | Cajeros | menus_items | * | N || 16 | Cajeros | users | * | N || 17 | Cajeros | modifiers | * | N || 18 | Cajeros | ambient_menus_items | * | N || 19 | Cajeros | discount | * | N || 26 | Cajeros | data | query | N |+----+-----------------+-----------------------+--------+-------+
El parámetro className permite establecer un modelo que contiene la estructura descrita en la tabla anterior. El campo resource y action pueden contener asteriscos (*) que son usados como comodines para cualquier criterio que coincida. El campo allow puede tener los valores Y(es) o N(o) para indicar si le concede el acceso al recurso.
La principal ventaja de la listas ACL es que validan los accesos en forma jerárquica ya sea a nivel de recursos ó mediante herencia de roles. En el ejemplo el acceso de jerarquía más alto es en el que hay comodines tanto para el recurso como para la acción, el método Acl::isAllowed busca jerárquicamente si existe un acceso ó no en la lista de acceso.
Según el ejemplo las siguientes consultas a la lista de acceso darian como resultado:
Ejemplo: Comportamiento de la lista ACL según datos de ejemplo
$acl = new Acl('Model', 'className: AccessList');
//Esta permitido el rol 'Public' a acceder al recurso 'menus' en la operación 'index'?
//No Permitido
$acl->isAllowed("Public", "menus", "index")
//Esta permitido el rol 'Cajeros' a acceder al recurso 'dinein' en cualquier operación?
//Permitido
$acl->isAllowed("Cajeros", "dinein", "*")
//Esta permitido el rol 'Cajeros a acceder al recurso 'data' en la operación 'query'?
//No Permitido
$acl->isAllowed("Cajeros", "data", "query")
El primer parámetro de Acl::isAllowed es el nombre del rol, el segundo el nombre del recurso y el tercero el nombre de la acción. Cuando no se encuentra una regla especifica para rol-recurso-operación, se busca rol-recurso-cualquiera y por ultimo rol-cualquiera-cualquiera.
Herencia de Roles
Una de las grandes ventajas del uso de listas de control de acceso es la construcción de arboles de jerarquía de roles. De esta forma los permisos de acceso pueden ser heredados ó compartidos entre varios roles sin que haya redundancia de información proporcionando a la aplicación capacidades de control de acceso potentes y flexibles.
Adaptadores de ACL
Kumbia Enterprise Framework permite utilizar varios backends para almacenar listas Acl. Cada adaptador implementa la interface AclInterface:
<?php
interface AclAdapter {
public function addRole(AclRole $roleObject, $accessInherits='');
public function addInherit($role, $roleToInherit);
public function isRole($role_name);
public function isResource($resource_name);
public function addResource(AclResource $resource);
public function addResourceAccess($resource, $accessList);
public function dropResourceAccess($resource, $accessList);
public function allow($role, $resource, $access);
public function deny($role, $resource, $access);
public function isAllowed($role, $resource, $accessList);
}
A continuación se explican las consideraciones de uso de cada adaptador:
AclModel
La lista de accesos también puede ser administrada usando modelos disponibles en la aplicación. Para esto es necesario crear una entidad con la siguiente estructura:
Ejemplo: Estructura de una tabla apta para almacenar una lista ACL
CREATE TABLE `access_list` (
`id` int(11) NOT NULL,
`role` varchar(24) NOT NULL,
`resource` varchar(32) NOT NULL,
`action` varchar(32) NOT NULL,
`allow` char(1) default NULL,
PRIMARY KEY (`id`),
)
Al instanciar el objeto Acl se debe indicar el modelo a utilizar mediante el parámetro className, luego el comportamiento y utilización es el normal:
Ejemplo: Uso de listas ACL con Modelos
$acl = new Acl('Model', 'className: AccessList');
$acl->isAllowed("Administrators", "customers", "create")
AclMemory
El adaptador AclMemory almacena los permisos en memoria. La lista de control de acceso puede construirse en un proceso inicializador y almacenarse en un backend de cache para usarse en otras peticiones. Para aplicaciones con requerimientos de validación de control de acceso reducidos este adaptador puede ser una opción a tener en cuenta.
AclXML
Este adaptador permite crear listas de control de acceso en archivos XML. Estos archivos mantienen los controles de forma estructurada haciendo sencilla su manipulación desde otros lenguajes y aplicaciones.
El archivo debe contener la siguiente estructura:
Un nodo raíz 'security' que contendrá la lista en sí
Un solo nodo 'roles-collection' que contiene nodos 'role' con información de roles
Los nodos 'role' deben tener los sub-nodos 'name' y 'description' con el nombre y descripción del rol respectivamente.
Un solo nodo 'resources-collection' que contiene nodos 'resource' con información de los recursos en la lista.
Los nodos 'resource' deben tener los sub-nodos 'name' y 'description' con el nombre y descripción del recurso respectivamente.
Múltiples nodos 'access-constraint' con las reglas de acceso. El orden de estas indica la prioridad de cada una.
Cada nodo 'access-constraint' contiene los nodos 'role-name' que es nombre del rol, 'resource-name' que es el nombre del recurso, 'action-name' que es nombre del acceso y 'rule-type' que contiene 'allow' si tiene acceso al recurso y 'deny' de lo contrario.
El siguiente es el ejemplo de una lista ACL en XML:
Ejemplo: Lista ACL usando una definición en XML
<?xml version="1.0" encoding="UTF-8" ?>
<security xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- ROLES DE LA APLICACION -->
<roles-collection>
<role>
<name>Public</name>
<description>Rol para usuarios no autenticados</description>
</role>
<role>
<name>Customers</name>
<description>Usuarios clientes de la empresa</description>
</role>
<role>
<name>QueryOnly</name>
<description>Usuarios con permisos de solo lectura</description>
</role>
</roles-collection>
<!-- RECURSOS DE LA APLICACION -->
<resources-collection>
<resource>
<name>banking</name>
<description>Controlador para operaciones del cajero</description>
</resource>
<resource>
<name>login</name>
<description>Controlador para operaciones de inicio de sesión</description>
</resource>
</resources-collection>
<!-- CONSTRAINTS DE ACCESO -->
<access-constraint>
<role-name>Public</role-name>
<resource-name>*</resource-name>
<action-name>*</action-name>
<rule-type>deny</rule-type>
</access-constraint>
<access-constraint>
<role-name>Public</role-name>
<resource-name>login</resource-name>
<action-name>validateCredentials</action-name>
<rule-type>allow</rule-type>
</access-constraint>
<access-constraint>
</security>
API de un Adaptador
public boolean addRole(AclRole $roleObject, mixed $accessInherits) Agrega un rol a la lista de roles de la lista de Acceso. En este tipo de Adaptador el rol se crea en la entidad definida en el constructor de la lista en el parámetro: rolesClassName.
public void addInherit($role, $roleToInherit) Agrega una herencia a la lista en la que el rol $role hereda todos los constraints de acceso que tiene el rol $roleToInherit.
public boolean isRole(string $roleName) Permite saber si $roleName esta presente en la lista ACL
public boolean isResource(string $resourceName) Permite saber si un recurso existe ó no en la lista de acceso actual.
public boolean addResource(AclResource $resource) Agrega un recurso para ser administrador por la lista de control de acceso.
public void addResourceAccess(string $resource, mixed $accessList) Agrega una operación/acción a un recurso de la lista ACL. El parámetro $accessList puede ser un string ó un vector.
public void dropResourceAccess($resource, $accessList) Elimina una operación/acción de un recurso de la lista ACL. El parámetro $accessList puede ser un string ó un vector.
public void allow(string $role, string $resource, mixed $access) Agrega una regla que da acceso a un determinado rol a un recurso.
public void deny(string $role, string $resource, mixed $access) Agrega una regla denegando el acceso de un determinado rol a un recurso.
public boolean isAllowed(string $role, string $resource, array $accessList) Realiza una consulta en la lista ACL
API de AclResource
public void getName() Obtener el nombre del recurso
public void getDescription() Obtener la descripción del recurso
API de AclRole
public void getName() Obtener el nombre del Role
public void getDescription() Obtener la descripción del Role, usualmente el nombre extendido del rol.