{ "info": { "author": "Ketan Goyal", "author_email": "ketangoyal1988@gmail.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Security", "Topic :: Software Development", "Topic :: System :: Networking", "Topic :: System :: Networking :: Firewalls", "Topic :: System :: Systems Administration", "Topic :: Utilities" ], "description": "# py-ABAC\nAttribute Based Access Control (ABAC) for python. \n\n[![Build Status](https://travis-ci.com/ketgo/py-abac.svg?token=oCVxhfjJAa2zDdszGjoy&branch=master)](https://travis-ci.com/ketgo/py-abac)\n[![codecov.io](https://codecov.io/gh/ketgo/pyabac/coverage.svg?branch=master)](https://codecov.io/gh/ketgo/pyabac/coverage.svg?branch=master)\n[![Apache 2.0 licensed](https://img.shields.io/badge/License-Apache%202.0-yellow.svg)](https://raw.githubusercontent.com/kolotaev/vakt/master/LICENSE)\n\n---\n\n- [Introduction](#introduction)\n- [Install](#install)\n- [Usage](#usage)\n- [Concepts](#concepts)\n- [Components](#components)\n\t- [Policy](#policy)\n\t- [Request](#inquiry)\n\t- [PDP](#pdp)\n\t- [Storage](#storage)\n\t - [Memory](#memory)\n\t - [MongoDB](#mongodb)\n\t - [SQL](#sql)\n\t- [Migration](#migration)\n\t- [AttributeProvider](#attributeprovider)\n\t- [EvaluationContext](#evaluationcontext)\n- [Policy Language](#policy-language)\n - [Policy JSON](#policy-json)\n - [Targets vs Rules](#targets-vs-rules)\n - [Targets Block](#targets-block)\n - [Rules Block](#rules-block)\n - [Condition Blocks](#condition-blocks)\n - [Access Request](#access-request)\n- [Logging](#logging)\n- [Milestones](#milestones)\n- [Acknowledgements](#acknowledgements)\n- [Development](#development)\n- [License](#license)\n\n---\n\n## Introduction\n\nPy-ABAC is an attribute-based access control ([ABAC](https://en.wikipedia.org/wiki/Attribute-based_access_control)) toolkit based on policies. ABAC gives you a fine-grained control on definition of the rules that restrict an access to resources and is generally considered a \"next generation\" authorization model. The design of py-ABAC stems from the [XACML](https://en.wikipedia.org/wiki/XACML) standard, and the ABAC python SDK [Vakt](https://github.com/kolotaev/vakt).\n\nSee [concepts](#concepts) section for more details.\n\n*[Back to top](#py-abac)*\n\n\n## Install\n\nPyABAC runs on Python >= 3.5. PyPy implementation is supported as well.\n\n\nTo install run the following:\n```bash\npip install py-abac\n```\n\n*[Back to top](#py-abac)*\n\n## Usage\n\nA quick dive-in:\n\n```python\nfrom pymongo import MongoClient\nfrom py_abac import PDP, Policy, Request\nfrom py_abac.storage import MongoStorage\n\n# Policy definition in JSON\npolicy_json = {\n \"uid\": \"1\",\n \"description\": \"Max and Nina are allowed to create, delete, get any \"\n \"resources only if the client IP matches.\",\n \"effect\": \"allow\",\n \"rules\": {\n \"subject\": [{\"$.name\": {\"condition\": \"Equals\", \"value\": \"Max\"}},\n {\"$.name\": {\"condition\": \"Equals\", \"value\": \"Nina\"}}],\n \"resource\": {\"$.name\": {\"condition\": \"RegexMatch\", \"value\": \".*\"}},\n \"action\": [{\"$.method\": {\"condition\": \"Equals\", \"value\": \"create\"}},\n {\"$.method\": {\"condition\": \"Equals\", \"value\": \"delete\"}},\n {\"$.method\": {\"condition\": \"Equals\", \"value\": \"get\"}}],\n \"context\": {\"$.ip\": {\"condition\": \"CIDR\", \"value\": \"127.0.0.1/32\"}}\n },\n \"targets\": {},\n \"priority\": 0\n}\n# Parse JSON and create policy object\npolicy = Policy.from_json(policy_json)\n\n# Setup policy storage\nclient = MongoClient()\nstorage = MongoStorage(client)\n# Add policy to storage\nstorage.add(policy)\n\n# Create policy decision point\npdp = PDP(storage)\n\n# A sample access request JSON\nrequest_json = {\n \"subject\": {\n \"id\": \"\", \n \"attributes\": {\"name\": \"Max\"}\n },\n \"resource\": {\n \"id\": \"\", \n \"attributes\": {\"name\": \"myrn:example.com:resource:123\"}\n },\n \"action\": {\n \"id\": \"\", \n \"attributes\": {\"method\": \"get\"}\n },\n \"context\": {\n \"ip\": \"127.0.0.1\"\n }\n}\n# Parse JSON and create access request object\nrequest = Request.from_json(request_json)\n\n# Check if access request is allowed. Evaluates to True since \n# Max is allowed to get any resource when client IP matches.\nassert pdp.is_allowed(request)\n```\n\nFor more examples see [here](./examples).\n\n*[Back to top](#py-abac)*\n\n## Concepts\n\n### Access Control Architecture\n\n![img](https://lh6.googleusercontent.com/z4oppCjtEITgem5UZUN28NiaV4LrYPrjqD1MjZiYDhjmj1OkFFcN9H2jj64Zd0tkRkf5O436eOA574Sur0uSDlUztRtadREn_wfRfMbh4dNiACxivd0zjM_gLcF94N-bdhl_g15N)\n\nThe above diagram depicts the standard architecture for ABAC, which is as follows:\n\n1. The PEP or Policy Enforcement Point: It is your piece of code that uses py-ABAC to protect app & data. The PEP should inspect a user request, create a corresponding access request, and send it to the PDP for evaluation.\n\n2. The PDP or Policy Decision Point is the brain of the architecture. This is the piece which evaluates incoming access requests against policies and returns a Permit / Deny decision. The PDP may also use PIPs to retrieve missing attribute values during policy evaluation.\n\n3. The PIP or Policy Information Point bridges the PDP to external sources of attribute values e.g. LDAP or databases. \n\n4. The PAP or Policy Administration Point: manages the creation, update and deletion of policies evaluated by PDP. \n\n*[Back to top](#py-abac)*\n\n### Access Control Elements\n\nIn the above architecture, following four elements are involved during an access request to PDP:\n\n1. `subject`: This is the entity which requests access, also known as the request principal. A subject can be anything that requests access, i.e. a user or an application.\n2. `resource`: The object which is requested to be accessed by the subject. \n3. `action`: The action being performed on the resource.\n4. `context`: This element deals with time, location or dynamic aspects of the access control scenario. \n\nIn py-ABAC one defines policies containing conditions on one or more attributes of these four elements. If these conditions are satisfied, an access decision is returned by the PDP using an evaluation algorithm. There are three different evaluation algorithms supported by py-ABAC:\n\n1. `AllowOverrides`: returns `allow` if any decision evaluates to `allow`; and returns `deny` if all decisions evaluate to `deny`.\n2. `DenyOverrides`: returns `deny` if any decision evaluates to `deny`; returns `allow` if all decisions evaluate to `allow`.\n3. `HighestPriority`: returns the highest priority decision that evaluates to either `allow` or `deny`. If there are multiple equally highest priority decisions that conflict, then `DenyOverrides` algorithm would be applied among those highest priority decisions.\n\n*[Back to top](#py-abac)*\n\n## Components\n\n### Policy\n\nThis is the main object containing rules for accessing resources. A policy object can be created by first defining a policy JSON using the JSON-based [Policy Language](#policy-language), and then parsing it using the `Policy` class. \n\n``` python\nfrom py_abac import Policy\n\n# Policy definition in JSON-based policy language\npolicy_json = {\n \"uid\": \"1\",\n \"description\": \"Max is not allowed to create, delete, get any resource\",\n \"effect\": \"deny\",\n \"rules\": {\n \"subject\": {\"$.name\": {\"condition\": \"Equals\", \"value\": \"Max\"}},\n \"resource\": {\"$.name\": {\"condition\": \"RegexMatch\", \"value\": \".*\"}},\n \"action\": [{\"$.method\": {\"condition\": \"Equals\", \"value\": \"create\"}},\n {\"$.method\": {\"condition\": \"Equals\", \"value\": \"delete\"}},\n {\"$.method\": {\"condition\": \"Equals\", \"value\": \"get\"}}],\n \"context\": {}\n },\n \"targets\": {},\n \"priority\": 0\n}\n# Prase policy JSON to create Policy object\npolicy = Policy.from_json(policy_json)\n```\n\nSee the [Policy Language](#policy-language) section for detailed description of JSON structure.\n\n*[Back to top](#py-abac)*\n\n### Request\n\nA `Request` object represents the access request generated by PEP in the ABAC architecture. All you need to do is take any kind of incoming user request (REST request, SOAP, etc.) and build a `Request` object out of it in order to feed it to py-ABAC. \n\n```python\nfrom py_abac import Request\nfrom flask import request, session\n\n# Create a access request JSON from flask request object\nrequest_json = {\n \"subject\": {\n \"id\": \"\", \n \"attributes\": {\"name\": request.values.get(\"username\")}\n },\n \"resource\": {\n \"id\": \"\", \n \"attributes\": {\"name\": request.path}\n },\n \"action\": {\n \"id\": \"\", \n \"attributes\": {\"method\": request.method}\n },\n \"context\": {}\n}\n# Parse JSON and create access request object\nrequest = Request.from_json(request_json)\n```\n\nYou might have noticed the presence of empty `\"id\"` fields for the `subject`, `resource` and `action` access control elements in the above example. These are called _target IDs_ and are mandatory fields for creating an access request object in py-ABAC. The purpose of these fields is explained in detail in the [Target Block](#targets-block) subsection of [Policy Language](#policylanguage). If you are unsure of their usage, you can safely set them to an empty string.\n\n*[Back to top](#py-abac)*\n\n### PDP\n\nThis component is the policy decision point, instantiated through the `PDP` class. It is the main entry point of py-ABAC for evaluating policies. At a minimum, a [Storage](#storage) object is required to create a `PDP` object. It has one method, `is_allowed`, which when passed a `Request` object, gives you a boolean answer: is access allowed or not?\n\n```python\nfrom pymongo import MongoClient\nfrom py_abac import PDP\nfrom py_abac.storage import MongoStorage\n\n# Setup storage\nclient = MongoClient()\nst = MongoStorage(client)\n# Insert all polices to storage\nfor p in policies:\n st.add(p)\n\n# Create PDP\npdp = PDP(st)\n\n# Evaluate if access is allowed\nif pdp.is_allowed(request):\n return \"Access Allowed\", 200\nelse:\n return \"Unauthorized Access\", 401\n```\n\nBy default, a `PDP` object uses the `DenyOverrides` algorithm for policy evaluation. To specify otherwise, pass the evaluation algorithm at creation. Moreover, a list of [AttributeProvider](#attributeproviders) objects can also be provided. \n\n```python\nfrom py_abac import PDP, EvaluationAlgorithm\nfrom py_abac.storage import MongoStorage\nfrom py_abac.providers import AttributeProvider\n\n# A simple email attribute provider class\nclass EmailAttributeProvider(AttributeProvider):\n def get_attribute_value(self, ace, attribute_path, ctx):\n return \"example@gmail.com\"\n \n# Setup storage\nclient = MongoClient()\nst = MongoStorage(client)\n# Insert all polices to storage\nfor p in policies:\n st.add(p)\n\n# Create PDP configured to use highest priority algorithm \n# and an additional email attribute provider\npdp = PDP(st, EvaluationAlgorithm.HIGHEST_PRIORITY, [EmailAttributeProvider()])\n```\n\nThe three supported algorithms are `EvaluationAlgorithm.DENY_OVERRIDES`, `EvaluationAlgorithm.ALLOW_OVERRIDES`, and `EvaluationAlgorithm.HIGHEST_PRIORITY`.\n\n*[Back to top](#py-abac)*\n\n### Storage\n\nThe `Storage` is a component which provides interface for implementing policy persistence. It provides the following methods:\n\n```python\n# Store a Policy\nadd(policy) \n\n# Retrieve a Policy by its ID\nget(uid) \n\n# Retrieve all stored Policies (with pagination)\nget_all(limit, offset) \n\n# Store an updated Policy\nupdate(policy) \n\n# Delete Policy from storage by its ID\ndelete(uid) \n\n# Retrieve Policies that match the given target IDs\nget_for_target(subject_id, resource_id, action_id) \n```\n\nStorage may have various backend implementations (RDBMS, NoSQL databases, etc.). py-ABAC ships some Storage implementations out of the box. See below.\n\n##### Memory\n\nWill be part of v0.2.1\n\n##### MongoDB\n\nMongoDB is chosen as the most popular and widespread NO-SQL database.\n\n```python\nfrom pymongo import MongoClient\nfrom py_abac.storage import MongoStorage\n\nclient = MongoClient('localhost', 27017)\nstorage = MongoStorage(client, 'database-name', collection='optional-collection-name')\n```\n\nDefault database and collection names are 'py_abac' and 'py_abac_policies' respectively.\n\nActions are the same as for any Storage that conforms interface of `py_abac.storage.base.StorageBase` base class.\n\n##### SQL\n\nWill be part of v0.2.2\n\n*[Back to top](#py-abac)*\n\n#### Migration\n\n`py_abac.storage.migration` is a set of components that are useful for [Storage](#storage). The design and implementation is taken from the [Vakt](https://github.com/kolotaev/vakt) SDK. It's recommended in favor over manual actions on DB schema/data since it's aware of py-ABAC requirements. But it's not mandatory. It is up to a particular Storage to decide whether it needs migrations. It consists of 3 components:\n\n- `Migration`\n- `MigrationSet`\n- `Migrator`\n\n`Migration` allows you to describe data modifications between versions. Each storage can have a number of `Migration` classes to address different releases with the order of the migration specified in `order` property. The class should be located inside corresponding storage module and should implement `py_abac.storage.migration.Migration`. Migration has 2 main methods (as you might guess) and 1 property:\n\n- `up` - runs db \"schema\" upwards\n- `down` - runs db \"schema\" downwards (rolls back the actions of `up`)\n- `order` - tells the number of the current migration in a row\n\n`MigrationSet` is a component that represents a collection of Migrations for a Storage. You should define your own migration-set. It should be located inside particular storage module and implement `py_abac.storage.migration.MigrationSet`. It has 3 methods that lest unimplemented:\n\n- `migrations` - should return all initialized Migration objects\n- `save_applied_number` - saves a number of a lst applied up migration in the Storage for later reference\n- `last_applied` - returns a number of a lst applied up migration from the Storage\n\n`Migrator` is an executor of a migrations. It can execute all migrations up or down, or execute a particular migration if `number` argument is provided.\n\nExample usage:\n\n```python\nfrom pymongo import MongoClient\nfrom py_abac.storage.mongo import MongoStorage, MongoMigrationSet\nfrom py_abac.storage.migration import Migrator\n\nclient = MongoClient('localhost', 27017)\nstorage = MongoStorage(client, 'database-name', collection='optional-collection-name')\n\nmigrator = Migrator(MongoMigrationSet(storage))\nmigrator.up()\n...\nmigrator.down()\n...\nmigrator.up(number=2)\n...\nmigrator.down(number=2)\n```\n\n*[Back to top](#py-abac)*\n\n### AttributeProvider\n\n `AttributeProvider` is an interface to create a PIP. The purpose of this object is to provide attribute values missing in the `Request` object. During policy evaluation, the `PDP` first checks the `Request` object for attribute values; If no values are found, it then checks the list of `AttributeProvider`objects passed during creation. In order to create an `AttributeProvider` object, you need to implement the `get_attribute_value` method. \n\n```python\nfrom py_abac.provider.base import AttributeProvider\n\n# A simple email attribute provider class\nclass EmailAttributeProvider(AttributeProvider):\n def get_attribute_value(self, ace, attribute_path, ctx):\n \"\"\"\n \tReturns a value for an attribute. If value not found\n \tthen return None.\n \t\n\n \t:param ace: string value indicating the access control \n \t\t\t\telement, i.e. \"subject\", \"resource\", \"action\"\n or \"context\".\n :param attribute_path: string in ObjectPat notation indicating \n the attribute for which the value is \n requested.\n :param ctx: evaluation context\n \"\"\"\n return \"example@gmail.com\"\n```\n\nAs seen in the above example, the `get_attribute_value` method takes in three arguments: `ace`, `attribute_path` and `ctx`. The `ace` is a string value indicating for which access control element the attribute value is being requested. This argument will be set to either `\"subject\"`, `\"resource\"`, `\"action\"`, or `\"context\"`. The `attribute_path` argument is a string in [ObjectPath](http://objectpath.org/) notation denoting the attribute for which the value is being requested. The `ctx` argument is an [EvaluationContext](#evaluationcontext) object. The primary purpose of this argument is to retrieve values of other attributes. A common use-case would be to return values conditioned upon the values of other attributes.\n\n```python\n# An email attribute provider class\nclass EmailAttributeProvider(AttributeProvider):\n def get_attribute_value(self, ace, attribute_path, ctx):\n # Return email for Max\n if ctx.get_attribute_value(\"subject\", \"$.name\") == \"Max\":\n return \"max@gmail.com\"\n # Else return default email\n return \"default@gmail.com\"\n```\n\nLastly, if the `AttributeProvider` does not contain value for an attribute, the `get_attribute_value` must return `None`.\n\n*[Back to top](#py-abac)*\n\n### EvaluationContext\n\nAn `EvaluationContext` object is created by the `PDP` during policy evaluation. This object is used by the `PDP` for retrieval of attribute values for which the policy is defined. It has following properties:\n\n```python\n# The target ID for subject access control element\nctx.subject_id \n\n# The target ID for resource access control element\nctx.resource_id\n\n# The target ID for action access control element\nctx.action_id\n\n# Lookup a value for an attribute of an access control element\nctx.get_attribute_value(ace: str, attribute_path: str)\n```\nDuring retrieval, the `EvaluationContext` first checks for attribute value in the `Request` object. If the value is not found, it then checks all the `AttributeProvider` objects sequentially.\n\n*[Back to top](#py-abac)*\n\n## Policy Language\n\nThis section presents the JSON-based policy language for py-ABAC. There are two subsections. The first subsection discusses JSON structure of a policy, while the latter about the access request. \n\n### Policy\n\nA policy structure consists of `uid`, `description`, `conditions`, `targets`, `effect`, and `priority` fields. The JSON schema is given by\n\n```\n{ \n \"uid\": , \n \"description\": , \n \"rules\": , \n \"targets\": , \n \"effect\": , \n \"priority\": \n}\n```\n\nwhere `` and `` are JSON blocks discussed in detail in the [Rules Block](#rules-block) and [Targets Block](#targets-block) subsections. Essentially, the `\"targets\"` and `\"rules\"` fields are used to define conditions on the attributes of access control elements. When these conditions are satisfied, the policy applies and the value for the `\"effect\"` field is returned by the `PDP`. Thus `\"effect\"` is the returned decision of the policy and can be either `\"allow\"` or `\"deny\"`. The `\"uid\"` field is a string value that uniquely identifies a policy. As the name suggests, the `\"description\"` field stores description of the policy. Finally, `\"priority\"` provides a numeric value indicating the weight of the policy when its decision conflicts with other policy under the `HighestPriority` evaluation algorithm. By default, this field is set to `0` for all policies.\n\n#### Targets vs Rules\n\nThe concept of `\"targets\"` and `\"rules\"` in py-ABAC is derived from the XACML standard. Both are used to define conditions on attributes during policy creation. There is however a basic distinction between the two. This distinction will become more clear in the following sections. From a conceptual standpoint, `\"targets\"` states for which access control elements a policy applies. In other words, targets of a policy. The `\"rules\"` on the other-hand define the conditions on the attributes of the targets. To illustrate this point, lets consider a system with two users, \"Sam\" and \"John\". Each user has an attribute called \"age\". Suppose we want to create a policy where \"Sam\" can access the system only if he is above 18 years old. To achieve this, we set the target of the policy to \"Sam\" while the rule to the condition \"age\" > 18. The exact syntax to do so is shown in the following sections.\n\n#### Targets Block\n\nThe targets block specifies for which access control elements a policy applies. This block contains one or more 'ID' attribute values for `subject`, `resource`, and `action` fields. Thus in py-ABAC it is mandatory that these three access control elements have a string valued ID attribute in the `Request` object. The JSON schema for the block is\n\n```\n{ \n \"subject_id\": [\"\", \"\", ... ], \n \"resource_id\": [\"\", \"\", ... ], \n \"action_id\": [\"\", \"\", ... ] \n} \n```\n\nwhere `` denotes string values of the \u2018ID\u2019 attribute. The array here acts as an implicit OR operator. Furthermore wild-carded values for `` are also supported:\n\n```json\n{ \n \"subject_id\": [\"a\", \"b\"], \n \"resource_id\": [\"ab*\"], \n \"action_id\": [\"*\"] \n}\n```\n\nThis example states that the policy is only applicable when the subject ID is either set to \u201ca\u201d or \u201cb\u201d, and when the resource ID starts with \u201cab\u201d. The action can have any ID value. \n\nFor convince, the array can be omitted when only a single `` is to be set for a filed. Thus the above target block can also be defined as\n\n```json\n{ \n \"subject_id\": [\"a\", \"b\"], \n \"resource_id\": \"ab*\", \n \"action_id\": \"*\" \n}\n```\n\nNote that when no target block is explicitly specified, the policy is considered to be applicable for all targets as py-ABAC uses the following default: \n\n```json\n{ \n \"subject_id\": \"*\", \n \"resource_id\": \"*\", \n \"action_id\": \"*\" \n} \n```\n\n#### Rules Block\n\nRules are Boolean expressions defined on the attributes of the targeted access control elements. The JSON schema is given by\n\n```json\n{ \n \"subject\": \"\", \n \"resource\": \"\", \n \"action\": \"\", \n \"context\": \"\" \n} \n```\nwith `` being a JSON block for Boolean expression.\n\nA policy is considered applicable only when each of the Boolean expressions are satisfied. These expressions define constraints on the attribute values of the access control elements. The constraints can be as simple as those involving only a single attribute, or can be complex involving multiple attributes. A simple Boolean expression consists of a key-value pair as shown below:\n\n```json\n{\"\": \"\"}\n```\n\nThe key specifies the attribute in [ObjectPath](http://objectpath.org/) notation while the value is a conditional expression. The `` is again a JSON block specifying the requirements that the attribute value needs to meet. The different supported condition expressions are shown in [Condition Blocks](#condition-blocks) subsection. As an example, the conditional block for the requirement that \"name\" attribute of subject field should be \"Max\" is shown below:\n\n```json\n{\n \"subject\": { \n \"$.name\": { \n \"condition\": \"Eq\", \n \"value\": \"Max\" \n } \n } \n}\n```\n\nSometimes conditions on a single attribute does not suffice and constraints on multiple attributes connected by logical relations like AND or OR are required. In py-ABAC, this is achieved by using in-built JSON data structures *object* and *array* as implicit logical operators. An *object* is implicitly an AND operator which would be evaluated to true only if all the included key-value pairs are evaluated to true. Similarly, an *array* is implicitly an OR operator which would be evaluated to true as long as at least one of its members is evaluated to true. For an example see the following conditional blocks:\n\n```json\n{ \n \"subject\": { \n \"$.firstName\": { \n \"condition\": \"Eq\",\n \"value\": \"Carl\"\n }\n }, \n \"$.lastName\": { \n \"condition\": \"Eq\", \n \"value\": \"Rubin\" \n }, \n \"resource\": [ \n { \n \"$.name\": { \n \"condition\": \"Eq\", \n \"value\": \"Default\" \n } \n }, \n { \n \"$.type\": { \n \"condition\": \"Eq\", \n \"value\": \"Book\" \n } \n } \n ] \n}\n```\n\nThe overall rule states that the subject should have an attribute \"firstName\" valued \"Carl\" AND \"lastName\" valued \"Rubin\". Similarly, the resource should have an attribute \"name\" valued \"Default\" OR \"type\" valued \"Book\".\n\n#### Condition Blocks\n\nThere are basically six types of `` blocks supported in py-ABAC: *Logic,* *Numeric*, *String*, *Collection*, Object, and *Other*. The JSON schema and examples for each are shown below:\n\n##### Logic Condition Block\n\n| **JSON Schema** | **Description** | **Example** |\n| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n| ```{ \"condition\": \"\", \"values\": \"> \"}
``` | *condition*: specifies the type of logic condition. The different possible values are: \"AllOf\": perform logical AND operation on items in *values*\"AnyOf\": perform logical OR operation on items in *values* *values*: contains a list of ConditionJSON objects | { \"condition\": \"AllOf\", \"values\": [ { \"condition\": \"Lt\", \"value\": 1.5 }, { \"condition\": \"Gt\", \"value\": 0.5 }] } |\n| { \"condition\": \"Not\", \"value\": } | *condition*: specifies logic \"Not\" condition. *value*: contains a ConditionJSON object | { \"condition\": \"Not\", \"value\": { \"condition\": \"Eq\", \"value\": 1.5 } } |\n\n##### Numeric Condition Block\n\n| **JSON Schema** | **Description** | **Example** |\n| ------------------------------------------------ | ------------------------------------------------------------ | -------------------------------------------- |\n| { \"condition\": , \"value\": } | *condition*: specifies the type of numeric condition. The different possible values are: \"Eq\": attribute value is equal to that in *value*\"Gt\": attribute value is greater than that in *value*\"Lt\": attribute value is less than that in *value*\"Gte\": attribute value is greater than equal to that in *value*\"Lte\": attribute value is less than equal to that in *value* *value*: contains a number. This can be a float or an int. | { \"condition\": \"Lte\", \"value\": 1.5 } |\n\n##### Collection Condition Block\n\n| **JSON Schema** | **Description** | **Example** |\n| ---------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |\n| { \"condition\": , \"values\": } | *condition*: specifies the type of collection condition. The different possible values are: \"AnyIn\": one or more of the values for attribute are in *values*\"AllIn\": all the values for attribute are in *values* *values*: collection of primitive type values like string, int ,float, etc | { \"condition\": \"AnyIn\", \"values\": [ \"Example1\", \"Example2\" ] } |\n\n##### Object Condition Block\n\n##### Other Condition Block\n\n| **JSON Schema** | **Description** | **Example** |\n| ---------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------- |\n| { \"condition\": \"CIDR\", \"value\": } | *condition*: specifies \"CIDR\" network block condition. The attribute value should be an IP address within the CIDR block to satisfy this condition. *values*: CIDR block as string type | { \"condition\": \"CIDR\", \"value\": \"192.168.0.0/16\" } |\n| { \"condition\": \"Any\" } | *condition*: specifies \"Any\" condition. The attribute can have any value. This condition only fails when the attribute for which this condition is defined does not exist. | { \"condition\": \"Any\" } |\n| { \"condition\": \"Exists\" } | *condition*: specifies \"Exists\" condition. This condition is satisfied when the attribute for which this condition is defined exists. | { \"condition\": \"Exists\" } |\n\n*[Back to top](#py-abac)*\n\n### Access Request\n\nAn access request is a data object sent by PEP to PDP. This object contains all the information needed by the PDP to evaluate the policies and return access decision. The JSON schema of the object is given by\n\n```json\n{ \n \"subject\": { \n \"id\": \"\", \n \"attributes\": \"\" \n }, \n \"resource\": { \n \"id\": \"\", \n \"attributes\": \"\" \n }, \n \"action\": { \n \"id\": \"\", \n \"attributes\": \"\" \n }, \n \"context\": \"\" \n}\n```\n\nwhere `` is just a JSON block containing one or more attribute-value pairs. An example request is shown below:\n\n```json\n{\n \"subject\": {\n \"id\": \"a\",\n \"attributes\": {\n \"firstName\": \"Carl\",\n \"lastName\": \"Right\"\n }\n },\n \"resource\": {\n \"id\": \"a\",\n \"attributes\": {\n \"name\": \"Calendar\"\n }\n },\n \"action\": {\n \"id\": \"\",\n \"attributes\": {}\n },\n \"context\": {}\n}\n```\n\n*[Back to top](#py-abac)*\n\n## Logging\n\npy-ABAC follows a common logging pattern for libraries:\n\nIts corresponding modules log all the events that happen but the log messages by default are handled by `NullHandler`. It's up to the outer code/application to provide desired log handlers, filters, levels, etc.\n\nFor example:\n\n```python\nimport logging\n\nroot = logging.getLogger()\nroot.setLevel(logging.INFO)\nroot.addHandler(logging.StreamHandler())\n\n... # here go all the py_abac calls.\n```\n\n*[Back to top](#py-abac)*\n\n## Milestones\n\nMost valuable features to be implemented in the order of importance:\n\n- In-Memory Storage\n- SQL Storage\n- Caching mechanism for Storage\n- YAML-based language for declarative policy definitions\n- File Storage\n\n*[Back to top](#py-abac)*\n\n## Acknowledgements\n\nThe conceptual and implementation design of py-ABAC stems from the [XACML](https://en.wikipedia.org/wiki/XACML) standard and the ABAC python SDK [Vakt](https://github.com/kolotaev/vakt).\n\n*[Back to top](#py-abac)*\n\n## Development\n\nTo hack py-ABAC locally run:\n\n```\n$ pip install -e .[dev] \t\t \t\t\t\t# to install all dependencies\n$ docker run --rm -d -p 27017:27017 mongo\t\t# Run mongodb server on docker\n$ pytest --cov=py_abac tests/ \t\t\t\t# to get coverage report\n$ pylint py_abac \t\t\t\t# to check code quality with PyLint\n```\n\nOptionally you can use `make` to perform development tasks.\n\n*[Back to top](#py-abac)*\n\n## License\n\nThe source code is licensed under Apache License Version 2.0\n\n*[Back to top](#py-abac)*", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ketgo/py-abac", "keywords": "ACL ABAC access-control policy security authorization permission", "license": "Apache 2.0 license", "maintainer": "", "maintainer_email": "", "name": "py-abac", "package_url": "https://pypi.org/project/py-abac/", "platform": "", "project_url": "https://pypi.org/project/py-abac/", "project_urls": { "Homepage": "https://github.com/ketgo/py-abac" }, "release_url": "https://pypi.org/project/py-abac/0.2.0/", "requires_dist": null, "requires_python": ">=3.4", "summary": "Attribute-based access control (ABAC)", "version": "0.2.0" }, "last_serial": 5986685, "releases": { "0.2.0": [ { "comment_text": "", "digests": { "md5": "001db52651adb031eba74dd75620283c", "sha256": "3824ecffd58e1b060e38ec98293c74027f5a2598770f24465571acca57ab718c" }, "downloads": -1, "filename": "py_abac-0.2.0.tar.gz", "has_sig": false, "md5_digest": "001db52651adb031eba74dd75620283c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 49629, "upload_time": "2019-10-16T22:30:30", "url": "https://files.pythonhosted.org/packages/6d/7c/e7e23ca56a8e7eb63562a79131f061f3122df158ffb9fc0f28206360ab14/py_abac-0.2.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "001db52651adb031eba74dd75620283c", "sha256": "3824ecffd58e1b060e38ec98293c74027f5a2598770f24465571acca57ab718c" }, "downloads": -1, "filename": "py_abac-0.2.0.tar.gz", "has_sig": false, "md5_digest": "001db52651adb031eba74dd75620283c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 49629, "upload_time": "2019-10-16T22:30:30", "url": "https://files.pythonhosted.org/packages/6d/7c/e7e23ca56a8e7eb63562a79131f061f3122df158ffb9fc0f28206360ab14/py_abac-0.2.0.tar.gz" } ] }