Advanced Identity Management

Overview

Advanced Identity Management allows you to represent your organization's structure within Matrix and Element: creating a space for all its members, maintaining their membership in rooms and subspaces, managing power levels and more.

It is composed of two main parts:

In addition to that, Advanced Identity Management is also an Application Service. The Provisioner observers the events reported by the AS in case it needs to enforce its rules on entities that it didn't itself create: for example demote a room creator to their expected power level (see LDAP as a source of truth).

Example configuration

provisioner:
  # Optional. A list of rooms that'll get automatically created in in managed space.
  # The ID is required to enable GPS to track whether they were already created or not
  # – you can change it, but it'll cause new rooms to be generated.
  default_rooms:
  - id: 'general'
    properties: { name: 'General discussion' }
  # Optional. A list of userid patterns that will not get kicked from rooms
  # even if they don't belong to them according to LDAP.
  # This is useful for things like the auditbot.
  # Patterns listed here will be wrapped in ^ and $ before matching.
  allowed_users:
  - '@adminbot:.*'
  # Optional. Determines whether users will be automatically invited to rooms (default, public and space-joinable)
  # when they gain access to them. Defaults to true. Users will still get invited to spaces regardless of this setting.
  invite_to_public_rooms: false
  # Optional: A list of remote Advanced Identity Management we'll be federating with. Requests from other remote users will be ignored.
  federation:
    federates_with:
    - '@aim_bot:consultancy.test'
  # Optional. When enabled, spaces that are no longer configured, and rooms belonging to those spaces will be cleaned up.
  # This will likely become enabled by default in the future.
  # When disabled (or omitted), GS will log the rooms and spaces it would clean up if allowed to.
  gc:
    enabled: true

# Optional. If configured, Advanced Identity Management will synchronize user accounts (attributes and account validity)
# found in the data directory to the specified list of targets.
userProvisioner:
  # Optional. Configure to enable user deprovisioning. Disabled by default.
  deprovisioning:
    enabled: false
    # Optional. When users get removed from the directory their accounts will only be deactivated,
    # but their erasure will be delayed by the specified time period, allowing them to be reactivated in the meantime.
    # The format is <amount><unit>, with amount being numeric and unit being one of: [s, m, h, d], for seconds, minutes,
    # hours or days respectively (for example: "24h", "31d" etc.).
    # The specified period will be translated into seconds, so won't account for things like DST, leap seconds etc.
    # Users will be deleted *no sooner* than that, but may be removed a bit later, depending on other Advanced Identity Management operations.
    # By default set to 30 days.
    soft_delete_period: '30d'

# Configure the spaces you want Advanced Identity Management to manage on your Matrix server
spaces:
  # The internal ID of this space. Don't change it after you set it, or it will create a new one and abandon the old one.
- id: main
  # The display name of the space, safe to change later.
  name: 'My Company'
  # The list of groups from your user directory to add as members to this space.
  # An empty string is a special name that means "all available users, regardless of group memberships".
  # You can set a power level for any of the groups. By default it's 0.
  # This space is going to contain all the users in the directory,
  # and those that are present in the "managers" groups will be the moderators (in the space and its child rooms).
  groups:
    - externalId: ''
    - externalId: 'cn=managers,ou=employees,dc=element,dc=test'
      powerLevel: 50
- id: management
  name: 'Management'
  groups:
    - externalId: 'cn=managers,ou=employees,dc=element,dc=test'
  # You can confgure spaces that'll be federated between multiple GS servers.
  # Each Advanced Identity Management will only manage its local users.
- id: shared
  name: 'Federated space'
  groups:
    - externalId: 'cn=engineering,ou=employees,dc=element,dc=test'
  federatedGroups:
      # The external ID of the group on the foreign server.
      # This will be enforced by the Advanced Identity Management running on consultancy.test, not this instance configured here.
      # The Advanced Identity Management running on consultancy.test needs to have our MXID
      # (@gpsbot:element.test by default) configured in its provisioner.federates_with config option.
    - externalId: 'ou=element-contractors,dc=consultancy,dc=test'
      # The MXID of the remote Advanced Identity Management bot.
      agent: '@aim_bot:consultancy.test'

source:
  type: 'ldap'
  # LDAP will be checked for changes every this many seconds
  check_interval_seconds: 60
  # The following can be copied straight from Synapse's homeserver.yaml
  # if you're already using its LDAP password provider
  uri: "ldap://element.test"
  # The base ou we specify here will become the root space
  base: "ou=employees,dc=element,dc=test"
  # Optional. An LDAP filter to use when searching for entries
  filter: '(!(ou=Domain Controllers))'
  # Make sure the account you use here has enough permissions to perform searches on your `base`
  bind_dn: "ELEMENT\\administrator"
  bind_password: "donkey.8"
  # Needs `uid` to be able to determine Matrix localparts for users
  # and `name`s to pick the right names for spaces
  attributes:
    uid: "sAMAccountName"
    name: "name"
  # If the LDAP server requires a client certificate, enable this option.
  # cert:
    # The path to the file
    # file: "./my-cert-file.pem"
    # OR the PEM-encoded cert itself
    # cert: "foobar"
    # Passphrase for the cert, if required.
    # passphrase: "passphrase"

# For Microsoft Graph:
# source:
#   type: 'ms-graph-ad'
#
#   # This is the "Tenant ID" from your Azure Active Directory Overview
#   tenant_id: 'b9355cb3-feed-dead-beef-9cc325f0335b'
#
#   # Register your app in "App registrations". This will be its "Application (client) ID"
#   client_id: '5c955b66-18b3-42de-bb5a-13b5a202d4fc'
#
#   # Go to "Certificates & secrets", and click on "New client secret".
#   # This will be the "Value" of the created secret (not the "Secret ID").
#   client_secret: 'yOb7Q~Km~~YMKzpeq73swJj3kOeJpUwXSZamr'
#   # For the bridge to be able to operate correctly, navigate to API permissions and unsure
#   # it has access to GroupMember.Read.All and User.Read.All
#   # Application permissions for Microsoft Graph. Remember to grant the admin consent for those.
#
#   # Optional. The url to reach Graph on. Override if your deployment uses a specific graph endpoint.
#   base_url: 'https://graph.microsoft.com/'
#
#   # Optional. Specific scopes to set for graph to use.
#   scopes: ['https://graph.microsoft.com/.default']

# For SCIM:
#   type: 'scim'
#   # HTTP port that the SCIM server will listen on
#   port: 8040
#   # Optional URL prefix for all routes
#   base_url: '/scim/v2'
#   client:
#     # Unique ID for the SCIM client.
#     # This will be used to keep track of the managed Space and User/Group storage in Matrix.
#     id: 'element-ad'
#     # You can set up multiple client tokens with different permission levels.
#     rbac:
#         # Bearer token for the client, as per RFC 6750
#       - token: 'foo-bar-baz'
#         # What's the token allowed to do: in this case, everything (read+write on all endpoints).
#         # The format for these is 'access:scope', access being 'read', 'write' or '*' for both,
#         # scope being 'users', 'groups' or '*' for everything.
#         roles: ['*:*']
#         # You can specify permissions for anyone who presents a valid Matrix access_token for an admin user
#       - synapse_user: 'admin'
#         # ...and assign more fine-tuned permissions to it
#         roles: ['read:*', 'write:groups']
#     attributeMapping:
#       # The SCIM user attribute that'll be used as the Matrix username for provisioned users
#       username: 'externalId'
#   # Should SCIM user creation register a Matrix account for the user.
#   # Possible values are 'yes', 'no' and 'if-missing'
#   # - 'yes' will register Matrix accounts on the server upon a SCIM create user request,
#   #   and error out if the user with that username already exists.
#   # - 'if-missing' will register Matrix accounts unless they exist already.
#   #   This is useful if some users have their user accounts created independently before the SCIM bridge was set up.
#   # - 'no' will not create user accounts, only work with existing ones.
#   register_users: 'no'
#   # Optional: Should SCIM responses wait for Matrix provisioning to complete.
#   # It is recommended to leave it as false. HTTP responses will be sent quicker,
#   # and Matrix provisioning may still fail in the background (to be retried later).
#   synchronous_provisioning: false
#   # Optional: Configure a mailer to send email notifications to newly registered, activated and deactivated users.
#   # mailer:
#   #   # The email address emails will be sent from
#   #   from: 'element@element.com'
#   #   # Path to a directory with email templates.
#   #   # Each template should be a directory containing 'subject.pug', 'text.pug' and 'html.pug',
#   #   # all using https://pugjs.org/ as a template language.
#   #   # Advanced Identity Management ships with standard, Element-branded templates in templates/
#   #   templates_path: './templates'
#   #   # SMTP transport configuration, as per https://nodemailer.com/smtp/,
#   #   # except that we default `secure` to `true` and `port` to 465.
#   #   transport:
#   #     host: 'smtp.example.com'
#   #     auth:
#   #       user: 'mailer'
#   #       pass: 'mailerpass.8'

# Optional. Configure this to gather usage statistics.
# See telemetry spec at https://gitlab.matrix.org/new-vector/modular/telemetry-schema
# for details on what's being gathered and sent.
telemetry:
  # Identifier of this Advanced Identity Management instance
  instance_id: 'foo'
  # Every this many seconds (and on startup) telemetry will be recorded (and optionally sent)
  send_interval: 3600
  # Optional: the EMS endpoint to submit telemetry entries to.
  # This is optional as it wouldn't work for airgapped environments,
  # and by default no telemetry is sent (but it is still gathered).
  endpoint: 'https://ems.com/telemetry'
  # Optional: how many times should we retry sending telemetry if it fails. Defaults to 3
  retry_count: 3
  # Optional: how long should we wait between retries. Defaults to 60, in seconds
  retry_interval: 60

# Optional
logging:
  # Allowed levels are: error, warn, info, http, verbose, debug, silly - case sensitive.
  # "info" will typically notify of all "write" actions (affecting the state of the homeserver),
  # while "debug" will also be reporting checks performed that didn't result in any changes.
  level: "info"
  # Optional. Allowed formats are are:
  # - pretty: the default. A timestamped, colorized output suitable for humans
  # - json:   logging a json object containing a `level`, `message`, `timestamp` and optionally a `label`
  format: "json"

Bridging

Bridging directories

Bridges' job is to turn the contents of an external data directory into a data structure that can then be then constructed on the Matrix server by the Provisioner. See State representation for the details description of the data structure being produced.

See specific bridges (in the sidebar) to learn more about how GS interprets the contents of specific data sources.

Bridges run continously and trigger provisioning whenever they observer changes in the data source.

LDAP

The LDAP bridge will periodically (according to its configuration) fetch the LDAP tree from the server (filtering out the things it doesn't find interesting).

To enable maximum flexibility it "flattens" the LDAP tree so that the users' (and groups') place in directory tree doesn't matter.

Groups, OrgUnits and Domains (if found), will all be flattened and treated like a container for users. It makes it possible to use their DNs[^note] (fully qualified names) to assign users to spaces and power levels in those spaces.

[^note]: CNs are also allowed here for backwards compatibility reasons, but only for groups. It is however advised to avoid using CNs and use DNs instead, since they are guaranteed to be unique across the LDAP tree. GS' behaviour is undefined when mapping groups with duplicate names.

For example, for the following LDAP tree:

- Company (Domain) (`dc=company`)
  - Alfred (User) (`cn=alfred,cn=company`)
  - Engineering (OrgUnit) (`ou=engineering,cn=company`)
    - Barbara (User) (`cn=barbara,ou=engineering,cn=company`)
    - Moderators (Group) (`cn=moderators,ou=engineering,cn=company`)
      - Charlie (User) (`cn=charlie,ou=engineering,cn=company`)

Company, Engineering and Moderators will all be treated as if they were an group. We could then use the following space mapping configuration with it:

spaces:
  id: root
  name: "Company"
  groups:
    - externalId: `dc=company` # or leave it empty with the same result
  subspaces:
    - id: engineering
      name: Engineering
      groups:
        - externalId: `ou=engineering,cn=company`
        - externalId: `cn=moderators,ou=engineering,cn=company`
          powerLevel: 50

Example Configuration

When using the helm chart, the authentication schema is automatically used to configure GroupSync LDAP source. If you want to override some settings, you can always implement the following configuration:

source:
  type: 'ldap'
  # LDAP will be checked for changes every this many seconds
  check_interval_seconds: 60
  # The following can be copied straight from Synapse's homeserver.yaml
  # if you're already using its LDAP password provider
  uri: "ldap://element.test"
  # The base ou we specify here will become the root space
  base: "ou=employees,dc=element,dc=test"
  # Optional. An LDAP filter to use when searching for entries
  filter: '(!(ou=Domain Controllers))'
  # Make sure the account you use here has enough permissions to perform searches on your `base`
  bind_dn: "ELEMENT\\administrator"
  bind_password: "donkey.8"
  # Needs `uid` to be able to determine Matrix localparts for users
  # and `name`s to pick the right names for spaces
  attributes:
    uid: "sAMAccountName"
    name: "name"
  # If the LDAP server requires a client certificate, enable this option.
  # cert:
    # The path to the file
    # file: "./my-cert-file.pem"
    # OR the PEM-encoded cert itself
    # cert: "foobar"
    # Passphrase for the cert, if required.
    # passphrase: "passphrase"

Microsoft Graph

The MsGraph bridge will periodically (according to its configuration) perform the following API calls:

In order to perform the queries successfully, Advanced Identity Management's Application needs to have the following permissions granted in Azure:

It emits a list of users and groups as-is, without performing any transformations on them.

Example Configuration

Using MS-Graph requires the following GroupSync configuration :

source:
  type: 'ms-graph-ad'

  # This is the "Tenant ID" from your Azure Active Directory Overview
  tenant_id: 'b9355cb3-feed-dead-beef-9cc325f0335b'

  # Register your app in "App registrations". This will be its "Application (client) ID"
  client_id: '5c955b66-18b3-42de-bb5a-13b5a202d4fc'

  # Go to "Certificates & secrets", and click on "New client secret".
  # This will be the "Value" of the created secret (not the "Secret ID").
  client_secret: 'yOb7Q~Km~~YMKzpeq73swJj3kOeJpUwXSZamr'
  # For the bridge to be able to operate correctly, navigate to API permissions and unsure
  # it has access to GroupMember.Read.All and User.Read.All
  # Application permissions for Microsoft Graph. Remember to grant the admin consent for those.

  # Optional. The url to reach Graph on. Override if your deployment uses a specific graph endpoint.
  base_url: 'https://graph.microsoft.com/'

  # Optional. Specific scopes to set for graph to use.
  scopes: ['https://graph.microsoft.com/.default']

SCIM

The SCIM bridge maintains an HTTP service that conforms to the SCIM protocol (RFC 7644) and provisions a Matrix server with the SCIM resources sent to it.

Configuration

The following options are available when configuring the SCIM bridge:

Example configuration

Configuring the SCIM bridge requires to configure the following values. When using ESS Helm Chart, you need to set groupSync.enableSCIM to expose the SCIM ingress. It will be abailable under GroupSync ingress if it is enabled, or Synapse ingress at /scim/v2 path.


source:
  type: 'scim'
  client:
    # Unique ID for the SCIM client.
    # This will be used to keep track of the managed Space and User/Group storage in Matrix.
    id: 'element-ad'
    # You can set up multiple client tokens with different permission levels.
    rbac:
        # Bearer token for the client, as per RFC 6750
      - token: 'foo-bar-baz'
        # What's the token allowed to do: in this case, everything (read+write on all endpoints).
        # The format for these is 'access:scope', access being 'read', 'write' or '*' for both,
        # scope being 'users', 'groups' or '*' for everything.
        roles: ['*:*']
        # You can specify permissions for anyone who presents a valid Matrix access_token for an admin user
      - synapse_user: 'admin'
        # ...and assign more fine-tuned permissions to it
        roles: ['read:*', 'write:groups']
    attributeMapping:
      # The SCIM user attribute that'll be used as the Matrix username for provisioned users
      username: 'externalId'
  # Should SCIM user creation register a Matrix account for the user.
  # Possible values are 'yes', 'no' and 'if-missing'
  # - 'yes' will register Matrix accounts on the server upon a SCIM create user request,
  #   and error out if the user with that username already exists.
  # - 'if-missing' will register Matrix accounts unless they exist already.
  #   This is useful if some users have their user accounts created independently before the SCIM bridge was set up.
  # - 'no' will not create user accounts, only work with existing ones.
  register_users: 'no'
  # Optional: Should SCIM responses wait for Matrix provisioning to complete.
  # It is recommended to leave it as false. HTTP responses will be sent quicker,
  # and Matrix provisioning may still fail in the background (to be retried later).
  synchronous_provisioning: false
  # Optional: Configure a mailer to send email notifications to newly registered, activated and deactivated users.
  # mailer:
  #   # The email address emails will be sent from
  #   from: 'element@element.com'
  #   # Path to a directory with email templates.
  #   # Each template should be a directory containing 'subject.pug', 'text.pug' and 'html.pug',
  #   # all using https://pugjs.org/ as a template language.
  #   # Group sync ships with standard, Element-branded templates in templates/
  #   templates_path: './templates'
  #   # SMTP transport configuration, as per https://nodemailer.com/smtp/,
  #   # except that we default `secure` to `true` and `port` to 465.
  #   transport:
  #     host: 'smtp.example.com'
  #     auth:
  #       user: 'mailer'
  #       pass: 'mailerpass.8'

Space Mapping

This mechanism allows us to configure spaces that Advanced Identity Management will maintain.

Configuration

We define each space giving it a name (which will be displayed in Element), a unique ID (which allows Advanced Identity Management to track the Space even if it gets renamed), and a list of groups whose users will become the members of the Space. Users needs to be a member of any configured group, not all of them.

You can pick any ID you want, but if you change it later Advanced Identity Management will create a brand new space and abandon the old ones, likely confusing the users.

In order to limit space membership to a specific Group, we include its Group ID.

Each group may optionally include a powerLevel setting, allowing specific groups to have elevated permissions in the space.

A special group ID of '' (an empty string) indicates that all users from the server, regardless of their group membership, should become the members of the Space.

In addition to regular groups, you may also make a space federated by specifying federatedGroups and a remote Advanced Identity Management server. See Federation for more details.

An optional list of subspaces may also be configured, each using the same configuration format and behaviour (recursively).

If a space has subspaces configured, its members list will be composed of the members of the space itself any any of its subspaces, recursively -- so a subspace's member list is always a subset of its parent space's member list. This may change in the future, so it's advised not to rely on this when configuring your spaces.

spaces:
  id: root
  name: 'Company'
  groups:
    - externalId: 'element-users'

With powerLevel option allows us to give users extra permissions. This is equivalent to the group_power_level setting[^note].

spaces:
  id: root
  name: 'Company'
  groups:
    # regular users
    - externalId: 'element-users'
    # moderators
    - externalId: 'element-moderators'
      powerLevel: 50

In case of Power Level conflicts, the highest power level will be used. With the following configuration:

spaces:
  id: root
  name: 'Company'
  groups:
    - externalId: 'moderators'
      powerLevel: 50
    - externalId: 'admins'
      powerLevel: 100

A user who's a member of both moderators and admins will end up with Power Level of 100.

Subspaces can be configured analogically:

spaces:
  id: shared
  name: "Element Corp"
  groups:
  - externalId: 'matrix-mods'
    powerLevel: 50
  - externalId: ''
  subspaces:
  - id: london
    name: "London Office"
    groups:
    - externalId: 'london-matrix-mods'
      powerLevel: 50
    - externalId: 'london-employees'

Provisioning

Provisioning

The role of the provisioner is to take the expected state representation produced by Bridges and ensure that the server state matches these expectations. The provisioner will try to do as little as possible to go from the existing to the desired state — in particular, running a Provisioner twice will result in no operations being performed on the second run.

Provisioning will typically be triggered by the bridge, either on its startup or whenever it becomes aware of changes in the data source.

See Usage Scenarios for examples of provisioning actions in response to data source changes.

Example Configuration


provisioner:
  # Optional. A list of rooms that'll get automatically created in in managed space.
  # The ID is required to enable GPS to track whether they were already created or not
  # – you can change it, but it'll cause new rooms to be generated.
  default_rooms:
  - id: 'general'
    properties: { name: 'General discussion' }
  # Optional. A list of userid patterns that will not get kicked from rooms
  # even if they don't belong to them according to LDAP.
  # This is useful for things like the auditbot.
  # Patterns listed here will be wrapped in ^ and $ before matching.
  allowed_users:
  - '@adminbot:.*'
  # Optional. Determines whether users will be automatically invited to rooms (default, public and space-joinable)
  # when they gain access to them. Defaults to true. Users will still get invited to spaces regardless of this setting.
  invite_to_public_rooms: false
  # Optional: A list of remote Advanced Identity Management we'll be federating with. Requests from other remote users will be ignored.
  federation:
    federates_with:
    - '@gs_bot:consultancy.test'

State representation

Both users and power level targets are currently only represented as a localpart: Advanced Identity Management is meant to manage a single server, where each organization member has an account on the server being provisioned.

Advanced Identity Management is not involved in the registration of user accounts themselves — this is typically handled by Synapse's authentication provider. Some bridges may take this responsibility upon themselves — for example the SCIM bridge, when new User accounts are being sent to it. Still, even in that case, Provisioner is not responsible for ensuring that the accounts exist before it starts managing them.

User provisioning

Advanced Identity Management can be configured to synchronize user accounts found in the bridged data directory to a specified list of targets.

Currently the only supported target is Synapse, and the synchronization is limited to user attributes for already existing accounts.

If you are using the helm chart, this can be configured through groupSync.syncedUserAttributes.

Attribute sync

When users in a data directory change, Advanced Identity Management will ensure that the attributes match those in Synapse (and in the future, other user provisioning targets). Advanced Identity Management will only update users if any updates need to be performed, and only update the attributes it needs to.

Supported attributes are:

Advanced Identity Management can be configured to sync all of them, or a limited set. See the example config for more details.

Federation

Advanced Identity Management supports closed federation — as in, one where all participating servers are known in advance.

Each federated server maintains its own Advanced Identity Management instance, crucially its own Provisioner. Each Provisioner is responsible for managing users belonging to its homeserver, and ignores those that belong to another homeserver and another Provisioner.

The servers are are equal, and any of them may invite other Advanced Identity Management servers to any of its spaces -- but they do need to be on a preconfigured list of servers (see federates_with option in the example config).

When a Advanced Identity Management server wishes to federated with another, it should specify which of its spaces should include a remote Advanced Identity Management server, and which of its groups should be invited.

Example

Let's say we have an organization with two servers -- dallas.example.com and berlin.example.com. Both use Advanced Identity Management with their own data directories.

Dallas has 3 users: Alice, Bob and Cyril. Alice is additionally in a group called "dallas-management".

Berlin has 3 users too: Dave, Eve and Francis. Dave is a member of "berlin-management" group.

We'll set up a space federated between the two, so that users from both servers will end up there, which both managers having a power level of 50.

Federation whitelist

Both provisioners need to have to be aware of the other participating server, so for Dallas we need:

provisioner:
  federates_with: ['@groupsync:berlin.example.com']

And for Berlin:

provisioner:
  federates_with: ['@groupsync:dallas.example.com']

Without having that configured, each Advanced Identity Management will ignore the requests sent by the other one, in order to not accidentally expose information to an untrusted party.

Note that Matrix IDs in the federates_with section must match the other servers: both the server_names and the sender_localparts, so that Advanced Identity Managements know how to invite to rooms and spaces as co-conspirators.

Federated space mapping

While the space will be replicated on both servers, with both being equally responsible for it, we need to pick a server to create it on. Let's do it on the Dallas server:

- id: shared
  name: 'Federated space'
  groups:
    - externalId: '' # include all our users
    - externalId: 'dallas-managers'
      powerLevel: 50
  federatedGroups:
      # The MXID of the remote Advanced Identity Management bot.
      agent: '@groupsync:berlin.example.com'
    - externalId: '' # include all users known to the Berlin Advanced Identity Management
    - externalId: 'berlin-managers'
      powerLevel: 50

No additional configuration is needed on the Berlin server.

Once this configuration is applied, the following thing will happen:

Room Cleanup

Room cleanup

After each provisioning cycle, Advanced Identity Management will clean up the rooms and spaces that it no longer needs to manage. Spaces in Matrix are still rooms, but we treat them a little differently during the cleanup, matching their distinct uses.

Internally, room cleanup is refered to as Room GC (Garbage Collection).

This is meant to be a reversible process (in case it was performed accidentally), so we avoid information loss when possible.

Space cleanup

Spaces are cleaned up when they are no longer configured -- once they are removed from Space mapping configuration, Advanced Identity Management will abandon them by kicking every member and then leaving itself

The kicking of the users is done so that the deconfigured spaces don't show up in their clients anymore. The rooms inside those spaces remain accessible though, so no conversations are being lost.

We don't draw a distinction here between GS- and user-created spaces, because GS doesn't care about user-created spaces at all. It never joins them and it never manages them, so they will never be part of the cleanup process.

Room cleanup

Rooms are cleaned up when they're no longer accessible from any of the spaces that Advanced Identity Management manages. This can happen in a few cases:

  1. The room belonged to a space that was cleaned up up by Advanced Identity Management
  2. The room has been removed from a space managed by Advanced Identity Management
  3. The room is made private (but remains in a managed space)

Notably, none of these apply if a default rooms gets deconfigured in Advanced Identity Management. Those get created in each GS-managed space, but after their creation they're treated like any other space-public[^note] room.

When a room is cleaned up, GS cleans up its room metadata (this is stored in state events) and leaves the room. All the room members remain in the room so that the conversation is preserved and can continue if needed. Room moderators can then tombstone the room if they so desire, or add it to a different space.

If the room was not originally created by Advanced Identity Management, we give PL 100 back to its original creator (having taken it away back when we took control of it). If a room was created by Advanced Identity Management, its power levels are not touched. Advanced Identity Management remains a room admin in case it needs to take control of the room again in the future (e.g. because it gets added to a different managed space).

[^note]: Space-public meaning: with join_rule: restricted, allowing space members to join.

Configuration

Room and Space cleanup can be configured through :


provisioner:
  # Optional. When enabled, spaces that are no longer configured, and rooms belonging to those spaces will be cleaned up.
  # This will likely become enabled by default in the future.
  # When disabled (or omitted), GS will log the rooms and spaces it would clean up if allowed to.
  gc:
    enabled: true

Usage Scenarios

Usage Scenarios

With LDAP bridge as an example data source.

Onboarding

For the following sections, we assume a hierarchy of LDAP Organizational Units:

Restructuring

Offboarding

Permission management

LDAP as a source of truth

User Deletion

When user are no longer desired on the AIM-managed server, they fall under the user deletion flow described here.

Deletion criteria

They are considered no longer desired if they are present in the root space of the organization, but they're not on the list of users who are supposed to be provisioned. In a GS-managed server this will only happen if a user was first added to the directory (and provisioned), and then removed from it.

Potential issues

If a user who was never part of the directory finds themselves in the company space somehow, they will be subject to the user deletion flow as well. This should never happen, as GS will not ever invite them to the root space by itself. However, a user with Admin (PL 100) permissions could invite them to the root space manually, which would make GS consider them a deletion candidate -- despite them never being part of a the directory and not being managed by GS before that point.

Configuration

User deletion can happen either instantly, or delayed by a configurable "grace period". In practice, the instant deletion is implemented the exact same way as the delayed deletion, but with grace period set to 0 seconds. It's controlled by the user_soft_delete_period parameter in the config, and leaving it unset is the same as setting it to "0s".

userProvisioner:
  # Optional. Configure to enable user deprovisioning. Disabled by default.
  deprovisioning:
    enabled: false
    # Optional. When users get removed from the directory their accounts will only be deactivated,
    # but their erasure will be delayed by the specified time period, allowing them to be reactivated in the meantime.
    # The format is <amount><unit>, with amount being numeric and unit being one of: [s, m, h, d], for seconds, minutes,
    # hours or days respectively (for example: "24h", "31d" etc.).
    # The specified period will be translated into seconds, so won't account for things like DST, leap seconds etc.
    # Users will be deleted *no sooner* than that, but may be removed a bit later, depending on other Advanced Identity Management operations.
    # By default set to 30 days.
    soft_delete_period: '30d'

Actions performed instantly

When a user is found to be undesirable, their Matrix account is deactivated, preventing them from logging in. They are not being removed from any rooms though, and their permissions and power levels stay the same. It's equivalent to using a deactivate user Synapse API (with erase set to false).

If a grace period is configured and the user gets added back to the directory before they get deleted completely, their account will get reactivated.

The user then gets put on the "grace period" list.

NOTE: Historically Advanced Identity Management would reset the password for the user to a random value, but modern versions will just lock the account.

Actions performed after the grace period

Once the grace period expires for a user, they get erased from the server. This is done under the hood by the Synapse API deactivate user, with erase set to true.