From 322ae4c4ed36a33385dd0f5e1431024d17e06cf9 Mon Sep 17 00:00:00 2001 From: Marc 'risson' Schmitt Date: Wed, 7 Aug 2024 21:30:29 +0200 Subject: [PATCH] website/docs: add source property mappings, rework provider property mappings (#10652) --- .../BasePropertyMappingForm.ts | 2 +- .../PropertyMappingLDAPSourceForm.ts | 4 + .../PropertyMappingOAuthSourceForm.ts | 4 + .../PropertyMappingRACForm.ts | 2 +- .../PropertyMappingSAMLSourceForm.ts | 4 + .../PropertyMappingSCIMSourceForm.ts | 4 + website/docs/core/terminology.md | 4 +- website/docs/flow/stages/prompt/index.md | 4 +- website/docs/property-mappings/index.md | 30 -------- website/docs/providers/oauth2/index.md | 2 +- .../property-mappings/expression.mdx | 10 +-- .../docs/providers/property-mappings/index.md | 13 ++++ website/docs/providers/rac/how-to-rac.md | 2 +- website/docs/providers/saml/index.md | 2 +- website/docs/releases/2024/v2024.8.md | 16 ++++ website/docs/security/security-hardening.md | 2 +- website/docs/sources/index.md | 5 +- website/docs/sources/ldap/index.md | 43 +++++++---- website/docs/sources/oauth/index.md | 26 +++++++ website/docs/sources/plex/index.md | 11 +++ .../sources/property-mappings/expressions.md | 21 +++++ .../docs/sources/property-mappings/index.md | 76 +++++++++++++++++++ website/docs/sources/saml/index.md | 11 +++ website/docs/sources/scim/index.md | 10 +++ .../docs/user-group-role/groups/group_ref.md | 16 ++++ website/integrations/services/minio/index.md | 2 +- website/netlify.toml | 16 +++- website/sidebars.js | 48 +++++++----- 28 files changed, 308 insertions(+), 82 deletions(-) delete mode 100644 website/docs/property-mappings/index.md rename website/docs/{ => providers}/property-mappings/expression.mdx (54%) create mode 100644 website/docs/providers/property-mappings/index.md create mode 100644 website/docs/sources/property-mappings/expressions.md create mode 100644 website/docs/sources/property-mappings/index.md create mode 100644 website/docs/user-group-role/groups/group_ref.md diff --git a/web/src/admin/property-mappings/BasePropertyMappingForm.ts b/web/src/admin/property-mappings/BasePropertyMappingForm.ts index 8fd8f18cc27f..de2c7c831935 100644 --- a/web/src/admin/property-mappings/BasePropertyMappingForm.ts +++ b/web/src/admin/property-mappings/BasePropertyMappingForm.ts @@ -16,7 +16,7 @@ export abstract class BasePropertyMappingForm extends string > { docLink(): string { - return "/docs/property-mappings/expression?utm_source=authentik"; + return "/docs/providers/property-mappings/expression?utm_source=authentik"; } getSuccessMessage(): string { diff --git a/web/src/admin/property-mappings/PropertyMappingLDAPSourceForm.ts b/web/src/admin/property-mappings/PropertyMappingLDAPSourceForm.ts index 066d3b5f9e2a..47671c288abd 100644 --- a/web/src/admin/property-mappings/PropertyMappingLDAPSourceForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingLDAPSourceForm.ts @@ -9,6 +9,10 @@ import { LDAPSourcePropertyMapping, PropertymappingsApi } from "@goauthentik/api @customElement("ak-property-mapping-ldap-source-form") export class PropertyMappingLDAPSourceForm extends BasePropertyMappingForm { + docLink(): string { + return "/docs/sources/property-mappings/expression?utm_source=authentik"; + } + loadInstance(pk: string): Promise { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSourceLdapRetrieve({ pmUuid: pk, diff --git a/web/src/admin/property-mappings/PropertyMappingOAuthSourceForm.ts b/web/src/admin/property-mappings/PropertyMappingOAuthSourceForm.ts index 842dea8ccf1f..73660cee7bc0 100644 --- a/web/src/admin/property-mappings/PropertyMappingOAuthSourceForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingOAuthSourceForm.ts @@ -9,6 +9,10 @@ import { OAuthSourcePropertyMapping, PropertymappingsApi } from "@goauthentik/ap @customElement("ak-property-mapping-oauth-source-form") export class PropertyMappingOAuthSourceForm extends BasePropertyMappingForm { + docLink(): string { + return "/docs/sources/property-mappings/expression?utm_source=authentik"; + } + loadInstance(pk: string): Promise { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSourceOauthRetrieve({ pmUuid: pk, diff --git a/web/src/admin/property-mappings/PropertyMappingRACForm.ts b/web/src/admin/property-mappings/PropertyMappingRACForm.ts index 4bd6d0803c80..12651055494e 100644 --- a/web/src/admin/property-mappings/PropertyMappingRACForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingRACForm.ts @@ -162,7 +162,7 @@ export class PropertyMappingRACForm extends ModelForm ${msg("See documentation for a list of all variables.")} diff --git a/web/src/admin/property-mappings/PropertyMappingSAMLSourceForm.ts b/web/src/admin/property-mappings/PropertyMappingSAMLSourceForm.ts index ce14c0620da1..6e9c4d94eb58 100644 --- a/web/src/admin/property-mappings/PropertyMappingSAMLSourceForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingSAMLSourceForm.ts @@ -9,6 +9,10 @@ import { PropertymappingsApi, SAMLSourcePropertyMapping } from "@goauthentik/api @customElement("ak-property-mapping-saml-source-form") export class PropertyMappingSAMLSourceForm extends BasePropertyMappingForm { + docLink(): string { + return "/docs/sources/property-mappings/expression?utm_source=authentik"; + } + loadInstance(pk: string): Promise { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSourceSamlRetrieve({ pmUuid: pk, diff --git a/web/src/admin/property-mappings/PropertyMappingSCIMSourceForm.ts b/web/src/admin/property-mappings/PropertyMappingSCIMSourceForm.ts index 692aacb1ffd4..b14b5f4895aa 100644 --- a/web/src/admin/property-mappings/PropertyMappingSCIMSourceForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingSCIMSourceForm.ts @@ -9,6 +9,10 @@ import { PropertymappingsApi, SCIMSourcePropertyMapping } from "@goauthentik/api @customElement("ak-property-mapping-scim-source-form") export class PropertyMappingSCIMSourceForm extends BasePropertyMappingForm { + docLink(): string { + return "/docs/sources/property-mappings/expression?utm_source=authentik"; + } + loadInstance(pk: string): Promise { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSourceScimRetrieve({ pmUuid: pk, diff --git a/website/docs/core/terminology.md b/website/docs/core/terminology.md index 5ac406079115..61ba65619a4e 100644 --- a/website/docs/core/terminology.md +++ b/website/docs/core/terminology.md @@ -61,9 +61,9 @@ See [Flows](../flow/index.md) ### Property Mappings -Property Mappings allow you to make information available for external applications. For example, if you want to login to AWS with authentik, you'd use Property Mappings to set the user's roles in AWS based on their group memberships in authentik. +Property Mappings allow you to make information available for external applications, and to modify how information from sources are stored in authentik. For example, if you want to log in to AWS with authentik, you'd use property mappings to set the user's roles in AWS based on their group memberships in authentik. -See [Property Mappings](../property-mappings/index.md) +See [Providers Property Mappings](../providers/property-mappings/index.md) and [Source Property Mappings](../sources/property-mappings/index.md). ### Outpost diff --git a/website/docs/flow/stages/prompt/index.md b/website/docs/flow/stages/prompt/index.md index 2bb33418bd46..5c9a115f1d8d 100644 --- a/website/docs/flow/stages/prompt/index.md +++ b/website/docs/flow/stages/prompt/index.md @@ -63,7 +63,7 @@ A flag which decides whether or not this field is required. A field placeholder, shown within the input field. By default, the placeholder is interpreted as-is. If you enable _Interpret placeholder as expression_, the placeholder -will be evaluated as a python expression. This happens in the same environment as [_Property mappings_](../../../property-mappings/expression). +will be evaluated as a Python expression. This happens in the same environment as [_Policies_](../../../policies/expression). In the case of `Radio Button Group` and `Dropdown` prompts, this field defines all possible values (choices). When interpreted as-is, only one value will be allowed (the placeholder string). When interpreted as expression, a list of values can be returned to define multiple choices. For example, `return ["first option", 42, "another option"]` defines 3 possible values. @@ -78,7 +78,7 @@ The prompt's initial value. It can also be left empty, in which case the field w With the `hidden` prompt, the initial value will also be the actual value, because the field is hidden to the user. By default, the initial value is interpreted as-is. If you enable _Interpret initial value as expression_, the initial value -will be evaluated as a python expression. This happens in the same environment as [_Property mappings_](../../../property-mappings/expression). +will be evaluated as a Python expression. This happens in the same environment as [_Policies_](../../../policies/expression). In the case of `Radio Button Group` and `Dropdown` prompts, this field defines the default choice. When interpreted as-is, the default choice will be the initial value string. When interpreted as expression, the default choice will be the returned value. For example, `return 42` defines `42` as the default choice. diff --git a/website/docs/property-mappings/index.md b/website/docs/property-mappings/index.md deleted file mode 100644 index 1e51820e9161..000000000000 --- a/website/docs/property-mappings/index.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Overview ---- - -Property Mappings allow you to pass information to external applications. For example, pass the current user's groups as a SAML parameter. Property Mappings are also used to map Source fields to authentik fields, for example when using LDAP. - -## SAML Property Mapping - -SAML Property Mappings allow you embed information into the SAML AuthN request. This information can then be used by the application to, for example, assign permissions to the object. - -## LDAP Property Mapping - -LDAP Property Mappings are used when you define a LDAP Source. These mappings define which LDAP property maps to which authentik property. By default, the following mappings are created: - -- authentik default Active Directory Mapping: givenName -- authentik default Active Directory Mapping: sAMAccountName -- authentik default Active Directory Mapping: sn -- authentik default Active Directory Mapping: userPrincipalName -- authentik default LDAP Mapping: mail -- authentik default LDAP Mapping: Name -- authentik default OpenLDAP Mapping: cn -- authentik default OpenLDAP Mapping: uid - -These are configured with most common LDAP setups. - -You can also configure [custom LDAP property mappings](../sources/ldap/index.md#custom-ldap-property-mapping). - -## Scope Mapping - -Scope Mappings are used by the OAuth2 Provider to map information from authentik to OAuth2/OpenID Claims. Values returned by a Scope Mapping are added as custom claims to Access and ID tokens. diff --git a/website/docs/providers/oauth2/index.md b/website/docs/providers/oauth2/index.md index 556f865f5010..cc865a1a1672 100644 --- a/website/docs/providers/oauth2/index.md +++ b/website/docs/providers/oauth2/index.md @@ -4,7 +4,7 @@ title: OAuth2 Provider This provider supports both generic OAuth2 as well as OpenID Connect -Scopes can be configured using Scope Mappings, a type of [Property Mappings](../../property-mappings/#scope-mapping). +Scopes can be configured using scope mappings, a type of [property mapping](../property-mappings/index.md#scope-mappings). | Endpoint | URL | | -------------------- | -------------------------------------------------------------------- | diff --git a/website/docs/property-mappings/expression.mdx b/website/docs/providers/property-mappings/expression.mdx similarity index 54% rename from website/docs/property-mappings/expression.mdx rename to website/docs/providers/property-mappings/expression.mdx index 566d6b11f444..f5ec3e3ddd1c 100644 --- a/website/docs/property-mappings/expression.mdx +++ b/website/docs/providers/property-mappings/expression.mdx @@ -2,23 +2,23 @@ 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. Supported types are documented in the individual provider. Returning `None` is always accepted and would simply skip the mapping for which `None` was returned. ## Available Functions -import Functions from "../expressions/_functions.md"; +import Functions from "../../expressions/_functions.md"; ## Variables -import Objects from "../expressions/_objects.md"; +import Objects from "../../expressions/_objects.md"; -import User from "../expressions/_user.md"; +import User from "../../expressions/_user.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. diff --git a/website/docs/providers/property-mappings/index.md b/website/docs/providers/property-mappings/index.md new file mode 100644 index 000000000000..4c0477fe9fcc --- /dev/null +++ b/website/docs/providers/property-mappings/index.md @@ -0,0 +1,13 @@ +--- +title: Provider property mappings +--- + +Property mappings allow you to pass information to external applications. For example, pass the current user's groups as a SAML parameter. + +## SAML property mappings + +SAML property mappings allow you embed information into the SAML authentication request. This information can then be used by the application to, for example, assign permissions to the object. + +## Scope mappings + +Scope mappings are used by the OAuth2 provider to map information from authentik to OAuth2/OpenID claims. Values returned by a scope mapping are added as custom claims to access and ID tokens. diff --git a/website/docs/providers/rac/how-to-rac.md b/website/docs/providers/rac/how-to-rac.md index 75ec0cdcd63c..e009abcf618f 100644 --- a/website/docs/providers/rac/how-to-rac.md +++ b/website/docs/providers/rac/how-to-rac.md @@ -54,7 +54,7 @@ Next, you need to add a property mapping for each of the remote machines you wan - **Enable font smoothing**: optional - **Enable full window dragging**: optional - Advanced settings: - - **Expressions**: optional, using Python you can define custom [expressions](../../property-mappings/expression.mdx). + - **Expressions**: optional, using Python you can define custom [expressions](../property-mappings/expression.mdx). 4. Click **Finish** to save your settings and close the modal. diff --git a/website/docs/providers/saml/index.md b/website/docs/providers/saml/index.md index 0683ceb760d3..67eb1d2abd0e 100644 --- a/website/docs/providers/saml/index.md +++ b/website/docs/providers/saml/index.md @@ -2,7 +2,7 @@ title: SAML Provider --- -This provider allows you to integrate enterprise software using the SAML2 Protocol. It supports signed requests and uses [Property Mappings](../../property-mappings/#saml-property-mapping) to determine which fields are exposed and what values they return. This makes it possible to expose vendor-specific fields. +This provider allows you to integrate enterprise software using the SAML2 protocol. It supports signed requests and uses [property mappings](../property-mappings/#saml-property-mappings) to determine which fields are exposed and what values they return. This makes it possible to expose vendor-specific fields. Default fields are exposed through auto-generated Property Mappings, which are prefixed with "authentik default". | Endpoint | URL | diff --git a/website/docs/releases/2024/v2024.8.md b/website/docs/releases/2024/v2024.8.md index fd9b0661c523..4e9c54a7ab08 100644 --- a/website/docs/releases/2024/v2024.8.md +++ b/website/docs/releases/2024/v2024.8.md @@ -32,6 +32,20 @@ To try out the release candidate, replace your Docker image tag with the latest **If you have any custom property mappings, we recommend migrating them to this new format.** +- **OAuth and SAML sources now sync groups by default** + + OAuth (specifically OpenID and Okta) sources now sync groups by default when a `groups` claim is available. + + SAML sources now sync groups by default when a `http://schemas.xmlsoap.org/claims/Group` attribute is available in the assertion. + + To disable that behavior, create an OAuth/SAML source property mapping with the following expression: + + ```python + return { + "groups": [], + } + ``` + ### Manual action may be required - **Changes to the external user type** @@ -50,6 +64,8 @@ To try out the release candidate, replace your Docker image tag with the latest ## New features +- **Source property mappings for SCIM, OAuth, SAML and Plex sources** + - **SAML Source encryption support** It is now possible to configure a SAML Source to decrypt and validate encrypted assertions. This can be configured by certaing a [Certificate-keypair](../../core/certificates.md) and selecting it in the SAML Source. diff --git a/website/docs/security/security-hardening.md b/website/docs/security/security-hardening.md index 8df3d876c032..fb3041d22694 100644 --- a/website/docs/security/security-hardening.md +++ b/website/docs/security/security-hardening.md @@ -6,7 +6,7 @@ While authentik is secure out of the box, you can take steps to further increase ### Expressions -[Expressions](../property-mappings/expression.mdx) allow super-users and other highly privileged users to create custom logic within authentik to modify its behaviour. Editing/creating these expressions is, by default, limited to super-users and any related events are fully logged. +[Expressions](../policies/expression.mdx) allow super-users and other highly privileged users to create custom logic within authentik to modify its behaviour. Editing/creating these expressions is, by default, limited to super-users and any related events are fully logged. However, for further hardening, it is possible to prevent any user (even super-users) from using expressions to create or edit any objects. To do so, configure your deployment to block API requests to these endpoints: diff --git a/website/docs/sources/index.md b/website/docs/sources/index.md index 6fefa3f7e65e..b557b2ea6136 100644 --- a/website/docs/sources/index.md +++ b/website/docs/sources/index.md @@ -7,10 +7,11 @@ Sources allow you to connect authentik to an external user directory. Sources ca ### Find your source -Sources are in three general categories: +Sources are in the following general categories: +- **Protocols** ([LDAP](./ldap/index.md), [OAuth](./oauth/index.md), [SAML](./saml/index.md), and [SCIM](./scim/index.md)) +- [**Property mappings**](./property-mappings/index.md) or how to import data from a source - **Directory synchronization** (Active Directory, FreeIPA) -- **Protocols** (LDAP, OAuth, SAML, and SCIM) - **Social logins** (Apple, Discord, Twitch, Twitter, and many others) For instructions to add a specific source, refer to the documentation links in the left navigation pane. diff --git a/website/docs/sources/ldap/index.md b/website/docs/sources/ldap/index.md index f950297e50a0..1cb245605640 100644 --- a/website/docs/sources/ldap/index.md +++ b/website/docs/sources/ldap/index.md @@ -45,7 +45,7 @@ To create or edit a source in authentik, open the Admin interface and navigate t #### LDAP Attribute mapping -- **User Property mappings** and **Group Property Mappings**: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](../../../docs/property-mappings/#ldap-property-mapping). +- **User Property mappings** and **Group Property Mappings**: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also our documentation on [property mappings](#ldap-source-property-mappings). #### Additional Settings @@ -65,11 +65,11 @@ To create or edit a source in authentik, open the Admin interface and navigate t - **Object uniqueness field**: This field contains a unique identifier. -## Property mappings +## LDAP source property mappings -LDAP property mappings can be used to convert the raw LDAP response into an authentik user/group. +See the [overview](../property-mappings/index.md) for information on how property mappings work. -By default, authentik ships with [pre-configured mappings](../../property-mappings/index.md#ldap-property-mapping) for the most common LDAP setups. These mappings can be found on the LDAP Source Configuration page in the Admin interface. +By default, authentik ships with [pre-configured mappings](#built-in-property-mappings) for the most common LDAP setups. These mappings can be found on the LDAP Source Configuration page in the Admin interface. You can assign the value of a mapping to any user attribute. Keep in mind though, data types from the LDAP server will be carried over. This means that with some implementations, where fields are stored as array in LDAP, they will be saved as array in authentik. To prevent this, use the built-in `list_flatten` function. Here is an example mapping for the user's username and a custom attribute for a phone number: @@ -82,19 +82,36 @@ return { } ``` -### Custom LDAP Property Mapping +### Built-in property mappings -If the default source mapping is not enough, you can set your own custom LDAP property mapping. +LDAP property mappings are used when you define a LDAP source. These mappings define which LDAP property maps to which authentik property. By default, the following mappings are created: -Here are the steps: +- authentik default Active Directory Mapping: givenName +- authentik default Active Directory Mapping: sAMAccountName +- authentik default Active Directory Mapping: sn +- authentik default Active Directory Mapping: userPrincipalName +- authentik default LDAP Mapping: mail +- authentik default LDAP Mapping: Name +- authentik default OpenLDAP Mapping: cn +- authentik default OpenLDAP Mapping: uid -1. In authentik, open the Admin interface, and then navigate to **Customization -> Property Mappings**. -2. Click **Create**, select **LDAP Property Mapping**, and then click **Next**. -3. Type a unique and meaningful **Name**, such as `ldap-displayName-mapping:name`. -4. In the**Object field** field, type the name of an existing authentik field, such as `name`. If you want to add more extended attributes, you can type `attributes.mobile` for example. -5. In the **Expression** field enter Python expressions to retrieve the value from LDAP source. For example `return list_flatten(ldap.get("displayName"))`. +These are configured with most common LDAP setups. -`list_flatten(["input string array"])` will convert a string array to a single string. If you are not sure whether the LDAP field is an array or not, you can map the field to any `attributes.xxx` and then check the sync result in authentik UI. +### Expression data + +The following variables are available to LDAP source property mappings: + +- `ldap`: A Python dictionary containing data from LDAP. +- `dn`: The object DN. + +### Additional expression semantics + +If you need to skip synchronization for a specific object, you can raise the `StopSync` exception: + +```python +if ldap.get("cn") == "doNotSync": + raise StopSync +``` ## Password login diff --git a/website/docs/sources/oauth/index.md b/website/docs/sources/oauth/index.md index 12aec5bc07d6..ee40581a3c76 100644 --- a/website/docs/sources/oauth/index.md +++ b/website/docs/sources/oauth/index.md @@ -31,3 +31,29 @@ This URL is fetched upon saving the source, and all the URLs will be replaced by To simplify Machine-to-machine authentication, you can create an OAuth Source as "trusted" source of JWTs. Create a source and configure either the Well-known URL or the OIDC JWKS URL, or you can manually enter the JWKS data if you so desire. Afterwards, this source can be selected in one or multiple OAuth2 providers, and any JWT issued by any of the configured sources' JWKS will be able to authenticate. To learn more about this, see [JWT-authentication](/docs/providers/oauth2/client_credentials#jwt-authentication). + +## OAuth source property mappings + +See the [overview](../property-mappings/index.md) for information on how property mappings work. + +### Expression data + +The following variables are available to OAuth source property mappings: + +- `info`: A Python dictionary containing OAuth claims. For example (values might differ depending on the source): + ```python + { + "iss": "https://source.company", + "sub": "f153e7da687eec8c8789c72b6cc6bb5197df7b48b263b3151f36908e1bc10691", + "aud": "01e4DmQiG1d3kaewD3Mkz7E7kXknk9j43eZMkNaE", + "aud": "a7809c1b1c4aaa50adfb68660a6273dd9c8d15e4", + "email": "user@authentik.company", + "email_verified": True, + "name": "User", + "given_name": "User", + "preferred_username": "user", + "nickname": "user", + } + ``` +- `client`: An OAuth client object to make requests to the Source with authentication built-in. +- `token`: A Python dictionary containing OAuth tokens. diff --git a/website/docs/sources/plex/index.md b/website/docs/sources/plex/index.md index 590f9df4d679..572d2c33de1d 100644 --- a/website/docs/sources/plex/index.md +++ b/website/docs/sources/plex/index.md @@ -25,3 +25,14 @@ Save, and you now have Plex as a source. :::note For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: + +## Plex source property mappings + +See the [overview](../property-mappings/index.md) for information on how property mappings work. + +### Expression data + +The following variables are available to OAuth source property mappings: + +- `info`: A Python dictionary containing Plex user data. +- `auth_api`: A Plex client object to make requests to the Source with authentication built-in. diff --git a/website/docs/sources/property-mappings/expressions.md b/website/docs/sources/property-mappings/expressions.md new file mode 100644 index 000000000000..aa0163476177 --- /dev/null +++ b/website/docs/sources/property-mappings/expressions.md @@ -0,0 +1,21 @@ +--- +title: Sources expression property mappings +--- + +The property mapping should return a value that is expected by the source. Returning `None` is always accepted and would simply skip the mapping for which `None` was returned. + +## Variables + +- Arbitrary arguments given by the source (this is documented by the source). +- `properties`: A Python dictionary containing the result of the previously run property mappings, plus the initial data computed by the source. +- `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)) + +import Objects from "../../expressions/\_objects.md"; + + + +## Available Functions + +import Functions from "../../expressions/\_functions.md"; + + diff --git a/website/docs/sources/property-mappings/index.md b/website/docs/sources/property-mappings/index.md new file mode 100644 index 000000000000..ab8d8e295cbb --- /dev/null +++ b/website/docs/sources/property-mappings/index.md @@ -0,0 +1,76 @@ +--- +title: Source property mappings +--- + +Source property mappings allow you to modify or gather extra information from sources. + +This page is an overview of how property mappings work. For information about specific protocol, please refer to each protocol page: + +- [LDAP](../ldap/#ldap-source-property-mappings) +- [OAuth](../oauth/#oauth-source-property-mappings) +- [SAML](../saml/#saml-source-property-mappings) +- [SCIM](../scim/#scim-source-property-mappings) + +## Create a custom source property mapping + +If the default source mappings are not enough, or if you need to get additional data from the source, you can create your own custom source property mappings. + +Here are the steps: + +1. In authentik, open the Admin interface, and then navigate to **Customization -> Property Mappings**. +2. Click **Create**, select the property mapping type for your source, and then click **Next**. +3. Type a unique and meaningful **Name**, such as `ldap-displayName-mapping:name`. +4. In the **Expression** field enter Python expressions to retrieve the value from the source. See [Expression Semantics](#expression-semantics) below for details. +5. In the source configuration, select the newly created property mapping as a **User property mapping** if it applies to users, or **Group property mapping** if it applies to groups. + +## How it works + +### Expression semantics + +Each source provides the Python expression with additional data. You can import parts of that data into authentik users and groups. Assuming the source provides us with a `data` Python dictionary, you can write the following: + +```python +return { + "name": data.get("displayName"), +} +``` + +You can see that the expression returns a Python dictionary. The dictionary keys must match [User properties](../../user-group-role/user/user_ref.md#object-properties) or [Group properties](../../user-group-role/groups/group_ref.md#object-properties). Note that for users, `ak_groups` and `group_attributes` cannot be set. + +See each source documentation for a reference of the available data. See the authentik [expressions documentation](./expressions.md) for available data and functions. + +Note that the [`list_flatten`](./expressions.md#list_flattenvalue-listany--any---optionalany) method is applied for all top-level properties, but not for attributes: + +```python +return { + "username": data.get("username"), # list_flatten is automatically applied to top-level attributes + "attributes": { + "phone": list_flatten(data.get("phoneNumber")), # but not for attributes! + }, +} +``` + +### Object construction process + +A user or group object is constructed as follows: + +1. The source provides initial properties based on commonly used data. +2. Each property mapping associated with the source is run and results are merged into the previous properties. + - If a property mapping throws an error, the process is aborted. If that happens inside a synchronization process, the object is skipped. If it happens during an enrollment or authentication flow, the flow is cancelled. + - If a property mapping sets one attribute to `None`, that attribute is then discarded. +3. If the `username` field is not set for user objects, or the `name` field is not set for group objects, the process is aborted. +4. The object is created or updated. The `attributes` property is merged with existing data if the object already exists. + +### Group synchronization + +LDAP and SCIM sources have built-in mechanisms to get groups. This section does not apply to them. + +You can write a custom property mapping to set the user's groups: + +```python +return { + "groups": data.get("groups", []), +} +``` + +The `groups` attribute is a special attribute that must contain group identifiers. By default, those identifiers are also used as the group name by default, those identifiers are also used as the group name. Each of those identifiers is then given to group property mappings as the `group_id` variable, if extra processing needs to happen. diff --git a/website/docs/sources/saml/index.md b/website/docs/sources/saml/index.md index 8b33e0c9066f..90d988bd6e26 100644 --- a/website/docs/sources/saml/index.md +++ b/website/docs/sources/saml/index.md @@ -80,3 +80,14 @@ This will depend heavily on what software you are using for your IDP. On the Met ``` + +## SAML source property mappings + +See the [overview](../property-mappings/index.md) for information on how property mappings work. + +### Expression data + +The following variables are available to SAML source property mappings: + +- `root`: An XML `ETree` object containing data from the source. +- `name_id`: An XML `Element` object identifying the user. diff --git a/website/docs/sources/scim/index.md b/website/docs/sources/scim/index.md index 5ef94ea12bfd..ba0bc1e2c71c 100644 --- a/website/docs/sources/scim/index.md +++ b/website/docs/sources/scim/index.md @@ -27,3 +27,13 @@ Endpoint to list, create, update and delete users. Endpoint to list, create, update and delete groups. There is also the `/v2/ServiceProviderConfig` and `/v2/ResourceTypes`, which is used by SCIM-enabled applications to find out which features authentik supports. + +## SCIM source property mappings + +See the [overview](../property-mappings/index.md) for information on how property mappings work. + +### Expression data + +The following variables are available to SCIM source property mappings: + +- `data`: A Python dictionary containing data from the SCIM source. diff --git a/website/docs/user-group-role/groups/group_ref.md b/website/docs/user-group-role/groups/group_ref.md new file mode 100644 index 000000000000..27c1c713630e --- /dev/null +++ b/website/docs/user-group-role/groups/group_ref.md @@ -0,0 +1,16 @@ +--- +title: Group properties and attributes +--- + +## Object properties + +The Group object has the following properties: + +- `name` Group's display name. +- `is_superuser` Boolean field if the group's users are superusers. +- `parent` The parent Group of this Group. +- `attributes` Dynamic attributes, see [Attributes](#attributes) + +## Attributes + +See [the user reference](../user/user_ref.md#attributes) for well-known attributes. diff --git a/website/integrations/services/minio/index.md b/website/integrations/services/minio/index.md index fed64c2f63ca..f01a318f355c 100644 --- a/website/integrations/services/minio/index.md +++ b/website/integrations/services/minio/index.md @@ -43,7 +43,7 @@ elif ak_is_group_member(request.user, name="Minio users"): return None ``` -Note that you can assign multiple policies to a user by returning a list, and returning `None` will map no policies to the user, resulting in no access to the MinIO instance. For more information on writing expressions, see [Expressions](../../../docs/property-mappings/expression) and [User](../../../docs/user-group-role/user/user_ref#object-properties) docs. +Note that you can assign multiple policies to a user by returning a list, and returning `None` will map no policies to the user, resulting in no access to the MinIO instance. For more information on writing expressions, see [Expressions](../../../docs/providers/property-mappings/expression) and [User](../../../docs/user-group-role/user/user_ref#object-properties) docs. ### Creating application and provider diff --git a/website/netlify.toml b/website/netlify.toml index bd9144cb4ceb..00af61600f68 100644 --- a/website/netlify.toml +++ b/website/netlify.toml @@ -47,6 +47,16 @@ # Moved Sources from Integrations to Docs [[redirects]] - from = "/integrations/sources/*" - to = "/docs/sources/:splat" - status = 302 + from = "/integrations/sources/*" + to = "/docs/sources/:splat" + status = 302 + +# Split Property Mappings docs between Providers and Sources +[[redirects]] + from = "/docs/property-mappings/" + to = "/docs/providers/property-mappings/" + status = 302 +[[redirects]] + from = "/docs/property-mappings/expression" + to = "/docs/providers/property-mappings/expression" + status = 302 diff --git a/website/sidebars.js b/website/sidebars.js index 58c03437bc39..ceb0e0f60a8d 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -74,6 +74,15 @@ const docsSidebar = { id: "providers/index", }, items: [ + { + type: "category", + label: "Property Mappings", + link: { + type: "doc", + id: "providers/property-mappings/index", + }, + items: ["providers/property-mappings/expression"], + }, { type: "category", label: "Google Workspace Provider", @@ -168,14 +177,6 @@ const docsSidebar = { id: "sources/index", }, items: [ - { - type: "category", - label: "Directory synchronization", - items: [ - "sources/active-directory/index", - "sources/freeipa/index", - ], - }, { type: "category", label: "Protocols", @@ -186,6 +187,23 @@ const docsSidebar = { "sources/scim/index", ], }, + { + type: "category", + label: "Property Mappings", + link: { + type: "doc", + id: "sources/property-mappings/index", + }, + items: ["sources/property-mappings/expressions"], + }, + { + type: "category", + label: "Directory synchronization", + items: [ + "sources/active-directory/index", + "sources/freeipa/index", + ], + }, { type: "category", label: "Social Logins", @@ -311,15 +329,6 @@ const docsSidebar = { "policies/expression", ], }, - { - type: "category", - label: "Property Mappings", - link: { - type: "doc", - id: "property-mappings/index", - }, - items: ["property-mappings/expression"], - }, { type: "category", label: "Events", @@ -374,7 +383,10 @@ const docsSidebar = { type: "doc", id: "user-group-role/groups/index", }, - items: ["user-group-role/groups/manage_groups"], + items: [ + "user-group-role/groups/manage_groups", + "user-group-role/groups/group_ref", + ], }, { type: "category",