Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
wiki2:oso [2021/08/09 11:09] alfred [ABAC] |
wiki2:oso [2021/08/09 13:29] (actual) |
||
|---|---|---|---|
| Línea 68: | Línea 68: | ||
| Usa una sintaxis declarativa, en vez de imperativa. Es decir, se le va indicando "qué aceptar" mediante reglas. Sigue un estilo lógico que sustituye el flujo (loops, condicionales...) por "facts" o reglas. En sí, el conjunto de estas reglas es conocido como base de conocimiento. | Usa una sintaxis declarativa, en vez de imperativa. Es decir, se le va indicando "qué aceptar" mediante reglas. Sigue un estilo lógico que sustituye el flujo (loops, condicionales...) por "facts" o reglas. En sí, el conjunto de estas reglas es conocido como base de conocimiento. | ||
| - | Se pueden añadir tantas funciones\reglas con el mismo nombre como se quiera, no se sobreescriben sino que se añaden. | + | Se pueden añadir tantas funciones\reglas con el mismo nombre como se quiera, no se sobreescriben sino que se añaden. Es decir, una consulta será cierta si hace match con una o varias reglas. |
| - | La regla principal y que ha de existir es ''allow(actor, acción, documento)''. | + | La regla principal y que ha de existir es ''allow(actor, acción, recurso)''. |
| ==== Simple Polar rules ==== | ==== Simple Polar rules ==== | ||
| + | Si no se añade un if entonces se acepta cualquier combinación. La siguiente regla acepta todo en todo: | ||
| + | <code> | ||
| + | allow(actor, action, resource); | ||
| + | </code> | ||
| + | |||
| + | Permitir explícitamente a Zora leer el documento 1: | ||
| + | <code> | ||
| + | allow("Zora", "read", "document-1"); | ||
| + | </code> | ||
| + | |||
| Si el usuario es el dueño del gasto: | Si el usuario es el dueño del gasto: | ||
| <code> | <code> | ||
| Línea 87: | Línea 97: | ||
| allow(user: User, "read", _expense: Expense) if | allow(user: User, "read", _expense: Expense) if | ||
| user_in_role(user, "accountant"); | user_in_role(user, "accountant"); | ||
| + | </code> | ||
| + | |||
| + | ==== Sintaxis ==== | ||
| + | Chequear si una variable (actor) matchea con un valor concreto: | ||
| + | <code> | ||
| + | allow(actor, "read", "document-1") if | ||
| + | actor = "Abagail" or | ||
| + | actor = "Carol" or | ||
| + | actor = "Johann"; | ||
| + | </code> | ||
| + | |||
| + | La comparación pasa cuando se usa el ''=''. Donde un parámetro se asigna ese valor y luego se compara. Esta comparación\asignación se puede dividir usando dos operadores diferentes, uno para asignar '':='' y otro para consultar ''==''. | ||
| + | |||
| + | Se puede hacer una query de los valores internos de un objeto. Por ejemplo, para permitir la lectura a un usuario administrador con id 0 al documento con id 1: | ||
| + | <code> | ||
| + | allow(User{id: 0, admin: true}, "read", Document{id: 1, owner: 0}) | ||
| + | </code> | ||
| + | |||
| + | O acceder a sus propiedades: | ||
| + | <code> | ||
| + | # A user that is an administrator may read any document. | ||
| + | allow(user, "read", _document) if | ||
| + | user.admin = true; | ||
| + | </code> | ||
| + | |||
| + | Para **comprobar el tipado** usamos matches: | ||
| + | <code> | ||
| + | # A user that is an administrator may read any document. | ||
| + | allow(user, "read", _document) if | ||
| + | user matches User and | ||
| + | user.admin = true; | ||
| + | |||
| + | # A user may read any document that they own. | ||
| + | allow(user, "read", document) if | ||
| + | user matches User and | ||
| + | document matches Document and | ||
| + | user.id = document.owner; | ||
| + | | ||
| + | # ----- O lo que es lo mismo ---------------------- | ||
| + | |||
| + | # A user that is an administrator may read any document. | ||
| + | allow(user: User, "read", _document: Document) if | ||
| + | user.admin = true; | ||
| + | |||
| + | # A user may read any document that they own. | ||
| + | allow(user: User, "read", document: Document) if | ||
| + | user.id = document.owner; | ||
| + | |||
| + | </code> | ||
| + | |||
| + | Podemos incluso **matchear con los atributos**, algo al estilo de... | ||
| + | <code> | ||
| + | # A user that is an administrator may read any document. | ||
| + | allow(_user: User{admin: true}, "read", _document: Document); | ||
| + | |||
| + | # A user may read any document that they own. | ||
| + | allow(_user: User{id: user_id}, "read", _document: Document{owner: document_owner}) if | ||
| + | user_id = document_owner; | ||
| + | | ||
| + | # A user may read any document that they own. | ||
| + | allow(_user: User{id: user_id}, "read", _document: Document{owner: user_id}); | ||
| + | </code> | ||
| + | |||
| + | Podemos también llamar a métodos: | ||
| + | <code> | ||
| + | allow(_actor, action: String, _resource) if | ||
| + | action.endswith("::resource"); | ||
| + | </code> | ||
| + | |||
| + | Piensa que podemos llamar también reglas con atributos que no tenemos en esta: | ||
| + | <code> | ||
| + | allow(user, action, resource) if | ||
| + | resource_role_applies_to(resource, role_resource) and | ||
| + | user_in_role(user, role, role_resource) and | ||
| + | role_allow(role, action, resource); | ||
| + | </code> | ||
| + | |||
| + | ==== Equivalencias en Python ==== | ||
| + | |||
| + | * None -> nil | ||
| + | * int -> Integer | ||
| + | * float -> Float | ||
| + | * bool -> Boolean | ||
| + | * list -> List | ||
| + | * dict -> Dictionary | ||
| + | * str -> String | ||
| + | |||
| + | Queries en listas o iterables (con yield): | ||
| + | <code> | ||
| + | allow(actor, _action, _resource) if "payroll" in actor.get_groups(); | ||
| + | allow(actor, _action, _resource) if actor.groups.index("HR") == 0; | ||
| + | </code> | ||
| + | |||
| + | Diccionarios: | ||
| + | <code> | ||
| + | # diccionario: user.roles = {"project1": "admin"} | ||
| + | allow(actor, _action, _resource) if actor.roles.project1 = "admin"; | ||
| + | </code> | ||
| + | |||
| + | Podemos acceder a métodos estáticos si la clase ha sido registrada. Por ejemplo, para permitir el acceso total en entorno de desarrollo: | ||
| + | <code> | ||
| + | # En Python | ||
| + | class Env: | ||
| + | @staticmethod | ||
| + | def var(variable): | ||
| + | return os.environ[variable] | ||
| + | | ||
| + | # En Polar | ||
| + | allow(_actor, _action, _resource) if Env.var("ENV") = "development"; | ||
| </code> | </code> | ||
| ===== Cómo implementar... ===== | ===== Cómo implementar... ===== | ||