This commit is contained in:
Mathieu Leplatre 2018-01-30 18:21:33 +01:00
Родитель 856c41d532
Коммит 2c9b506574
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 767B105F81A15CDD
13 изменённых файлов: 732 добавлений и 308 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -4,7 +4,8 @@ coverage.txt
policies.yaml
vendor/
node_modules/
api-docs/
docs/_build
.venv
__pycache__/
*.pyc
examples/python/records/*.json

Просмотреть файл

@ -62,10 +62,15 @@ docker-build: main
docker-run:
docker run --name doorman --rm mozilla/doorman
api-docs: api/openapi.yaml
# https://github.com/sourcey/spectacle
spectacle --target-dir api-docs api/openapi.yaml
.venv/bin/sphinx-build:
virtualenv .venv
.venv/bin/pip install -r docs/requirements.txt
api-docs-publish: api-docs
docs: .venv/bin/sphinx-build docs/*.rst
.venv/bin/sphinx-build -a -W -n -b html -d docs/_build/doctrees docs docs/_build/html
@echo
@echo "Build finished. The HTML pages are in $(SPHINX_BUILDDIR)/html/index.html"
docs-publish: docs
# https://github.com/tschaub/gh-pages
gh-pages -d api-docs

201
README.md
Просмотреть файл

@ -1,210 +1,15 @@
Doorman
=======
# Doorman
![](logo.svg)
![](docs/logo.svg)
*Doorman* is an **authorization micro-service**.
- [API Documentation](https://mozilla.github.io/doorman/)
- [Examples](examples/)
- [Documentation](https://doorman.readthedocs.io)
[![Build Status](https://travis-ci.org/mozilla/doorman.svg?branch=master)](https://travis-ci.org/mozilla/doorman)
[![Coverage Status](https://coveralls.io/repos/github/mozilla/doorman/badge.svg?branch=master)](https://coveralls.io/github/mozilla/doorman?branch=master)
[![Go Report](https://goreportcard.com/badge/github.com/mozilla/doorman)](https://goreportcard.com/report/github.com/mozilla/doorman)
*Doorman* responds to authorization requests based on a set of rules (policies files).
Having a centralized access control service has several advantages:
- it clearly dissociates authentication from authorization
- it provides a standard and generic permissions system to services developers
- it facilitates permissions management across services (eg. makes revocation easier)
- it allows authorizations monitoring, metrics, anomaly detection
## Run
```
docker run \
-e POLICIES=/config \
-v ./examples/python:/config \
-p 8000:8080 \
--name doorman \
mozilla/doorman
```
*Doorman* is now ready to respond authorization requests on `http://localhost:8080`. See [API docs](https://mozilla.github.io/doorman/).
## Policies
Policies are defined in YAML files for each consuming service, locally or in remote (private) Github repos, as follow:
```yaml
service: https://service.stage.net
identityProvider: https://auth.mozilla.auth0.com/
tags:
superusers:
- userid:maria
- group:admins
policies:
-
id: authors-superusers-delete
description: Authors and superusers can delete articles
principals:
- role:author
- tag:superusers
actions:
- delete
resources:
- article
effect: allow
```
* **service**: the unique identifier of the service
* **identityProvider** (*optional*): when the identify provider is not empty, *Doorman* will verify the Access Token or the ID Token provided in the authorization request to authenticate the request and obtain the subject profile information (*principals*)
* **tags**: Local «groups» of principals in addition to the ones provided by the Identity Provider
* **actions**: a domain-specific string representing an action that will be defined as allowed by a principal (eg. `publish`, `signoff`, …)
* **resources**: a domain-specific string representing a resource. Preferably not a full URL to decouple from service API design (eg. `print:blackwhite:A4`, `category:homepage`, …).
* **effect**: Use `effect: deny` to deny explicitly. Requests that don't match any rule are denied.
### Principals
The principals is a list of prefixed strings to refer to the «user» as the combination of ids, emails, groups, roles…
Supported prefixes:
* ``userid:``: provided by Identity Provider (IdP)
* ``tag:``: local tags
* ``role:``: provided in context of authorization request (see below)
* ``email:``: provided by IdP
* ``group:``: provided by IdP
Example: `["userid:ldap|user", "email:user@corp.com", "group:Employee", "group:Admins", "role:editor"]`
## Settings
Via environment variables:
* ``POLICIES``: space separated locations of YAML files with policies. They can be **single files**, **folders** or **Github URLs** (default: ``./policies.yaml``)
* ``GITHUB_TOKEN``: Github API token to be used when fetching policies files from private repositories
Advanced:
* ``PORT``: listen (default: ``8080``)
* ``GIN_MODE``: server mode (``release`` or default ``debug``)
* ``LOG_LEVEL``: logging level (``fatal|error|warn|info|debug``, default: ``info`` with ``GIN_MODE=release`` else ``debug``)
* ``VERSION_FILE``: location of JSON file with version information (default: ``./version.json``)
> Note: the ``Dockerfile`` contains different default values, suited for production.
## Advanced policies rules
### Regular expressions
Regular expressions begin with ``<`` and end with ``>``.
```yaml
principals:
- userid:<[peter|ken]>
resources:
- /page/<.*>
```
> Note: regular expressions are not supported in tags members definitions.
### Conditions
The conditions are **optional** on policies and are used to match field values from the authorization request context.
The context value ``remoteIP`` is forced by the server.
For example:
```yaml
policies:
-
description: Allow everything from dev environment
conditions:
env:
type: StringEqualCondition
options:
equals: dev
```
There are several ``type``s of conditions:
**Field comparison**
* type: ``StringEqualCondition``
For example, match ``request.context["country"] == "catalunya"``:
```yaml
conditions:
country:
type: StringEqualCondition
options:
equals: catalunya
```
**Field pattern**
* type: ``StringMatchCondition``
For example, match ``request.context["bucket"] ~= "blocklists-.*"``:
```yaml
conditions:
bucket:
type: StringMatchCondition
options:
matches: blocklists-.*
```
**Match principals**
* type: ``MatchPrincipalsCondition``
For example, allow requests where ``request.context["owner"]`` is in principals:
```yaml
conditions:
owner:
type: MatchPrincipalsCondition
```
> Note: This also works when a the context field is list (e.g. list of collaborators).
**IP/Range**
* type: ``CIDRCondition``
For example, match ``request.context["remoteIP"]`` with [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation):
```yaml
conditions:
remoteIP:
type: CIDRCondition
options:
# mask 255.255.0.0
cidr: 192.168.0.1/16
```
## Run from source
make serve -e POLICIES=sample.yaml
## Run tests
make test
## Generate API docs
make api-docs
## Build docker container
make docker-build
## License
* MPLv2.0

Просмотреть файл

@ -3,101 +3,6 @@ info:
title: "Mozilla Doorman"
description: |
*Doorman* is an **authorization micro-service** that allows to checks if an arbitrary subject is allowed to perform an action on a resource, based on a set of rules (policies).
It takes a set of YAML files like the one below and answers authorization requests by matching the rules:
```YAML
service: https://api.service.org
identityProvider: https://auth.mozilla.auth0.com/
policies:
-
id: crud-articles
description: Editors can CRUD articles
principals:
- role:editor
actions:
- create
- read
- delete
- update
resources:
- article
effect: allow
```
### Workflow with OpenID
When a service takes advantage of *Doorman*, a typical workflow is:
1. Users obtain an access token from an Identity Provider (eg. Auth0)
1. They use it to call a service API endpoint
1. The service posts an authorization request on *Doorman* to check if the user is allowed to perform a specific action
1. *Doorman* uses the `Origin` request header to select the set of policies to match
1. *Doorman* fetches the user infos using the provided access token and builds a list of strings (principals) to characterize this user
1. *Doorman* matches the policies and returns true or allowed, along with the list of principals
1. Based on the *Doorman* response, the service denies the original request or executes it
*Doorman* will verify that the specified Access token (or ID token) is valid.
The authorization request **principals** will be built from the user profile information like this:
* `"sub"`: `userid:{}`
* `"email"`: `email:{}` (*optional*)
* `"groups"`: `group:{}, group:{}, ...` (*optional*)
### Without authentication/OpenID
If the identity provider is not configured for a service, no authentication is required and the principals
are posted in the authorization body.
It is not especially recommended, but it can give a certain amount of flexibility when authentication is fully managed on the service.
A typical workflow in this case would be:
1. Users call the service API endpoint
1. The service authenticates the user and builds the list of principals
1. The service posts an authorization request on *Doorman* containing the list of principals to check if the user is allowed
### API Summary
Basically, use **POST /allowed** to check authorization requests.
**Request**:
```HTTP
POST /allowed HTTP/1.1
Origin: https://api.service.org
Authorization: Bearer f2457yu86yikhmbh
{
"action" : "delete",
"resource": "articles/doorman-introduce",
"context": {
"env": "stage",
"roles": ["editor"]
}
}
```
**Response**:
```HTTP
HTTP/1.1 200 OK
Content-Type: application/json
{
"allowed": true,
"principals": [
"role:editor",
"userid:myself"
]
}
```
version: "0.1"
contact:
url: "irc://irc.mozilla.org:6696/#product-delivery"
@ -117,7 +22,7 @@ paths:
post:
summary: Check authorization request
description: |
Are those `principals` allowed to perform this `action` on this `resource` in this `context`?
Are those ``principals`` allowed to perform this ``action`` on this ``resource`` in this ``context``?
With authentication enabled, the principals are either read from the Identity Provider user info endpoint or directly from the JSON Web Token payload
if an ID token is provided.
@ -132,13 +37,13 @@ paths:
name: Origin
type: string
description: |
The service identifier (eg. `https://api.service.org`). It must match one of the known service from the policies files.
The service identifier (eg. ``https://api.service.org``). It must match one of the known service from the policies files.
- in: header
name: Authorization
type: string
description: |
With OpenID enabled, a valid Access token (or JSON Web ID Token) must be provided in the `Authorization` request header.
With OpenID enabled, a valid Access token (or JSON Web ID Token) must be provided in the ``Authorization`` request header.
(eg. `Bearer eyJ0eXAiOiJKV1QiLCJhbG...9USXpOalEzUXpV`)
- in: body
@ -155,22 +60,22 @@ paths:
description: |
**Only without authentication**
Arbitrary list of strings (eg. `userid:alice`, `group:editors`).
Arbitrary list of strings (eg. ``userid:alice``, ``group:editors``).
type: array
items:
type: string
action:
description: Any domain specific action (eg. `read`, `delete`, `signoff`)
description: Any domain specific action (eg. ``read``, ``delete``, ``signoff``)
type: string
resource:
description: Any resource (eg. `blocklist`, `/update/rules/35`)
description: Any resource (eg. ``blocklist``, ``rules-<.*>``)
type: string
context:
description: |
The context can contain any extra information to be matched in policies conditions.
The context field `remoteIP` will be forced by the server.
The values provided in the `roles` context field will expand the principals with extra `role:{}` values.
The context field ``remoteIP`` will be forced by the server.
The values provided in the ``roles`` context field will expand the principals with extra ``role:{}`` values.
type: object
properties:
@ -196,7 +101,7 @@ paths:
message:
type: string
example:
message: Missing `Origin` request header
message: Missing ``Origin`` request header
"401":
description: "OpenID token is invalid."
"200":
@ -220,7 +125,7 @@ paths:
post:
summary: "Reload the policies"
description: |
Reload the policies (synchronously). This endpoint is meant to be used as a Web hook when policies files were changed.
Reload the policies (synchronously). This endpoint is meant to be used as a Web hook when policies files were changed upstream.
> It would be wise to limit the access to this endpoint (e.g. by IP on reverse proxy)

146
docs/api.rst Normal file
Просмотреть файл

@ -0,0 +1,146 @@
.. _api:
API
===
Summary
-------
Basically, authorization requests are checked using **POST /allowed**.
* The ``Origin`` request header specifies the service to match policies from.
* The ``Authorization`` request header provides the OpenID :term:`Access Token` to authenticate the request.
**Request**:
.. code-block:: HTTP
POST /allowed HTTP/1.1
Origin: https://api.service.org
Authorization: Bearer f2457yu86yikhmbh
{
"action" : "delete",
"resource": "articles/doorman-introduce",
}
**Response**:
.. code-block:: HTTP
HTTP/1.1 200 OK
Content-Type: application/json
{
"allowed": true,
"principals": [
"userid:ada",
"email:ada.lovelace@eff.org",
"group:scientists",
"group:history"
]
}
Principals
----------
The authorization request :term:principals will be built from the user profile information like this:
* ``"sub"``: ``userid:{}``
* ``"email"``: ``email:{}`` (*optional*)
* ``"groups"``: ``group:{}, group:{}, ...`` (*optional*)
They will be matched against those specified in the policies rules to determine if the authorization request is denied or allowed.
Authentication
--------------
*Doorman* relies on OpenID to authenticate requests.
It will use the ``service`` and ``identityProvider`` fields from the service policies file to fetch the user profile information.
The ``Origin`` request header should match one of the services defined in the policies files.
The ``Authorization`` request header should contain a valid :term:`Access Token`, prefixed with ``Bearer ``.
This access token must have been requested with the ``openid profile`` scope for *Doorman* to be able to fetch the profile information (See `Auth0 docs <https://auth0.com/docs/tokens/access-token#access-token-format>`_).
The userinfo URI endpoint is then obtained from the metadata available at ``{identityProvider}/.well-known/openid-configuration``.
If the obtention of user infos is denied by the :term:`Identity Provider`, the authorization request is obviously denied.
Using ID tokens
'''''''''''''''
*Doorman* can verify and read user information from JWT :term:`ID tokens`. Since the ID token payload contains the user information, it saves a roundtrip to the Identity Provider when handling authorization requests.
For this to work, the ``service`` value in the policies file must match the ``audience`` value configured on the Identity Provider — the unique identifier of the target API. For example, in `Auth0 <https://auth0.com>`_ it can look like this: ``SLocf7Sa1ibd5GNJMMqO539g7cKvWBOI``.
.. important::
When using JWT :term:`ID tokens`, only the validity of the token will be checked. In other words, users that are revoked from the Identity Provider after their ID token was issued will still considered authenticated until the token expires.
Without authentication
''''''''''''''''''''''
If the identity provider is not configured for a service (explicit empty value), no authentication is required and the principals are posted in the authorization body.
.. code-block:: HTTP
POST /allowed HTTP/1.1
Origin: https://api.service.org
Authorization: Bearer f2457yu86yikhmbh
{
"action" : "delete",
"resource": "articles/doorman-introduce",
"principals": [
"userid:mickaeljfox",
"email:mj@fox.com",
"group:actors"
]
}
It is not especially recommended, but it can give a certain amount of flexibility when authentication is fully managed on the service.
A typical workflow in this case would be:
1. Users call the service API endpoint
1. The service authenticates the user and builds the list of principals
1. The service posts an authorization request on *Doorman* containing the list of principals to check if the user is allowed
.. _api-context:
Context
-------
Authorization requests can carry additional information contain any extra information to be matched in :ref:`policies conditions <policies-conditions>`.
The values provided in the ``roles`` context field will expand the principals with extra ``role:{}`` values.
.. code-block:: HTTP
POST /allowed HTTP/1.1
Origin: https://api.service.org
Authorization: Bearer f2457yu86yikhmbh
{
"action" : "delete",
"resource": "articles/doorman-introduce",
"context": {
"env", "stage",
"roles": ["editor"]
}
}
API Endpoints
-------------
(Automatically generated from `the OpenAPI specs <https://github.com/mozilla/doorman/blob/master/api/openapi.yaml>`_)
.. openapi:: ../api/openapi.yaml

176
docs/conf.py Normal file
Просмотреть файл

@ -0,0 +1,176 @@
# -*- coding: utf-8 -*-
#
# Doorman documentation build configuration file, created by
# sphinx-quickstart on Tue Jan 30 15:41:49 2018.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Custom
from recommonmark.parser import CommonMarkParser
source_parsers = {
'.md': CommonMarkParser,
}
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinxcontrib.openapi',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
source_suffix = ['.rst', '.md']
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Doorman'
copyright = u'2018, Mozilla'
author = u'Mozilla'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'1.0'
# The full version, including alpha/beta/rc tags.
release = u'1.0.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
]
}
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Doormandoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Doorman.tex', u'Doorman Documentation',
u'Mozilla', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'doorman', u'Doorman Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Doorman', u'Doorman Documentation',
author, 'Doorman', 'One line description of project.',
'Miscellaneous'),
]

Двоичные данные
docs/flow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 238 KiB

50
docs/index.rst Normal file
Просмотреть файл

@ -0,0 +1,50 @@
Welcome to Doorman's documentation!
===================================
.. image:: logo.svg
*Doorman* is an **authorization micro-service** that allows to checks if an arbitrary subject is allowed to perform an action on a resource, based on a set of rules (policies).
Having a centralized access control service has several advantages:
- it clearly dissociates authentication from authorization
- it provides a standard and generic permissions system to services developers
- it facilitates permissions management across services (eg. makes revocation easier)
- it allows authorizations monitoring, metrics, anomaly detection
Workflow
========
.. image:: flow.png
It relies on `OpenID Connect <https://en.wikipedia.org/wiki/OpenID_Connect>`_ to authenticate requests. The policies are defined per service and loaded in memory. Authorization requests are logged out.
When a service takes advantage of *Doorman*, a typical workflow is:
#. Users obtain an access token from an Identity Provider (eg. Auth0)
#. They use it to call a service API endpoint
#. The service posts an authorization request on *Doorman* to check if the user is allowed to perform a specific action
#. *Doorman* uses the ``Origin`` request header to select the set of policies to match
#. *Doorman* fetches the user infos using the provided access token and builds a list of strings (*principals*) to characterize this user
#. *Doorman* matches the policies and returns if allowed or not, along with the list of principals
#. Based on the *Doorman* response, the service denies the original request or executes it
Contents
========
.. toctree::
:maxdepth: 2
quickstart
policies
api
misc
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 5.7 KiB

После

Ширина:  |  Высота:  |  Размер: 5.7 KiB

104
docs/misc.rst Normal file
Просмотреть файл

@ -0,0 +1,104 @@
Misc
====
.. _misc-run-source:
Run from source
---------------
.. code-block:: bash
make serve -e "POLICIES=sample.yaml /etc/doorman"
Run tests
---------
.. code-block:: bash
make test
Generate API docs
-----------------
We use `Sphinx <http://www.sphinx-doc.org>`_, therefore the Python ``virtualenv`` command is required.
.. code-block:: bash
make docs
Build docker container
----------------------
.. code-block:: bash
make docker-build
Advanced settings
-----------------
* ``PORT``: listen (default: ``8080``)
* ``GIN_MODE``: server mode (``release`` or default ``debug``)
* ``LOG_LEVEL``: logging level (``fatal|error|warn|info|debug``, default: ``info`` with ``GIN_MODE=release`` else ``debug``)
* ``VERSION_FILE``: location of JSON file with version information (default: ``./version.json``)
Frequently Asked Questions
--------------------------
Why did you do this like that?
''''''''''''''''''''''''''''''
If something puzzles you, looks bad, or is not crystal clear, we would really appreciate your feedback! Please `file an issue <https://github.com/mozilla/doorman/issues>`_! — yes, even if you feel uncertain :)
Why should I use Doorman?
'''''''''''''''''''''''''
*Doorman* saves you the burden of implementing a fined-grained permission system into your service. Plus, it can centralize and track authorizations accross multiple services, which makes permissions management a lot easier.
How is it different than OpenID servers (like Hydra, etc.)?
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
*Doorman* is not responsible of managing users. It relies on an Identity Provider to authenticate requests and focuses on authorization.
What is the difference with my Identity Provider authorizations?
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Identity Providers may have some authorization/permissions system that allow to restrict access using user groups, audience and scopes.
This kind of access control is global for the whole service. *Doorman* provides advanced policies rules that can be matched per action, resource, or any domain specific context.
Why YAML?
'''''''''
Policies files are meant to be edited or at least reviewed by humans. And YAML is relatively human-friendly.
Plus, YAML allows to add comments.
Glossary
--------
.. glossary::
Identity Provider
An identity provider (abbreviated IdP) is a service in charge of managing identity information, and providing authentication endpoints (login forms, tokens manipulation etc.)
Access Token
Access Tokens
An access token is an opaque string that is issued by the Identity Provider.
ID Token
ID Tokens
The ID token is a JSON Web Token (JWT) that contains user profile information (like the user's name, email, and so forth), represented in the form of claims.
Principal
Principals
In *Doorman*, the *principals* is the list of strings that characterize a user. It is built from the user information, tags from the policies file and roles from the authorization request. (see `Wikipedia <https://en.wikipedia.org/wiki/Principal_(computer_security)>`_)

166
docs/policies.rst Normal file
Просмотреть файл

@ -0,0 +1,166 @@
Policies
========
Policies are defined in YAML files for each consuming service as follow:
.. code-block:: YAML
service: https://service.stage.net
identityProvider: https://auth.mozilla.auth0.com/
tags:
superusers:
- userid:maria
- group:admins
policies:
-
id: authors-superusers-delete
description: Authors and superusers can delete articles
principals:
- role:author
- tag:superusers
actions:
- delete
resources:
- article
effect: allow
- **service**: the unique identifier of the service
- **identityProvider** (*optional*): when the identify provider is not empty, *Doorman* will verify the Access Token or the ID Token provided in the authorization header to authenticate the request and obtain the subject profile information (*principals*)
- **tags**: Local «groups» of principals in addition to the ones provided by the Identity Provider
- **actions**: a domain-specific string representing an action that will be defined as allowed by a principal (eg. ``publish``, ``signoff``, …)
- **resources**: a domain-specific string representing a resource. Preferably not a full URL to decouple from service API design (eg. `print:blackwhite:A4`, `category:homepage`, …).
- **effect**: Use ``effect: deny`` to deny explicitly. Requests that don't match any rule are denied.
Settings
--------
Policies can be read locally or in remote (private) Github repos.
Settings are set via environment variables:
* ``POLICIES``: space separated locations of YAML files with policies. They can be **single files**, **folders** or **Github URLs** (default: ``./policies.yaml``)
* ``GITHUB_TOKEN``: Github API token to be used when fetching policies files from private repositories
.. note::
The ``Dockerfile`` contains different default values, suited for production.
Principals
----------
The principals is a list of prefixed strings to refer to the «user» as the combination of ids, emails, groups, roles…
Supported prefixes:
* ``userid:``: provided by Identity Provider (IdP)
* ``tag:``: local tags from policies file
* ``role:``: provided in :ref:`context of authorization requests <api-context>`
* ``email:``: provided by IdP
* ``group:``: provided by IdP
Example: ``["userid:ldap|user", "email:user@corp.com", "group:Employee", "group:Admins", "role:editor"]``
Advanced policies rules
-----------------------
Regular expressions
'''''''''''''''''''
Regular expressions begin with ``<`` and end with ``>``.
.. code-block:: YAML
principals:
- userid:<[peter|ken]>
resources:
- /page/<.*>
.. note::
Regular expressions are not supported in tags members definitions.
.. _policies-conditions:
Conditions
''''''''''
The conditions are **optional** on policies and are used to match field values from the :ref:`authorization request context <api-context>`.
The context value ``remoteIP`` is forced by the server.
For example:
.. code-block:: YAML
policies:
-
description: Allow everything from dev environment
conditions:
env:
type: StringEqualCondition
options:
equals: dev
There are several types of conditions:
**Field comparison**
* type: ``StringEqualCondition``
For example, match ``request.context["country"] == "catalunya"``:
.. code-block:: YAML
conditions:
country:
type: StringEqualCondition
options:
equals: catalunya
**Field pattern**
* type: ``StringMatchCondition``
For example, match ``request.context["bucket"] ~= "blocklists-.*"``:
.. code-block:: YAML
conditions:
bucket:
type: StringMatchCondition
options:
matches: blocklists-.*
**Match principals**
* type: ``MatchPrincipalsCondition``
For example, allow requests where ``request.context["owner"]`` is in principals:
.. code-block:: YAML
conditions:
owner:
type: MatchPrincipalsCondition
.. note::
This also works when a the context field is list (e.g. list of collaborators).
**IP/Range**
* type: ``CIDRCondition``
For example, match ``request.context["remoteIP"]`` with [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation):
.. code-block:: YAML
conditions:
remoteIP:
type: CIDRCondition
options:
# mask 255.255.0.0
cidr: 192.168.0.1/16

63
docs/quickstart.rst Normal file
Просмотреть файл

@ -0,0 +1,63 @@
Quickstart
==========
Policies
--------
Policies are defined in YAML files for each consuming service, locally or in remote (private) Github repos, as follow:
.. code-block:: YAML
service: https://api.service.org
identityProvider: https://api.auth0.com/
policies:
- id: alice-bob-create-keys
description: Alice and Bob can create keys
principals:
- userid:alice
- userid:bob
actions:
- create
resources:
- key
effect: allow
-
id: crud-articles
description: Editors can CRUD articles
principals:
- role:editor
actions:
- create
- read
- delete
- update
resources:
- article
effect: allow
Save it to ``config/api-policies.yaml`` for example.
Run
---
*Doorman* is available as a Docker image (but can also be :ref:`ran from source <misc-run-source>`).
In order to read the local files from the container, we will mount the local ``config`` folder to ``/config``.
We'll then use ``/config`` as the ``POLICIES`` location.
.. code-block:: bash
docker run \
-e POLICIES=/config \
-v ./config:/config \
-p 8000:8080 \
--name doorman \
mozilla/doorman
*Doorman* is now ready to respond authorization requests on `http://localhost:8080`. See :ref:`API docs <api>`!
Examples
--------
See the `examples folder <https://github.com/mozilla/doorman/tree/master/examples>`_ on Github.

3
docs/requirements.txt Normal file
Просмотреть файл

@ -0,0 +1,3 @@
sphinx
sphinxcontrib-openapi
recommonmark