website/docs: improve docs for expressions

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-05-29 21:47:35 +02:00
parent 6232333a52
commit a4c28a28b4
10 changed files with 122 additions and 81 deletions

View File

@ -26,8 +26,8 @@ class BaseEvaluator:
_filename: str _filename: str
def __init__(self): def __init__(self):
# update authentik/policies/expression/templates/policy/expression/form.html # update website/docs/expressions/_objects.md
# update website/docs/policies/expression.md # update website/docs/expressions/_functions.md
self._globals = { self._globals = {
"regex_match": BaseEvaluator.expr_filter_regex_match, "regex_match": BaseEvaluator.expr_filter_regex_match,
"regex_replace": BaseEvaluator.expr_filter_regex_replace, "regex_replace": BaseEvaluator.expr_filter_regex_replace,

View File

@ -38,7 +38,8 @@ class PolicyEvaluator(BaseEvaluator):
def set_policy_request(self, request: PolicyRequest): def set_policy_request(self, request: PolicyRequest):
"""Update context based on policy request (if http request is given, update that too)""" """Update context based on policy request (if http request is given, update that too)"""
# update website/docs/policies/expression.md # update website/docs/expressions/_objects.md
# update website/docs/expressions/_functions.md
self._context["ak_is_sso_flow"] = request.context.get(PLAN_CONTEXT_SSO, False) self._context["ak_is_sso_flow"] = request.context.get(PLAN_CONTEXT_SSO, False)
if request.http_request: if request.http_request:
self.set_http_request(request.http_request) self.set_http_request(request.http_request)
@ -47,7 +48,8 @@ class PolicyEvaluator(BaseEvaluator):
def set_http_request(self, request: HttpRequest): def set_http_request(self, request: HttpRequest):
"""Update context based on http request""" """Update context based on http request"""
# update website/docs/policies/expression.md # update website/docs/expressions/_objects.md
# update website/docs/expressions/_functions.md
self._context["ak_client_ip"] = ip_address( self._context["ak_client_ip"] = ip_address(
get_client_ip(request) or "255.255.255.255" get_client_ip(request) or "255.255.255.255"
) )

View File

@ -1,22 +1,3 @@
---
title: Expressions
---
Expressions allow you to write custom logic using Python code.
Expressions are used in different places throughout authentik, and can do different things.
:::info
These functions/objects are available wherever expressions are used. For more specific information, see [Expression Policies](../policies/expression.md) and [Property Mappings](../property-mappings/expression.md)
:::
## Global objects
- `ak_logger`: structlog BoundLogger. ([ref](https://www.structlog.org/en/stable/api.html#structlog.BoundLogger))
- `requests`: requests Session object. ([ref](https://requests.readthedocs.io/en/master/user/advanced/))
## Generally available functions
### `regex_match(value: Any, regex: str) -> bool` ### `regex_match(value: Any, regex: str) -> bool`
Check if `value` matches Regular Expression `regex`. Check if `value` matches Regular Expression `regex`.
@ -49,7 +30,9 @@ return ak_is_group_member(request.user, name="test_group")
### `ak_user_by(**filters) -> Optional[User]` ### `ak_user_by(**filters) -> Optional[User]`
Fetch a user matching `**filters`. Returns "None" if no user was found. Fetch a user matching `**filters`.
Returns "None" if no user was found, otherwise [User](/docs/expressions/reference/user-object)
Example: Example:

View File

@ -0,0 +1,11 @@
- `ak_logger`: structlog BoundLogger. See ([structlog documentation](https://www.structlog.org/en/stable/api.html#structlog.BoundLogger))
Example:
```python
ak_logger.debug("This is a test message")
ak_logger.warning("This will be logged with a warning level")
ak_logger.info("Passing structured data", request=request)
```
- `requests`: requests Session object. See ([request documentation](https://requests.readthedocs.io/en/master/user/advanced/))

View File

@ -15,9 +15,16 @@ The User object has the following attributes:
- `group_attributes` Merged attributes of all groups the user is member of and the user's own attributes. - `group_attributes` Merged attributes of all groups the user is member of and the user's own attributes.
- `ak_groups` This is a queryset of all the user's groups. - `ak_groups` This is a queryset of all the user's groups.
You can do additional filtering like `user.ak_groups.filter(name__startswith='test')`, see [here](https://docs.djangoproject.com/en/3.1/ref/models/querysets/#id4) You can do additional filtering like
```python
user.ak_groups.filter(name__startswith='test')
```
see [here](https://docs.djangoproject.com/en/3.1/ref/models/querysets/#id4)
To get the name of all groups, you can do `[group.name for group in user.ak_groups.all()]` To get the name of all groups, you can do
```python
[group.name for group in user.ak_groups.all()]
```
## Examples ## Examples

View File

@ -4,6 +4,12 @@ title: Flows
Flows are a method of describing a sequence of stages. A stage represents a single verification or logic step. They are used to authenticate users, enroll them, and more. Flows are a method of describing a sequence of stages. A stage represents a single verification or logic step. They are used to authenticate users, enroll them, and more.
For example, a standard login flow would consist of the following stages:
- Identification, user identifies themselves via a username or email address
- Password, the user's password is checked against the hash in the database
- Log the user in
Upon flow execution, a plan containing all stages is generated. This means that all attached policies are evaluated upon execution. This behaviour can be altered by enabling the **Re-evaluate Policies** option on the binding. Upon flow execution, a plan containing all stages is generated. This means that all attached policies are evaluated upon execution. This behaviour can be altered by enabling the **Re-evaluate Policies** option on the binding.
To determine which flow is linked, authentik searches all flows with the required designation and chooses the first instance the current user has access to. To determine which flow is linked, authentik searches all flows with the required designation and chooses the first instance the current user has access to.

View File

@ -2,15 +2,19 @@
title: Expression Policies title: Expression Policies
--- ---
:::note The passing of the policy is determined by the return value of the code. Use
These variables are available in addition to the common variables/functions defined in [**Expressions**](../expressions/index.md) ```python
::: return True
```
to pass a policy and
```python
return False
```
to fail it.
The passing of the policy is determined by the return value of the code. Use `return True` to pass a policy and `return False` to fail it. ## Available Functions
### Available Functions ### `ak_message(message: str)`
#### `ak_message(message: str)`
Add a message, visible by the end user. This can be used to show the reason why they were denied. Add a message, visible by the end user. This can be used to show the reason why they were denied.
@ -21,16 +25,24 @@ ak_message("Access denied")
return False return False
``` ```
### Context variables import Functions from '../expressions/_functions.md'
<Functions />
## Variables
import Objects from '../expressions/_objects.md'
<Objects />
- `request`: A PolicyRequest object, which has the following properties: - `request`: A PolicyRequest object, which has the following properties:
- `request.user`: ([ref](../expressions/reference/user-object.md)) The current user, against which the policy is applied. - `request.user`: The current user, against which the policy is applied. See [User](../expressions/reference/user-object.md)
- `request.http_request`: ([ref](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects)) The Django HTTP Request. - `request.http_request`: The Django HTTP Request. See ([Django documentation](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects))
- `request.obj`: A Django Model instance. This is only set if the policy is ran against an object. - `request.obj`: A Django Model instance. This is only set if the policy is ran against an object.
- `request.context`: A dictionary with dynamic data. This depends on the origin of the execution. - `request.context`: A dictionary with dynamic data. This depends on the origin of the execution.
- `geoip`: ([ref](https://geoip2.readthedocs.io/en/latest/#geoip2.models.City)) GeoIP object, which is added when GeoIP is enabled. - `geoip`: GeoIP object, which is added when GeoIP is enabled. See [GeoIP](https://geoip2.readthedocs.io/en/latest/#geoip2.models.City)
- `ak_is_sso_flow`: Boolean which is true if request was initiated by authenticating through an external provider. - `ak_is_sso_flow`: Boolean which is true if request was initiated by authenticating through an external provider.
- `ak_client_ip`: ([ref](https://docs.python.org/3/library/ipaddress.html#ipaddress.ip_address)) Client's IP Address or 255.255.255.255 if no IP Address could be extracted. Can be [compared](../expressions/index.md#comparing-ip-addresses), for example - `ak_client_ip`: Client's IP Address or 255.255.255.255 if no IP Address could be extracted. Can be [compared](../expressions/index.md#comparing-ip-addresses), for example
```python ```python
return ak_client_ip in ip_network('10.0.0.0/24') return ak_client_ip in ip_network('10.0.0.0/24')
@ -38,10 +50,12 @@ return False
return ak_client_ip.is_private return ak_client_ip.is_private
``` ```
See also [Python documetnation](https://docs.python.org/3/library/ipaddress.html#ipaddress.ip_address)
Additionally, when the policy is executed from a flow, every variable from the flow's current context is accessible under the `context` object. Additionally, when the policy is executed from a flow, every variable from the flow's current context is accessible under the `context` object.
This includes the following: This includes the following:
- `prompt_data`: Data which has been saved from a prompt stage or an external source. - `prompt_data`: Data which has been saved from a prompt stage or an external source.
- `application`: The application the user is in the process of authorizing. - `application`: The application the user is in the process of authorizing.
- `pending_user`: The currently pending user - `pending_user`: The currently pending user, see [User](/docs/expressions/reference/user-object)

View File

@ -1,15 +1,22 @@
--- ---
title: Property Mapping Expressions title: Expressions
--- ---
The property mapping should return a value that is expected by the Provider/Source. Supported types are documented in the individual Provider/Source. Returning `None` is always accepted and would simply skip the mapping for which `None` was returned. The property mapping should return a value that is expected by the Provider/Source. Supported types are documented in the individual Provider/Source. Returning `None` is always accepted and would simply skip the mapping for which `None` was returned.
:::note
These variables are available in addition to the common variables/functions defined in [**Expressions**](../expressions/index.md)
:::
### Context Variables ## Available Functions
- `user`: The current user. This may be `None` if there is no contextual user. ([ref](../expressions/reference/user-object.md)) import Functions from '../expressions/_functions.md'
- `request`: The current request. This may be `None` if there is no contextual request. ([ref](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects))
<Functions />
## Variables
import Objects from '../expressions/_objects.md'
<Objects />
- `user`: The current user. This may be `None` if there is no contextual user. See ([User](../expressions/reference/user-object.md))
- `request`: The current request. This may be `None` if there is no contextual request. See ([Django documentation](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects))
- Other arbitrary arguments given by the provider, this is documented on the Provider/Source. - Other arbitrary arguments given by the provider, this is documented on the Provider/Source.

View File

@ -10,6 +10,18 @@ title: Next
Currently, only Duo push notifications are supported. Because no additional input is required, Duo also works with the LDAP Outpost. Currently, only Duo push notifications are supported. Because no additional input is required, Duo also works with the LDAP Outpost.
- Multi-tenancy
This version adds soft multi-tenancy. This means you can configure different branding settings and different default flows per domain.
This also changes how a default flow is determined. Previously, for defaults flow, authentik would pick the first flow that
- matches the required designation
- comes first sorted by slug
- is allowed by policies
Now, authentik first checks if the current tenant has a default flow configured for the selected designation. If not, it behaves the same as before, meaning that if you want to select a default flow based on policy, you can just leave the tenant default empty.
## Minor changes ## Minor changes
- You can now specify which sources should be shown on an Identification stage. - You can now specify which sources should be shown on an Identification stage.

View File

@ -41,6 +41,40 @@ module.exports = {
"outposts/manual-deploy-kubernetes", "outposts/manual-deploy-kubernetes",
], ],
}, },
{
type: "category",
label: "Integrations",
items: [
{
type: "category",
label: "as Source",
items: ["integrations/sources/active-directory/index"],
},
{
type: "category",
label: "as Provider",
items: [
"integrations/services/apache-guacamole/index",
"integrations/services/aws/index",
"integrations/services/awx-tower/index",
"integrations/services/gitlab/index",
"integrations/services/grafana/index",
"integrations/services/harbor/index",
"integrations/services/home-assistant/index",
"integrations/services/minio/index",
"integrations/services/nextcloud/index",
"integrations/services/rancher/index",
"integrations/services/sentry/index",
"integrations/services/sonarr/index",
"integrations/services/tautulli/index",
"integrations/services/ubuntu-landscape/index",
"integrations/services/veeam-enterprise-manager/index",
"integrations/services/vmware-vcenter/index",
"integrations/services/wiki-js/index",
],
},
],
},
{ {
type: "category", type: "category",
label: "Flows", label: "Flows",
@ -83,7 +117,6 @@ module.exports = {
type: "category", type: "category",
label: "Expressions", label: "Expressions",
items: [ items: [
"expressions/index",
{ {
type: "category", type: "category",
label: "Reference", label: "Reference",
@ -100,40 +133,6 @@ module.exports = {
"events/transports" "events/transports"
], ],
}, },
{
type: "category",
label: "Integrations",
items: [
{
type: "category",
label: "as Source",
items: ["integrations/sources/active-directory/index"],
},
{
type: "category",
label: "as Provider",
items: [
"integrations/services/apache-guacamole/index",
"integrations/services/aws/index",
"integrations/services/awx-tower/index",
"integrations/services/gitlab/index",
"integrations/services/grafana/index",
"integrations/services/harbor/index",
"integrations/services/home-assistant/index",
"integrations/services/minio/index",
"integrations/services/nextcloud/index",
"integrations/services/rancher/index",
"integrations/services/sentry/index",
"integrations/services/sonarr/index",
"integrations/services/tautulli/index",
"integrations/services/ubuntu-landscape/index",
"integrations/services/veeam-enterprise-manager/index",
"integrations/services/vmware-vcenter/index",
"integrations/services/wiki-js/index",
],
},
],
},
{ {
type: "category", type: "category",
label: "Maintenance", label: "Maintenance",