diff --git a/authentik/events/migrations/0011_notification_trigger_default_v1.py b/authentik/events/migrations/0011_notification_trigger_default_v1.py index 5601c90a3..3f85fed6f 100644 --- a/authentik/events/migrations/0011_notification_trigger_default_v1.py +++ b/authentik/events/migrations/0011_notification_trigger_default_v1.py @@ -16,9 +16,11 @@ def notify_configuration_error(apps: Apps, schema_editor: BaseDatabaseSchemaEdit ) NotificationTrigger = apps.get_model("authentik_events", "NotificationTrigger") - admin_group = Group.objects.using(db_alias).filter( - name="authentik Admins", is_superuser=True - ).first() + admin_group = ( + Group.objects.using(db_alias) + .filter(name="authentik Admins", is_superuser=True) + .first() + ) policy, _ = EventMatcherPolicy.objects.using(db_alias).update_or_create( name="default-match-configuration-error", @@ -45,9 +47,11 @@ def notify_update(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): ) NotificationTrigger = apps.get_model("authentik_events", "NotificationTrigger") - admin_group = Group.objects.using(db_alias).filter( - name="authentik Admins", is_superuser=True - ).first() + admin_group = ( + Group.objects.using(db_alias) + .filter(name="authentik Admins", is_superuser=True) + .first() + ) policy, _ = EventMatcherPolicy.objects.using(db_alias).update_or_create( name="default-match-update", @@ -74,9 +78,11 @@ def notify_exception(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): ) NotificationTrigger = apps.get_model("authentik_events", "NotificationTrigger") - admin_group = Group.objects.using(db_alias).filter( - name="authentik Admins", is_superuser=True - ).first() + admin_group = ( + Group.objects.using(db_alias) + .filter(name="authentik Admins", is_superuser=True) + .first() + ) policy_policy_exc, _ = EventMatcherPolicy.objects.using(db_alias).update_or_create( name="default-match-policy-exception", diff --git a/website/docs/events/event_matcher.png b/website/docs/events/event_matcher.png new file mode 100644 index 000000000..a89adedcb Binary files /dev/null and b/website/docs/events/event_matcher.png differ diff --git a/website/docs/events/index.md b/website/docs/events/index.md new file mode 100644 index 000000000..0ce3271a4 --- /dev/null +++ b/website/docs/events/index.md @@ -0,0 +1,33 @@ +--- +title: Events +--- + +Events are authentik's built-in logging system. Whenever any of the following actions occur, an event is created: + +- A user logs in/logs out (including the source, if available) +- A user fails to login +- A user sets their password + +- A user views a token + +- An invitation is used + +- A user object is written to during a flow + +- A user authorizes an application +- A user links a source to their account + +- A user starts/ends impersonation, including the user that was impersonated + +- A policy is executed (when a policy has "Execution Logging" enabled) +- A policy or property mapping causes an exception + +- A configuration error occurs, for example during the authorization of an application + +- Any objects is created/updated/deleted + +- An update is available + +Certain information is stripped from events, to ensure no passwords or other credentials are saved in the log. + +If you want to forward these events to another application, simply forward the log output of all authentik containers. Every event creation is logged there. diff --git a/website/docs/events/notifications.md b/website/docs/events/notifications.md new file mode 100644 index 000000000..15c5a64b1 --- /dev/null +++ b/website/docs/events/notifications.md @@ -0,0 +1,31 @@ +--- +title: Notifications +--- + +## Filtering Events + +Starting with authentik 0.15, you can create notification triggers, which can alert you based on the creation of certain events. + +Filtering is done by using the Policy Engine. You can do simple filtering using the "Event Matcher Policy" type + +![](./event_matcher.png) + +An Event has to match all configured fields, otherwise it will not match. + +To match events with an "Expression Policy", you can write code like so + +```python +if "event" not in request.context: + return False + +return ip_address(request.context["evnet"].client_ip) in ip_network('192.0.2.0/24') +``` + +## Selecting who gets notified + +After you've create the policies to match the events you want, create a "Notification Trigger". + +You have to select which group the generated notification should be sent to. If left empty, the trigger will be disabled. + +You also have to select which transports should be used to send the Notification. +A transport with the name "default-email-transport" is created by default. This transport will use the [global email configuration](../installation/docker-compose#email-configuration-optional-but-recommended) diff --git a/website/docs/events/transports.md b/website/docs/events/transports.md new file mode 100644 index 000000000..d50293efd --- /dev/null +++ b/website/docs/events/transports.md @@ -0,0 +1,28 @@ +--- +title: Transports +--- + +Notifications can be sent to users via multiple mediums. Per default, the [global email configuration](../installation/docker-compose#email-configuration-optional-but-recommended) will be used. + +## Generic Webhook + +This will send a POST request to the given URL with the following contents: + +```json +{ + "body": "body of the notification message", + "severity": "severity level as configured in the trigger", + "user_email": "user's email", + "user_username": "user's username", +} +``` + +The `Content-Type` Header is set to `text/json`. + +:::warning +This will send a request for each user of the group selected in the trigger. +::: + +## Slack Webhook + +This sends a request using the Slack-specific format. This is also compatible with Discord's Webhooks by appending `/slack`. diff --git a/website/sidebars.js b/website/sidebars.js index 62a3d6f44..3f90a1b23 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -85,6 +85,15 @@ module.exports = { }, ], }, + { + type: "category", + label: "Events", + items: [ + "events/index", + "events/notifications", + "events/transports" + ], + }, { type: "category", label: "Integrations",