zitadel / zitadel

ZITADEL - Identity infrastructure, simplified for you.
https://zitadel.com
Apache License 2.0
9.11k stars 582 forks source link

[Epic]: Actions v2 - Extend ZITADEL with custom executions and triggers #7235

Open adlerhurst opened 10 months ago

adlerhurst commented 10 months ago

Actions v2

This feature allows further customization of ZITADEL. The admin will be able to provide an endpoint to manipulate the request before zitadel handles a request, manipulate the response before it's sent to the client, react on events which were stored or hook into predefined trigger points to complement a token for example.

The custom code is a REST API server managed by the customer, ZITADEL will call the provided endpoint and either use the HTTP status code of the response or even the response body depending on your configuration.

Examples of configurations and diagrams can be found in this comment

This epic summarises the action items for the new actions features. Based on the "Future of Actions"-Discussion

Basic implementation

The following tasks build the foundation of actions when these tasks are finished admins are able to use the new version of actions.

Future Tasks

Tasks which are not yet planned but will come up in the future.

Secure call

This milestone will add security to actions. The goal is to allow the server to verify if the call was made by ZITADEL.

API contract

This milestone adds API contracts to actions, this allows easier implementation of actions because of defined contracts. There are also generators for many languages which allows code generation of the server for your language.

SDKs

SDKs allow easy implementation of actions. A developer should only implement the handler and the SDK starts the server to listen to events.

Per language

If possible extend the already existing SDK

Targets

The object describes how ZITADEL interacts with the action.

Response codes of the action are handled as follows:

Targets can be managed with the following calls:

Request execution

It's possible to set the following conditions:

ZITADEL decides which condition is triggered like a proxy, the most exact match is executed. A condition is allowed once per instance.

Requests can be managed with the following calls:

Response execution

It's possible to set the following conditions:

ZITADEL decides which condition is triggered like a proxy, the most exact match is executed. A condition is allowed once per instance.

Responses can be managed with the following calls:

Function execution

It's possible to set the following conditions:

The condition only allows exact match. A condition is allowed once per instance.

Functions can be managed with the following calls:

Event execution

ZITADEL decides which condition is triggered like a proxy, the most exact match is executed. A condition is allowed once per instance. ZITADEL sends events in the order they occurred and uses the same logic as for internal projections to execute the calls to the targets, including timeouts, failure handling, retries.

Events can be managed with the following calls:

adlerhurst commented 10 months ago

Examples

Show case

sequenceDiagram
    actor Client
    Client->>+ZITADEL: Create User
    ZITADEL->>ZITADEL: Get request execution for create user
    ZITADEL->>+AddMetadataToUser: request info
    AddMetadataToUser->>AddMetadataToUser: Add metadata
    AddMetadataToUser-->>-ZITADEL: updated user, ok
    ZITADEL->>ZITADEL: Store events
    ZITADEL->>ZITADEL: Get execution for "user.added" event
    ZITADEL->>+UserAddedHook: event (background processing)
    UserAddedHook->>LDAP: Store new user
    UserAddedHook-->>-ZITADEL: ok
    ZITADEL->>ZITADEL: Get response execution for create user
    ZITADEL->>+ResponseStateAsyncHook: response info
    ZITADEL->>-Client: ok
    ResponseStateAsyncHook->>-ResponseStateAsyncHook: Log user id

configuration

requests:
  all_requests:
    targets: 
      - target: logger
      - target: allow_list
  user_service:
    targets: 
      - include: all_requests
      - target: call_counter
  change_user:
    targets: 
      - target: all_requests
  add_user:
    targets:
      - target: set_display_name
      - include: all_requests
      - include: user_service

responses:
  all_responses:
    targets: 
      - target: hook
  user_service:
    # hook is called twice in this example
    targets: 
      - include: all_responses
      - target: hook
  change_user:
    targets:
      - include: all_responses
      - target: hook
  add_user:
    targets:
      - include: user_service
      - target: hook

# for events only targets of type REST webhook are allowed allowed
events:
  "project.*":
    targets:
      - target: handler
      - target: queue
  "user.added":
    targets:
      - target: webhook1
      - target: webhook2

function:
  create_id_token:
    targets: 
      - target: hook

targets:
  allow_list:
    # response is not mapped to object
    # only status code is relevant
    type: REST webhook
    url: https://my.super.duper/endpoint/ip/allow/list
    timeout: 10s
    # returns an error if status code is >= 400
    Interrupt_on_error: true
    async: false
  allow_list_ignore_err:
    type: REST webhook
    url: https://my.super.duper/endpoint/ip/allow/list
    timeout: 10s
    Interrupt_on_error: false
    # awaiting http status
    async: false
  call_counter:
    type: REST webhook
    url: https://my.super.duper/endpoint/count/calls
    async: true
    timeout: 1s
    Interrupt_on_error: true
  logger:
    # response is NOT mapped to object
    type: REST webhook
    url: https://my.super.duper/endpoint/logger
    # NOT waiting for response
    async: true
    # allow_to_fail is irrelevant if async is true
    Interrupt_on_error: false
  set_display_name:
    # waiting for response
    # response is mapped to object
    type: REST request response
    url: https://my.super.duper/endpoint/users/displayname
    Interrupt_on_error: true
    timeout: 1s
hifabienne commented 10 months ago

Related Issues: Actions: Provide trigger to run actions on user management events

vs-gtadeu commented 9 months ago

@hifabienne, question about this epic: would it enable the management of Actions at the instance level?

We plan to use organizations to represent and isolate customers, but because Actions live at the organization, we would have to manage and duplicate actions thousands of times.

adlerhurst commented 9 months ago

Hi @vs-gtadeu Actions v2 will come available on org level before we deprecate actions v1. Actions v2 will start on instance level before it comes to org level

muhlemmer commented 1 day ago

As this is currently on the Q1-2025 roadmap, we should start defining all the sub-issues that will be part of the Q1 Epic and estimate. I would propose to move anything we do not wish for Q1 to a separate issue to be planned at a later stage.

@adlerhurst as you are the architect of the actions, can you start doing those preparations?