Document Pomerium Policy Language (#2784) (#2789)

* Init PPL doc

* copy edits

* Apply suggestions from code review

Co-authored-by: Caleb Doxsey <cdoxsey@pomerium.com>

* Apply suggestions from code review

Co-authored-by: bobby <1544881+desimone@users.noreply.github.com>

* Update docs/docs/topics/ppl.md

* whitespace cleanup

Co-authored-by: Caleb Doxsey <cdoxsey@pomerium.com>
Co-authored-by: bobby <1544881+desimone@users.noreply.github.com>

Co-authored-by: Alex Fornuto <afornuto@pomerium.com>
Co-authored-by: Caleb Doxsey <cdoxsey@pomerium.com>
Co-authored-by: bobby <1544881+desimone@users.noreply.github.com>
This commit is contained in:
backport-actions-token[bot] 2021-11-29 17:15:43 -06:00 committed by GitHub
parent 86614b5b0e
commit 91c1b249a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 172 additions and 0 deletions

View file

@ -179,6 +179,7 @@ module.exports = {
"topics/data-storage", "topics/data-storage",
"topics/getting-users-identity", "topics/getting-users-identity",
"topics/original-request-context", "topics/original-request-context",
"topics/ppl",
"topics/production-deployment", "topics/production-deployment",
"topics/programmatic-access", "topics/programmatic-access",
"topics/single-sign-out", "topics/single-sign-out",

171
docs/docs/topics/ppl.md Normal file
View file

@ -0,0 +1,171 @@
---
title: Pomerium Policy Language
description: >-
This article covers Pomerium Policy Language, used to define secure access policies for routes.
---
# Pomerium Policy Language
Pomerium Policy Language (**PPL**) is a [yaml]-based notation for creating easy and flexible authorization policies. This document covers the usage of PPL and provides several example policies.
## At a Glance
Each PPL policy has at the top level a set of `allow` or `deny` actions, with a list of logical operators, criteria, matchers, and values underneath. For example:
```yaml
allow:
and:
- domain:
is: example.com
- groups:
has: admin
deny:
or:
- user:
is: user1@example.com
- user:
is: user2@example.com
```
This policy will allow a user with an email address at `example.com` who **is also** a member of the `admin` group. It will deny `user1` **or** `user2`, regardless of their domain and group membership.
## Rules
A PPL document is either an object or an array of objects. The object represents a rule where the action is the key and the value is an object containing the logical operators.
## Actions
Only two actions are supported: `allow` and `deny`. `deny` takes precedence over `allow`. More precisely: a user will have access to a route if **at least one** `allow` rule matches and **no** `deny` rules match.
## Logical Operators
A logical operator combines multiple criteria together for the evaluation of a rule. There are 4 logical operators: `and`, `or`, `not` and `nor`.
::: details More on Logical Operators
Given the following example with `OPERATOR` replaced:
```yaml
allow:
OPERATOR:
- domain:
is: example.com
- groups:
has: admin
```
If `and` is used, the user will have access if their email address ends in `example.com` **and** they are a member of the admin group. **(A ∧ B)**
If `or` is used, the user will have access if their email address ends in `example.com` **or** they are a member of the admin group. **(A B)**
If `not` is used, the user will have access if their email address does not end in `example.com` **and** they are not a member of the `admin` group. **(¬A ∧ ¬B)**
If `nor` is used, the user will have access if their email address does not end in `example.com` **or** they are not a member of the admin group. **(¬A ¬B)**
:::
## Criteria
Criteria in PPL are represented as an object where the key is the name and optional sub-path of the criterion, and the value changes depending on which criterion is used. A sub-path is indicated with a `/` in the name:
```yaml
allow:
and:
- claim/family_name: Smith
```
PPL supports many different criteria:
| Criterion Name | Data Format | Description |
| ---------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accept` | Anything. Typically `true`. | Always returns true, thus always allowing access. Equivalent to the [`allow_public_unauthenticated_access`] option. |
| `authenticated_user` | Anything. Typically `true`. | Always returns true for logged-in users. Equivalent to the [`allow_any_authenticated_user`] option. |
| `claim` | Anything. Typically a string. | Returns true if a token claim matches the supplied value **exactly**. The claim to check is determined via the sub-path. <br/> For example, `claim/family_name: Smith` matches if the user's `family_name` claim is `Smith`. |
| `cors_preflight` | Anything. Typically `true`. | Returns true if the incoming request uses the `OPTIONS` method and has both the `Access-Control-Request-Method` and `Origin` headers. Used to allow [CORS pre-flight requests]. |
| `domain` | String Matcher | Returns true if the logged-in user's email address domain (the part after `@`) matches the given value. |
| `email` | String Matcher | Returns true if the logged-in user's email address matches the given value. |
| `groups` | List Matcher | Returns true if the logged-in user is a member of the given group. |
| `invalid_client_certificate` | Anything. Typically `true`. | Returns true if the incoming request has an invalid client certificate. A default `deny` rule using this criterion is added to all Pomerium policies when an mTLS [client certificate authority] is set. |
| `pomerium_routes` | Anything. Typically `true`. | Returns true if the incoming request is for the special `.pomerium` routes. A default `allow` rule using this criterion is added to all Pomerium policies. |
| `reject` | Anything. Typically `true`. | Always returns false. The opposite of `accept`. |
| `user` | String Matcher | Returns true if the logged-in user's id matches the given value. |
[Pomerium Enterprise] supports all the open source criteria, but also supports these additional criteria:
| Criterion Name | Data Format | Description |
| -------------- | ------------------- | -------------------------------------------------------------------------------------- |
| `date` | Date Matcher | Returns true if the time of the request matches the constraints. |
| `day_of_week` | Day of Week Matcher | Returns true if the day of the request matches the constraints. |
| `time_of_day` | Time of Day Matcher | Returns true if the time of the request (for the current day) matches the constraints. |
## Matchers
### String Matcher
A string matcher is an object with operators as keys. It supports the following operators: `contains`, `ends_with`, `is` and `starts_with`. For example:
```yaml
allow:
and:
- email:
starts_with: 'admin@'
```
### List Matcher
A list matcher is an object with operators as keys. It supports the following operators: `has`. For example:
```yaml
allow:
and:
- groups:
has: 'admin'
```
## Date Matcher
The date matcher is an object with operators as keys. It supports the following operators: `after` and `before`. The values are [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) date strings. `after` means that the time of the request must be after the supplied date and `before` means that the time of the request must be before the supplied date. For example:
```yaml
allow:
and:
- date:
after: 2020-01-02T16:20:00
before: 2150-01-02T16:20:00
```
## Day of Week Matcher
The day of week matcher is a **string**. The string can either be `*`, a comma-separated list of days, or a dash-separated list of days.
- `*` matches all days.
- `,` matches either day (e.g. `mon,wed,fri`).
- `-` matches a range of days. (e.g. `mon-fri`). Days can be specified as English full day names, or as 3 character abbreviations. For example:
```yaml
allow:
and:
- day_of_week: tue-fri
```
## Time of Day Matcher
The time of day matcher is an object with operators as keys. It supports the following operators: `timezone`, `after`, and `before`.
`timezone` is required and specifies the timezone to use when interpreting the supplied times. It is recommended to use city names (like `America/Phoenix`) instead of standard timezone abbreviations because standard timezones change throughout the year (i.e. EST becomes EDT and back again).
`after` means the time of the request must be after the supplied time and `before` means that the time of the request must be before the supplied time. For example:
```yaml
allow:
and:
- time_of_day:
timezone: UTC
after: 2:20:00
before: 4:30PM
```
[`allow_public_unauthenticated_access`]: /reference/readme.md#public-access
[`allow_any_authenticated_user`]: /reference/readme.md#allow-any-authenticated-user
[CORS pre-flight requests]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests
[client certificate authority]: /reference/readme.md#client-certificate-authority
[Pomerium Enterprise]: /enterprise/about.md
[yaml]: https://en.wikipedia.org/wiki/YAML