chore!: Introduce ZITADEL v3 (#9645)

This PR summarizes multiple changes specifically only available with
ZITADEL v3:

- feat: Web Keys management
(https://github.com/zitadel/zitadel/pull/9526)
- fix(cmd): ensure proper working of mirror
(https://github.com/zitadel/zitadel/pull/9509)
- feat(Authz): system user support for permission check v2
(https://github.com/zitadel/zitadel/pull/9640)
- chore(license): change from Apache to AGPL
(https://github.com/zitadel/zitadel/pull/9597)
- feat(console): list v2 sessions
(https://github.com/zitadel/zitadel/pull/9539)
- fix(console): add loginV2 feature flag
(https://github.com/zitadel/zitadel/pull/9682)
- fix(feature flags): allow reading "own" flags
(https://github.com/zitadel/zitadel/pull/9649)
- feat(console): add Actions V2 UI
(https://github.com/zitadel/zitadel/pull/9591)

BREAKING CHANGE
- feat(webkey): migrate to v2beta API
(https://github.com/zitadel/zitadel/pull/9445)
- chore!: remove CockroachDB Support
(https://github.com/zitadel/zitadel/pull/9444)
- feat(actions): migrate to v2beta API
(https://github.com/zitadel/zitadel/pull/9489)

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Ramon <mail@conblem.me>
Co-authored-by: Elio Bischof <elio@zitadel.com>
Co-authored-by: Kenta Yamaguchi <56732734+KEY60228@users.noreply.github.com>
Co-authored-by: Harsha Reddy <harsha.reddy@klaviyo.com>
Co-authored-by: Livio Spring <livio@zitadel.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Iraq <66622793+kkrime@users.noreply.github.com>
Co-authored-by: Florian Forster <florian@zitadel.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Max Peintner <peintnerm@gmail.com>
This commit is contained in:
Fabienne Bühler
2025-04-02 16:53:06 +02:00
committed by GitHub
parent d14a23ae7e
commit 07ce3b6905
559 changed files with 14578 additions and 7622 deletions

View File

@@ -0,0 +1,725 @@
syntax = "proto3";
package zitadel.action.v2beta;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/action/v2beta/target.proto";
import "zitadel/action/v2beta/execution.proto";
import "zitadel/action/v2beta/query.proto";
import "google/protobuf/timestamp.proto";
import "zitadel/filter/v2beta/filter.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v2beta;action";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Action Service";
version: "2.0-beta";
description: "This API is intended to manage custom executions (previously known as actions) in a ZITADEL instance. This service is in beta state. It can AND will continue breaking until a stable version is released.";
contact:{
name: "ZITADEL"
url: "https://zitadel.com"
email: "hi@zitadel.com"
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;
schemes: HTTP;
consumes: "application/json";
consumes: "application/grpc";
produces: "application/json";
produces: "application/grpc";
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "$CUSTOM-DOMAIN";
base_path: "/";
external_docs: {
description: "Detailed information about ZITADEL",
url: "https://zitadel.com/docs"
}
security_definitions: {
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
value: "openid";
}
scope: {
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "openid";
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
};
// Service to manage custom executions.
// The service provides methods to create, update, delete and list targets and executions.
service ActionService {
// Create Target
//
// Create a new target to your endpoint, which can be used in executions.
//
// Required permission:
// - `action.target.write`
//
// Required feature flag:
// - `actions`
rpc CreateTarget (CreateTargetRequest) returns (CreateTargetResponse) {
option (google.api.http) = {
post: "/v2beta/actions/targets"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target created successfully";
};
};
responses: {
key: "409"
value: {
description: "The target to create already exists.";
}
};
responses: {
key: "400"
value: {
description: "The feature flag `actions` is not enabled.";
}
};
};
}
// Update Target
//
// Update an existing target.
// To generate a new signing key set the optional expirationSigningKey.
//
// Required permission:
// - `action.target.write`
//
// Required feature flag:
// - `actions`
rpc UpdateTarget (UpdateTargetRequest) returns (UpdateTargetResponse) {
option (google.api.http) = {
post: "/v2beta/actions/targets/{id}"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target successfully updated or left unchanged";
};
};
responses: {
key: "404"
value: {
description: "The target to update does not exist.";
}
};
responses: {
key: "400"
value: {
description: "The feature flag `actions` is not enabled.";
}
};
};
}
// Delete Target
//
// Delete an existing target. This will remove it from any configured execution as well.
// In case the target is not found, the request will return a successful response as
// the desired state is already achieved.
//
// Required permission:
// - `action.target.delete`
//
// Required feature flag:
// - `actions`
rpc DeleteTarget (DeleteTargetRequest) returns (DeleteTargetResponse) {
option (google.api.http) = {
delete: "/v2beta/actions/targets/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target deleted successfully";
};
};
responses: {
key: "400"
value: {
description: "The feature flag `actions` is not enabled.";
}
};
};
}
// Get Target
//
// Returns the target identified by the requested ID.
//
// Required permission:
// - `action.target.read`
//
// Required feature flag:
// - `actions`
rpc GetTarget (GetTargetRequest) returns (GetTargetResponse) {
option (google.api.http) = {
get: "/v2beta/actions/targets/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "Target retrieved successfully";
}
};
responses: {
key: "404"
value: {
description: "The target to update does not exist.";
}
};
responses: {
key: "400"
value: {
description: "The feature flag `actions` is not enabled.";
}
};
};
}
// List targets
//
// List all matching targets. By default all targets of the instance are returned.
// Make sure to include a limit and sorting for pagination.
//
// Required permission:
// - `action.target.read`
//
// Required feature flag:
// - `actions`
rpc ListTargets (ListTargetsRequest) returns (ListTargetsResponse) {
option (google.api.http) = {
post: "/v2beta/actions/targets/_search",
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "A list of all targets matching the query";
};
};
responses: {
key: "400";
value: {
description: "invalid list query";
};
};
responses: {
key: "400"
value: {
description: "The feature flag `actions` is not enabled.";
}
};
};
}
// Set Execution
//
// Sets an execution to call a target or include the targets of another execution.
// Setting an empty list of targets will remove all targets from the execution, making it a noop.
//
// Required permission:
// - `action.execution.write`
//
// Required feature flag:
// - `actions`
rpc SetExecution (SetExecutionRequest) returns (SetExecutionResponse) {
option (google.api.http) = {
put: "/v2beta/actions/executions"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.execution.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Execution successfully updated or left unchanged";
};
};
responses: {
key: "400"
value: {
description: "Condition to set execution does not exist or the feature flag `actions` is not enabled.";
}
};
};
}
// List Executions
//
// List all matching executions. By default all executions of the instance are returned that have at least one execution target.
// Make sure to include a limit and sorting for pagination.
//
// Required permission:
// - `action.execution.read`
//
// Required feature flag:
// - `actions`
rpc ListExecutions (ListExecutionsRequest) returns (ListExecutionsResponse) {
option (google.api.http) = {
post: "/v2beta/actions/executions/_search"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.execution.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "A list of all non noop executions matching the query";
};
};
responses: {
key: "400";
value: {
description: "Invalid list query or the feature flag `actions` is not enabled.";
};
};
};
}
// List Execution Functions
//
// List all available functions which can be used as condition for executions.
rpc ListExecutionFunctions (ListExecutionFunctionsRequest) returns (ListExecutionFunctionsResponse) {
option (google.api.http) = {
get: "/v2beta/actions/executions/functions"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all functions successfully";
};
};
};
}
// List Execution Methods
//
// List all available methods which can be used as condition for executions.
rpc ListExecutionMethods (ListExecutionMethodsRequest) returns (ListExecutionMethodsResponse) {
option (google.api.http) = {
get: "/v2beta/actions/executions/methods"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all methods successfully";
};
};
};
}
// List Execution Services
//
// List all available services which can be used as condition for executions.
rpc ListExecutionServices (ListExecutionServicesRequest) returns (ListExecutionServicesResponse) {
option (google.api.http) = {
get: "/v2beta/actions/executions/services"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all services successfully";
};
};
};
}
}
message CreateTargetRequest {
string name = 1 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\"";
min_length: 1
max_length: 1000
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
option (validate.required) = true;
// Wait for response but response body is ignored, status is checked, call is sent as post.
RESTWebhook rest_webhook = 2;
// Wait for response and response body is used, status is checked, call is sent as post.
RESTCall rest_call = 3;
// Call is executed in parallel to others, ZITADEL does not wait until the call is finished. The state is ignored, call is sent as post.
RESTAsync rest_async = 4;
}
// Timeout defines the duration until ZITADEL cancels the execution.
// If the target doesn't respond before this timeout expires, then the connection is closed and the action fails. Depending on the target type and possible setting on `interrupt_on_error` following targets will not be called. In case of a `rest_async` target only this specific target will fail, without any influence on other targets of the same execution.
google.protobuf.Duration timeout = 5 [
(validate.rules).duration = {gte: {}, lte: {seconds: 270}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
string endpoint = 6 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\""
min_length: 1
max_length: 1000
}
];
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
example: "{\"name\": \"ip_allow_list\",\"restWebhook\":{\"interruptOnError\":true},\"timeout\":\"10s\",\"endpoint\":\"https://example.com/hooks/ip_check\"}";
};
}
message CreateTargetResponse {
// The unique identifier of the newly created target.
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629012906488334\"";
}
];
// The timestamp of the target creation.
google.protobuf.Timestamp creation_date = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2024-12-18T07:50:47.492Z\"";
}
];
// Key used to sign and check payload sent to the target.
string signing_key = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"98KmsU67\""
}
];
}
message UpdateTargetRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
optional string name = 2 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\""
min_length: 1
max_length: 1000
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
// Wait for response but response body is ignored, status is checked, call is sent as post.
RESTWebhook rest_webhook = 3;
// Wait for response and response body is used, status is checked, call is sent as post.
RESTCall rest_call = 4;
// Call is executed in parallel to others, ZITADEL does not wait until the call is finished. The state is ignored, call is sent as post.
RESTAsync rest_async = 5;
}
// Timeout defines the duration until ZITADEL cancels the execution.
// If the target doesn't respond before this timeout expires, then the connection is closed and the action fails. Depending on the target type and possible setting on `interrupt_on_error` following targets will not be called. In case of a `rest_async` target only this specific target will fail, without any influence on other targets of the same execution.
optional google.protobuf.Duration timeout = 6 [
(validate.rules).duration = {gte: {}, lte: {seconds: 270}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
optional string endpoint = 7 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\""
min_length: 1
max_length: 1000
}
];
// Regenerate the key used for signing and checking the payload sent to the target.
// Set the graceful period for the existing key. During that time, the previous
// signing key and the new one will be used to sign the request to allow you a smooth
// transition onf your API.
//
// Note that we currently only allow an immediate rotation ("0s") and will support
// longer expirations in the future.
optional google.protobuf.Duration expiration_signing_key = 8 [
(validate.rules).duration = {const: {seconds: 0, nanos: 0}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"0s\""
minimum: 0
maximum: 0
}
];
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
example: "{\"name\": \"ip_allow_list\",\"restCall\":{\"interruptOnError\":true},\"timeout\":\"10s\",\"endpoint\":\"https://example.com/hooks/ip_check\",\"expirationSigningKey\":\"0s\"}";
};
}
message UpdateTargetResponse {
// The timestamp of the change of the target.
google.protobuf.Timestamp change_date = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2025-01-23T10:34:18.051Z\"";
}
];
// Key used to sign and check payload sent to the target.
optional string signing_key = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"98KmsU67\""
}
];
}
message DeleteTargetRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message DeleteTargetResponse {
// The timestamp of the deletion of the target.
// Note that the deletion date is only guaranteed to be set if the deletion was successful during the request.
// In case the deletion occurred in a previous request, the deletion date might be empty.
google.protobuf.Timestamp deletion_date = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2025-01-23T10:34:18.051Z\"";
}
];
}
message GetTargetRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message GetTargetResponse {
Target target = 1;
}
message ListTargetsRequest {
// List limitations and ordering.
optional zitadel.filter.v2beta.PaginationRequest pagination = 1;
// The field the result is sorted by. The default is the creation date. Beware that if you change this, your result pagination might be inconsistent.
optional TargetFieldName sorting_column = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"TARGET_FIELD_NAME_CREATION_DATE\""
}
];
// Define the criteria to query for.
repeated TargetSearchFilter filters = 3;
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
example: "{\"pagination\":{\"offset\":0,\"limit\":0,\"asc\":true},\"sortingColumn\":\"TARGET_FIELD_NAME_CREATION_DATE\",\"filters\":[{\"targetNameFilter\":{\"targetName\":\"ip_allow_list\",\"method\":\"TEXT_FILTER_METHOD_EQUALS\"}},{\"inTargetIdsFilter\":{\"targetIds\":[\"69629023906488334\",\"69622366012355662\"]}}]}";
};
}
message ListTargetsResponse {
zitadel.filter.v2beta.PaginationResponse pagination = 1;
repeated Target result = 2;
}
message SetExecutionRequest {
// Condition defining when the execution should be used.
Condition condition = 1;
// Ordered list of targets/includes called during the execution.
repeated ExecutionTargetType targets = 2;
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
example: "{\"condition\":{\"request\":{\"method\":\"zitadel.session.v2.SessionService/ListSessions\"}},\"targets\":[{\"target\":\"69629026806489455\"}]}";
};
}
message SetExecutionResponse {
// The timestamp of the execution set.
google.protobuf.Timestamp set_date = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2024-12-18T07:50:47.492Z\"";
}
];
}
message ListExecutionsRequest {
// List limitations and ordering.
optional zitadel.filter.v2beta.PaginationRequest pagination = 1;
// The field the result is sorted by. The default is the creation date. Beware that if you change this, your result pagination might be inconsistent.
optional ExecutionFieldName sorting_column = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"EXECUTION_FIELD_NAME_CREATION_DATE\""
}
];
// Define the criteria to query for.
repeated ExecutionSearchFilter filters = 3;
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
example: "{\"pagination\":{\"offset\":0,\"limit\":0,\"asc\":true},\"sortingColumn\":\"EXECUTION_FIELD_NAME_ID\",\"filters\":[{\"targetFilter\":{\"targetId\":\"69629023906488334\"}}]}";
};
}
message ListExecutionsResponse {
zitadel.filter.v2beta.PaginationResponse pagination = 1;
repeated Execution result = 2;
}
message ListExecutionFunctionsRequest{}
message ListExecutionFunctionsResponse{
// All available methods
repeated string functions = 1;
}
message ListExecutionMethodsRequest{}
message ListExecutionMethodsResponse{
// All available methods
repeated string methods = 1;
}
message ListExecutionServicesRequest{}
message ListExecutionServicesResponse{
// All available methods
repeated string services = 1;
}

View File

@@ -1,6 +1,6 @@
syntax = "proto3";
package zitadel.resources.action.v3alpha;
package zitadel.action.v2beta;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
@@ -10,21 +10,27 @@ import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/resources/object/v3alpha/object.proto";
import "google/protobuf/timestamp.proto";
import "zitadel/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v2beta;action";
message Execution {
Condition condition = 1;
// The timestamp of the execution creation.
google.protobuf.Timestamp creation_date = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2024-12-18T07:50:47.492Z\"";
}
];
// The timestamp of the last change to the execution.
google.protobuf.Timestamp change_date = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2025-01-23T10:34:18.051Z\"";
}
];
// Ordered list of targets/includes called during the execution.
repeated ExecutionTargetType targets = 1;
}
message GetExecution {
zitadel.resources.object.v3alpha.Details details = 1;
Condition condition = 2;
Execution execution = 3;
repeated ExecutionTargetType targets = 4;
}
message ExecutionTargetType {

View File

@@ -1,15 +1,16 @@
syntax = "proto3";
package zitadel.resources.action.v3alpha;
package zitadel.action.v2beta;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v2beta;action";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "google/protobuf/timestamp.proto";
import "zitadel/resources/object/v3alpha/object.proto";
import "zitadel/resources/action/v3alpha/execution.proto";
import "zitadel/action/v2beta/execution.proto";
import "zitadel/filter/v2beta/filter.proto";
message ExecutionSearchFilter {
oneof filter {
@@ -52,6 +53,18 @@ message IncludeFilter {
];
}
enum TargetFieldName {
TARGET_FIELD_NAME_UNSPECIFIED = 0;
TARGET_FIELD_NAME_ID = 1;
TARGET_FIELD_NAME_CREATED_DATE = 2;
TARGET_FIELD_NAME_CHANGED_DATE = 3;
TARGET_FIELD_NAME_NAME = 4;
TARGET_FIELD_NAME_TARGET_TYPE = 5;
TARGET_FIELD_NAME_URL = 6;
TARGET_FIELD_NAME_TIMEOUT = 7;
TARGET_FIELD_NAME_INTERRUPT_ON_ERROR = 8;
}
message TargetSearchFilter {
oneof filter {
option (validate.required) = true;
@@ -71,7 +84,7 @@ message TargetNameFilter {
}
];
// Defines which text comparison method used for the name query.
zitadel.resources.object.v3alpha.TextFilterMethod method = 2 [
zitadel.filter.v2beta.TextFilterMethod method = 2 [
(validate.rules).enum.defined_only = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "defines which text equality method is used";
@@ -97,21 +110,10 @@ enum ExecutionType {
EXECUTION_TYPE_FUNCTION = 4;
}
enum TargetFieldName {
TARGET_FIELD_NAME_UNSPECIFIED = 0;
TARGET_FIELD_NAME_ID = 1;
TARGET_FIELD_NAME_CREATED_DATE = 2;
TARGET_FIELD_NAME_CHANGED_DATE = 3;
TARGET_FIELD_NAME_NAME = 4;
TARGET_FIELD_NAME_TARGET_TYPE = 5;
TARGET_FIELD_NAME_URL = 6;
TARGET_FIELD_NAME_TIMEOUT = 7;
TARGET_FIELD_NAME_INTERRUPT_ON_ERROR = 8;
}
enum ExecutionFieldName {
EXECUTION_FIELD_NAME_UNSPECIFIED = 0;
EXECUTION_FIELD_NAME_ID = 1;
EXECUTION_FIELD_NAME_CREATED_DATE = 2;
EXECUTION_FIELD_NAME_CHANGED_DATE = 3;
}
}

View File

@@ -0,0 +1,75 @@
syntax = "proto3";
package zitadel.action.v2beta;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "google/protobuf/timestamp.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v2beta;action";
message Target {
// The unique identifier of the target.
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629012906488334\"";
}
];
// The timestamp of the target creation.
google.protobuf.Timestamp creation_date = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2024-12-18T07:50:47.492Z\"";
}
];
// The timestamp of the last change to the target (e.g. creation, activation, deactivation).
google.protobuf.Timestamp change_date = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2025-01-23T10:34:18.051Z\"";
}
];
string name = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\"";
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
RESTWebhook rest_webhook = 5;
RESTCall rest_call = 6;
RESTAsync rest_async = 7;
}
// Timeout defines the duration until ZITADEL cancels the execution.
// If the target doesn't respond before this timeout expires, the the connection is closed and the action fails. Depending on the target type and possible setting on `interrupt_on_error` following targets will not be called. In case of a `rest_async` target only this specific target will fail, without any influence on other targets of the same execution.
google.protobuf.Duration timeout = 8 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
string endpoint = 9 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\""
}
];
string signing_key = 10 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"98KmsU67\""
}
];
}
message RESTWebhook {
// Define if any error stops the whole execution. By default the process continues as normal.
bool interrupt_on_error = 1;
}
message RESTCall {
// Define if any error stops the whole execution. By default the process continues as normal.
bool interrupt_on_error = 1;
}
message RESTAsync {}

View File

@@ -41,7 +41,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
tags: [

View File

@@ -25,7 +25,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;
@@ -113,6 +113,12 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
// reserving the proto field number. Such removal is not considered a breaking change.
// Setting a removed field will effectively result in a no-op.
service FeatureService {
// Set System Features
//
// Configure and set features that apply to the complete system. Only fields present in the request are set or unset.
//
// Required permissions:
// - system.feature.write
rpc SetSystemFeatures (SetSystemFeaturesRequest) returns (SetSystemFeaturesResponse) {
option (google.api.http) = {
put: "/v2/features/system"
@@ -126,8 +132,6 @@ service FeatureService {
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Set system level features";
description: "Configure and set features that apply to the complete system. Only fields present in the request are set or unset."
responses: {
key: "200"
value: {
@@ -137,6 +141,12 @@ service FeatureService {
};
}
// Reset System Features
//
// Deletes ALL configured features for the system, reverting the behaviors to system defaults.
//
// Required permissions:
// - system.feature.delete
rpc ResetSystemFeatures (ResetSystemFeaturesRequest) returns (ResetSystemFeaturesResponse) {
option (google.api.http) = {
delete: "/v2/features/system"
@@ -149,8 +159,6 @@ service FeatureService {
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Reset system level features";
description: "Deletes ALL configured features for the system, reverting the behaviors to system defaults."
responses: {
key: "200"
value: {
@@ -160,6 +168,12 @@ service FeatureService {
};
}
// Get System Features
//
// Returns all configured features for the system. Unset fields mean the feature is the current system default.
//
// Required permissions:
// - none
rpc GetSystemFeatures (GetSystemFeaturesRequest) returns (GetSystemFeaturesResponse) {
option (google.api.http) = {
get: "/v2/features/system"
@@ -167,13 +181,11 @@ service FeatureService {
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "system.feature.read"
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Get system level features";
description: "Returns all configured features for the system. Unset fields mean the feature is the current system default."
responses: {
key: "200"
value: {
@@ -183,6 +195,12 @@ service FeatureService {
};
}
// Set Instance Features
//
// Configure and set features that apply to a complete instance. Only fields present in the request are set or unset.
//
// Required permissions:
// - iam.feature.write
rpc SetInstanceFeatures (SetInstanceFeaturesRequest) returns (SetInstanceFeaturesResponse) {
option (google.api.http) = {
put: "/v2/features/instance"
@@ -196,8 +214,6 @@ service FeatureService {
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Set instance level features";
description: "Configure and set features that apply to a complete instance. Only fields present in the request are set or unset."
responses: {
key: "200"
value: {
@@ -207,6 +223,12 @@ service FeatureService {
};
}
// Reset Instance Features
//
// Deletes ALL configured features for an instance, reverting the behaviors to system defaults.
//
// Required permissions:
// - iam.feature.delete
rpc ResetInstanceFeatures (ResetInstanceFeaturesRequest) returns (ResetInstanceFeaturesResponse) {
option (google.api.http) = {
delete: "/v2/features/instance"
@@ -219,8 +241,6 @@ service FeatureService {
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Reset instance level features";
description: "Deletes ALL configured features for an instance, reverting the behaviors to system defaults."
responses: {
key: "200"
value: {
@@ -230,6 +250,12 @@ service FeatureService {
};
}
// Get Instance Features
//
// Returns all configured features for an instance. Unset fields mean the feature is the current system default.
//
// Required permissions:
// - none
rpc GetInstanceFeatures (GetInstanceFeaturesRequest) returns (GetInstanceFeaturesResponse) {
option (google.api.http) = {
get: "/v2/features/instance"
@@ -237,13 +263,11 @@ service FeatureService {
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.feature.read"
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Get instance level features";
description: "Returns all configured features for an instance. Unset fields mean the feature is the current system default."
responses: {
key: "200"
value: {
@@ -253,6 +277,12 @@ service FeatureService {
};
}
// Set Organization Features
//
// Configure and set features that apply to a complete instance. Only fields present in the request are set or unset.
//
// Required permissions:
// - org.feature.write
rpc SetOrganizationFeatures (SetOrganizationFeaturesRequest) returns (SetOrganizationFeaturesResponse) {
option (google.api.http) = {
put: "/v2/features/organization/{organization_id}"
@@ -266,8 +296,6 @@ service FeatureService {
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Set organization level features";
description: "Configure and set features that apply to a complete instance. Only fields present in the request are set or unset."
responses: {
key: "200"
value: {
@@ -277,6 +305,12 @@ service FeatureService {
};
}
// Reset Organization Features
//
// Deletes ALL configured features for an organization, reverting the behaviors to instance defaults.
//
// Required permissions:
// - org.feature.delete
rpc ResetOrganizationFeatures (ResetOrganizationFeaturesRequest) returns (ResetOrganizationFeaturesResponse) {
option (google.api.http) = {
delete: "/v2/features/organization/{organization_id}"
@@ -284,13 +318,11 @@ service FeatureService {
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "org.feature.write"
permission: "org.feature.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Reset organization level features";
description: "Deletes ALL configured features for an organization, reverting the behaviors to instance defaults."
responses: {
key: "200"
value: {
@@ -300,6 +332,13 @@ service FeatureService {
};
}
// Get Organization Features
//
// Returns all configured features for an organization. Unset fields mean the feature is the current instance default.
//
// Required permissions:
// - org.feature.read
// - no permission required for the organization the user belongs to
rpc GetOrganizationFeatures(GetOrganizationFeaturesRequest) returns (GetOrganizationFeaturesResponse) {
option (google.api.http) = {
get: "/v2/features/organization/{organization_id}"
@@ -307,13 +346,11 @@ service FeatureService {
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "org.feature.read"
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Get organization level features";
description: "Returns all configured features for an organization. Unset fields mean the feature is the current instance default."
responses: {
key: "200"
value: {
@@ -323,6 +360,12 @@ service FeatureService {
};
}
// Set User Features
//
// Configure and set features that apply to an user. Only fields present in the request are set or unset.
//
// Required permissions:
// - user.feature.write
rpc SetUserFeatures(SetUserFeatureRequest) returns (SetUserFeaturesResponse) {
option (google.api.http) = {
put: "/v2/features/user/{user_id}"
@@ -336,8 +379,6 @@ service FeatureService {
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Set user level features";
description: "Configure and set features that apply to an user. Only fields present in the request are set or unset."
responses: {
key: "200"
value: {
@@ -347,6 +388,12 @@ service FeatureService {
};
}
// Reset User Features
//
// Deletes ALL configured features for a user, reverting the behaviors to organization defaults.
//
// Required permissions:
// - user.feature.delete
rpc ResetUserFeatures(ResetUserFeaturesRequest) returns (ResetUserFeaturesResponse) {
option (google.api.http) = {
delete: "/v2/features/user/{user_id}"
@@ -354,13 +401,11 @@ service FeatureService {
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "user.feature.write"
permission: "user.feature.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Reset user level features";
description: "Deletes ALL configured features for a user, reverting the behaviors to organization defaults."
responses: {
key: "200"
value: {
@@ -370,6 +415,13 @@ service FeatureService {
};
}
// Get User Features
//
// Returns all configured features for a user. Unset fields mean the feature is the current organization default.
//
// Required permissions:
// - user.feature.read
// - no permission required for the own user
rpc GetUserFeatures(GetUserFeaturesRequest) returns (GetUserFeaturesResponse) {
option (google.api.http) = {
get: "/v2/features/user/{user_id}"
@@ -377,13 +429,11 @@ service FeatureService {
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "user.feature.read"
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Get organization level features";
description: "Returns all configured features for an organization. Unset fields mean the feature is the current instance default."
responses: {
key: "200"
value: {

View File

@@ -25,7 +25,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -0,0 +1,59 @@
syntax = "proto3";
package zitadel.filter.v2beta;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/filter/v2beta;filter";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
enum TextFilterMethod {
TEXT_FILTER_METHOD_EQUALS = 0;
TEXT_FILTER_METHOD_EQUALS_IGNORE_CASE = 1;
TEXT_FILTER_METHOD_STARTS_WITH = 2;
TEXT_FILTER_METHOD_STARTS_WITH_IGNORE_CASE = 3;
TEXT_FILTER_METHOD_CONTAINS = 4;
TEXT_FILTER_METHOD_CONTAINS_IGNORE_CASE = 5;
TEXT_FILTER_METHOD_ENDS_WITH = 6;
TEXT_FILTER_METHOD_ENDS_WITH_IGNORE_CASE = 7;
}
enum ListFilterMethod {
LIST_FILTER_METHOD_IN = 0;
}
enum TimestampFilterMethod {
TIMESTAMP_FILTER_METHOD_EQUALS = 0;
TIMESTAMP_FILTER_METHOD_GREATER = 1;
TIMESTAMP_FILTER_METHOD_GREATER_OR_EQUALS = 2;
TIMESTAMP_FILTER_METHOD_LESS = 3;
TIMESTAMP_FILTER_METHOD_LESS_OR_EQUALS = 4;
}
message PaginationRequest {
// Starting point for retrieval, in combination of offset used to query a set list of objects.
uint64 offset = 1;
// limit is the maximum amount of objects returned. The default is set to 100
// with a maximum of 1000 in the runtime configuration.
// If the limit exceeds the maximum configured ZITADEL will throw an error.
// If no limit is present the default is taken.
uint32 limit = 2;
// Asc is the sorting order. If true the list is sorted ascending, if false
// the list is sorted descending. The default is descending.
bool asc = 3;
}
message PaginationResponse {
// Absolute number of objects matching the query, regardless of applied limit.
uint64 total_result = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"100\"";
}
];
// Applied limit from query, defines maximum amount of objects per request, to compare if all objects are returned.
uint64 applied_limit = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"100\"";
}
];
}

View File

@@ -24,7 +24,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -24,7 +24,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -24,7 +24,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -34,7 +34,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -33,7 +33,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -1,565 +0,0 @@
syntax = "proto3";
package zitadel.resources.action.v3alpha;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/resources/action/v3alpha/target.proto";
import "zitadel/resources/action/v3alpha/execution.proto";
import "zitadel/resources/action/v3alpha/query.proto";
import "zitadel/resources/object/v3alpha/object.proto";
import "zitadel/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Action Service";
version: "3.0-alpha";
description: "This API is intended to manage custom executions (previously known as actions) in a ZITADEL instance. It will continue breaking as long as it is in alpha state.";
contact:{
name: "ZITADEL"
url: "https://zitadel.com"
email: "hi@zitadel.com"
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
};
};
schemes: HTTPS;
schemes: HTTP;
consumes: "application/json";
consumes: "application/grpc";
produces: "application/json";
produces: "application/grpc";
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "$CUSTOM-DOMAIN";
base_path: "/";
external_docs: {
description: "Detailed information about ZITADEL",
url: "https://zitadel.com/docs"
}
security_definitions: {
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
value: "openid";
}
scope: {
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "openid";
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
};
service ZITADELActions {
// Create a target
//
// Create a new target, which can be used in executions.
rpc CreateTarget (CreateTargetRequest) returns (CreateTargetResponse) {
option (google.api.http) = {
post: "/resources/v3alpha/actions/targets"
body: "target"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.write"
}
http_response: {
success_code: 201
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "201";
value: {
description: "Target successfully created";
schema: {
json_schema: {
ref: "#/definitions/v3alphaCreateTargetResponse";
}
}
};
};
};
}
// Patch a target
//
// Patch an existing target.
rpc PatchTarget (PatchTargetRequest) returns (PatchTargetResponse) {
option (google.api.http) = {
patch: "/resources/v3alpha/actions/targets/{id}"
body: "target"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target successfully updated or left unchanged";
};
};
};
}
// Delete a target
//
// Delete an existing target. This will remove it from any configured execution as well.
rpc DeleteTarget (DeleteTargetRequest) returns (DeleteTargetResponse) {
option (google.api.http) = {
delete: "/resources/v3alpha/actions/targets/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target successfully deleted";
};
};
};
}
// Target by ID
//
// Returns the target identified by the requested ID.
rpc GetTarget (GetTargetRequest) returns (GetTargetResponse) {
option (google.api.http) = {
get: "/resources/v3alpha/actions/targets/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "Target successfully retrieved";
}
};
};
}
// Search targets
//
// Search all matching targets. By default all targets of the instance are returned.
// Make sure to include a limit and sorting for pagination.
rpc SearchTargets (SearchTargetsRequest) returns (SearchTargetsResponse) {
option (google.api.http) = {
post: "/resources/v3alpha/actions/targets/_search",
body: "filters"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "A list of all targets matching the query";
};
};
responses: {
key: "400";
value: {
description: "invalid list query";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
};
}
// Sets an execution to call a target or include the targets of another execution.
//
// Setting an empty list of targets will remove all targets from the execution, making it a noop.
rpc SetExecution (SetExecutionRequest) returns (SetExecutionResponse) {
option (google.api.http) = {
put: "/resources/v3alpha/actions/executions"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.execution.write"
}
http_response: {
success_code: 201
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Execution successfully updated or left unchanged";
schema: {
json_schema: {
ref: "#/definitions/v3alphaSetExecutionResponse";
}
}
};
};
};
}
// Search executions
//
// Search all matching executions. By default all executions of the instance are returned that have at least one execution target.
// Make sure to include a limit and sorting for pagination.
rpc SearchExecutions (SearchExecutionsRequest) returns (SearchExecutionsResponse) {
option (google.api.http) = {
post: "/resources/v3alpha/actions/executions/_search"
body: "filters"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.execution.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "A list of all non noop executions matching the query";
};
};
responses: {
key: "400";
value: {
description: "invalid list query";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
};
}
// List all available functions
//
// List all available functions which can be used as condition for executions.
rpc ListExecutionFunctions (ListExecutionFunctionsRequest) returns (ListExecutionFunctionsResponse) {
option (google.api.http) = {
get: "/resources/v3alpha/actions/executions/functions"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all functions successfully";
};
};
};
}
// List all available methods
//
// List all available methods which can be used as condition for executions.
rpc ListExecutionMethods (ListExecutionMethodsRequest) returns (ListExecutionMethodsResponse) {
option (google.api.http) = {
get: "/resources/v3alpha/actions/executions/methods"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all methods successfully";
};
};
};
}
// List all available service
//
// List all available services which can be used as condition for executions.
rpc ListExecutionServices (ListExecutionServicesRequest) returns (ListExecutionServicesResponse) {
option (google.api.http) = {
get: "/resources/v3alpha/actions/executions/services"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all services successfully";
};
};
};
}
}
message CreateTargetRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
Target target = 2 [
(validate.rules).message = {
required: true
}
];
}
message CreateTargetResponse {
zitadel.resources.object.v3alpha.Details details = 1;
// Key used to sign and check payload sent to the target.
string signing_key = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"98KmsU67\""
}
];
}
message PatchTargetRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
string id = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
PatchTarget target = 3 [
(validate.rules).message = {
required: true
}
];
}
message PatchTargetResponse {
zitadel.resources.object.v3alpha.Details details = 1;
// Key used to sign and check payload sent to the target.
optional string signing_key = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"98KmsU67\""
}
];
}
message DeleteTargetRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
string id = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message DeleteTargetResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message GetTargetRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
string id = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message GetTargetResponse {
GetTarget target = 1;
}
message SearchTargetsRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
// list limitations and ordering.
optional zitadel.resources.object.v3alpha.SearchQuery query = 2;
// The field the result is sorted by. The default is the creation date. Beware that if you change this, your result pagination might be inconsistent.
optional TargetFieldName sorting_column = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"TARGET_FIELD_NAME_CREATION_DATE\""
}
];
// Define the criteria to query for.
repeated TargetSearchFilter filters = 4;
}
message SearchTargetsResponse {
zitadel.resources.object.v3alpha.ListDetails details = 1;
repeated GetTarget result = 2;
}
message SetExecutionRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
Condition condition = 2;
Execution execution = 3;
}
message SetExecutionResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message SearchExecutionsRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
// list limitations and ordering.
optional zitadel.resources.object.v3alpha.SearchQuery query = 2;
// The field the result is sorted by. The default is the creation date. Beware that if you change this, your result pagination might be inconsistent.
optional ExecutionFieldName sorting_column = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"EXECUTION_FIELD_NAME_CREATION_DATE\""
}
];
// Define the criteria to query for.
repeated ExecutionSearchFilter filters = 4;
}
message SearchExecutionsResponse {
zitadel.resources.object.v3alpha.ListDetails details = 1;
repeated GetExecution result = 2;
}
message ListExecutionFunctionsRequest{}
message ListExecutionFunctionsResponse{
// All available methods
repeated string functions = 1;
}
message ListExecutionMethodsRequest{}
message ListExecutionMethodsResponse{
// All available methods
repeated string methods = 1;
}
message ListExecutionServicesRequest{}
message ListExecutionServicesResponse{
// All available methods
repeated string services = 1;
}

View File

@@ -1,124 +0,0 @@
syntax = "proto3";
package zitadel.resources.action.v3alpha;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "google/protobuf/timestamp.proto";
import "zitadel/resources/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
message Target {
string name = 1 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\"";
min_length: 1
max_length: 1000
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
option (validate.required) = true;
SetRESTWebhook rest_webhook = 2;
SetRESTCall rest_call = 3;
SetRESTAsync rest_async = 4;
}
// Timeout defines the duration until ZITADEL cancels the execution.
google.protobuf.Duration timeout = 5 [
(validate.rules).duration = {gte: {}, lte: {seconds: 270}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "if the target doesn't respond before this timeout expires, the the connection is closed and the action fails";
example: "\"10s\"";
}
];
string endpoint = 6 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\""
min_length: 1
max_length: 1000
}
];
}
message GetTarget {
zitadel.resources.object.v3alpha.Details details = 1;
Target config = 2;
string signing_key = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"98KmsU67\""
}
];
}
message PatchTarget {
optional string name = 1 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\""
min_length: 1
max_length: 1000
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
SetRESTWebhook rest_webhook = 2;
SetRESTCall rest_call = 3;
SetRESTAsync rest_async = 4;
}
// Timeout defines the duration until ZITADEL cancels the execution.
optional google.protobuf.Duration timeout = 5 [
(validate.rules).duration = {gte: {}, lte: {seconds: 270}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "if the target doesn't respond before this timeout expires, the the connection is closed and the action fails";
example: "\"10s\"";
}
];
optional string endpoint = 6 [
(validate.rules).string = {min_len: 1, max_len: 1000},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\""
min_length: 1
max_length: 1000
}
];
// Regenerate the key used for signing and checking the payload sent to the target.
// Set the graceful period for the existing key. During that time, the previous
// signing key and the new one will be used to sign the request to allow you a smooth
// transition onf your API.
//
// Note that we currently only allow an immediate rotation ("0s") and will support
// longer expirations in the future.
optional google.protobuf.Duration expiration_signing_key = 7 [
(validate.rules).duration = {const: {seconds: 0, nanos: 0}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"0s\""
minimum: 0
maximum: 0
}
];
}
// Wait for response but response body is ignored, status is checked, call is sent as post.
message SetRESTWebhook {
// Define if any error stops the whole execution. By default the process continues as normal.
bool interrupt_on_error = 1;
}
// Wait for response and response body is used, status is checked, call is sent as post.
message SetRESTCall {
// Define if any error stops the whole execution. By default the process continues as normal.
bool interrupt_on_error = 1;
}
// Call is executed in parallel to others, ZITADEL does not wait until the call is finished. The state is ignored, call is sent as post.
message SetRESTAsync {}

View File

@@ -27,7 +27,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -30,7 +30,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -27,7 +27,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -1,41 +0,0 @@
syntax = "proto3";
package zitadel.resources.webkey.v3alpha;
import "validate/validate.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/webkey/v3alpha;webkey";
message WebKeyRSAConfig {
enum RSABits {
RSA_BITS_UNSPECIFIED = 0;
RSA_BITS_2048 = 1;
RSA_BITS_3072 = 2;
RSA_BITS_4096 = 3;
}
enum RSAHasher {
RSA_HASHER_UNSPECIFIED = 0;
RSA_HASHER_SHA256 = 1;
RSA_HASHER_SHA384 = 2;
RSA_HASHER_SHA512 = 3;
}
// bit size of the RSA key
RSABits bits = 1 [(validate.rules).enum = {defined_only: true, not_in: [0]}];
// signing algrithm used
RSAHasher hasher = 2 [(validate.rules).enum = {defined_only: true, not_in: [0]}];
}
message WebKeyECDSAConfig {
enum ECDSACurve {
ECDSA_CURVE_UNSPECIFIED = 0;
ECDSA_CURVE_P256 = 1;
ECDSA_CURVE_P384 = 2;
ECDSA_CURVE_P512 = 3;
}
ECDSACurve curve = 1 [(validate.rules).enum = {defined_only: true, not_in: [0]}];
}
message WebKeyED25519Config {}

View File

@@ -1,31 +0,0 @@
syntax = "proto3";
package zitadel.resources.webkey.v3alpha;
import "google/protobuf/timestamp.proto";
import "zitadel/resources/webkey/v3alpha/config.proto";
import "zitadel/resources/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/webkey/v3alpha;webkey";
enum WebKeyState {
STATE_UNSPECIFIED = 0;
STATE_INITIAL = 1;
STATE_ACTIVE = 2;
STATE_INACTIVE = 3;
STATE_REMOVED = 4;
}
message GetWebKey {
zitadel.resources.object.v3alpha.Details details = 1;
WebKey config = 2;
WebKeyState state = 3;
}
message WebKey {
oneof config {
WebKeyRSAConfig rsa = 6;
WebKeyECDSAConfig ecdsa = 7;
WebKeyED25519Config ed25519 = 8;
}
}

View File

@@ -1,278 +0,0 @@
syntax = "proto3";
package zitadel.resources.webkey.v3alpha;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/resources/webkey/v3alpha/key.proto";
import "zitadel/resources/object/v3alpha/object.proto";
import "zitadel/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/webkey/v3alpha;webkey";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Web key Service";
version: "3.0-preview";
description: "This API is intended to manage web keys for a ZITADEL instance, used to sign and validate OIDC tokens. This project is in preview state. It can AND will continue breaking until a stable version is released.";
contact:{
name: "ZITADEL"
url: "https://zitadel.com"
email: "hi@zitadel.com"
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
};
};
schemes: HTTPS;
schemes: HTTP;
consumes: "application/json";
produces: "application/json";
consumes: "application/grpc";
produces: "application/grpc";
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "$CUSTOM-DOMAIN";
base_path: "/";
external_docs: {
description: "Detailed information about ZITADEL",
url: "https://zitadel.com/docs"
}
security_definitions: {
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
value: "openid";
}
scope: {
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "openid";
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
};
service ZITADELWebKeys {
rpc CreateWebKey(CreateWebKeyRequest) returns (CreateWebKeyResponse) {
option (google.api.http) = {
post: "/resources/v3alpha/web_keys"
body: "key"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.write"
}
http_response: {
success_code: 201
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Generate a web key pair for the instance";
description: "Generate a private and public key pair. The private key can be used to sign OIDC tokens after activation. The public key can be used to valite OIDC tokens."
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
rpc ActivateWebKey(ActivateWebKeyRequest) returns (ActivateWebKeyResponse) {
option (google.api.http) = {
post: "/resources/v3alpha/web_keys/{id}/_activate"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.write"
}
http_response: {
success_code: 200
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Activate a signing key for the instance";
description: "Switch the active signing web key. The previously active key will be deactivated. Note that the JWKs OIDC endpoint returns a cacheable response. Therefore it is not advised to activate a key that has been created within the cache duration (default is 5min), as the public key may not have been propagated to caches and clients yet."
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
rpc DeleteWebKey(DeleteWebKeyRequest) returns (DeleteWebKeyResponse) {
option (google.api.http) = {
delete: "/resources/v3alpha/web_keys/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.delete"
}
http_response: {
success_code: 200
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Delete a web key pair for the instance";
description: "Delete a web key pair. Only inactive keys can be deleted. Once a key is deleted, any tokens signed by this key will be invalid."
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
rpc ListWebKeys(ListWebKeysRequest) returns (ListWebKeysResponse) {
option (google.api.http) = {
get: "/resources/v3alpha/web_keys"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.read"
}
http_response: {
success_code: 200
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "List web key details for the instance";
description: "List web key details for the instance"
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
}
message CreateWebKeyRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
WebKey key = 2;
}
message CreateWebKeyResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message ActivateWebKeyRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
string id = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message ActivateWebKeyResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message DeleteWebKeyRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
string id = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message DeleteWebKeyResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message ListWebKeysRequest {
optional zitadel.object.v3alpha.Instance instance = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "\"domain from HOST or :authority header\""
}
];
}
message ListWebKeysResponse {
repeated GetWebKey web_keys = 1;
}

View File

@@ -24,7 +24,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -28,7 +28,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -28,7 +28,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -30,7 +30,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -30,7 +30,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -30,7 +30,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
tags: [

View File

@@ -32,7 +32,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -32,7 +32,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;

View File

@@ -0,0 +1,109 @@
syntax = "proto3";
package zitadel.webkey.v2beta;
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/webkey/v2beta;webkey";
enum State {
STATE_UNSPECIFIED = 0;
// A newly created key is in the initial state and published to the public key endpoint.
STATE_INITIAL = 1;
// The active key is used to sign tokens. Only one key can be active at a time.
STATE_ACTIVE = 2;
// The inactive key is not used to sign tokens anymore, but still published to the public key endpoint.
STATE_INACTIVE = 3;
// The removed key is not used to sign tokens anymore and not published to the public key endpoint.
STATE_REMOVED = 4;
}
message WebKey {
// The unique identifier of the key.
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629012906488334\"";
}
];
// The timestamp of the key creation.
google.protobuf.Timestamp creation_date = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2024-12-18T07:50:47.492Z\"";
}
];
// The timestamp of the last change to the key (e.g. creation, activation, deactivation).
google.protobuf.Timestamp change_date = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2025-01-23T10:34:18.051Z\"";
}
];
// State of the key
State state = 4;
// Configured type of the key (either RSA, ECDSA or ED25519)
oneof key {
RSA rsa = 5;
ECDSA ecdsa = 6;
ED25519 ed25519 = 7;
}
}
message RSA {
// Bit size of the RSA key. Default is 2048 bits.
RSABits bits = 1 [
(validate.rules).enum = {defined_only: true, not_in: [0]},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "RSA_BITS_2048";
}
];
// Signing algrithm used. Default is SHA256.
RSAHasher hasher = 2 [
(validate.rules).enum = {defined_only: true, not_in: [0]},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "RSA_HASHER_SHA256";
}
];
}
enum RSABits {
RSA_BITS_UNSPECIFIED = 0;
// 2048 bit RSA key
RSA_BITS_2048 = 1;
// 3072 bit RSA key
RSA_BITS_3072 = 2;
// 4096 bit RSA key
RSA_BITS_4096 = 3;
}
enum RSAHasher {
RSA_HASHER_UNSPECIFIED = 0;
// SHA256 hashing algorithm resulting in the RS256 algorithm header
RSA_HASHER_SHA256 = 1;
// SHA384 hashing algorithm resulting in the RS384 algorithm header
RSA_HASHER_SHA384 = 2;
// SHA512 hashing algorithm resulting in the RS512 algorithm header
RSA_HASHER_SHA512 = 3;
}
message ECDSA {
// Curve of the ECDSA key. Default is P-256.
ECDSACurve curve = 1 [
(validate.rules).enum = {defined_only: true, not_in: [0]},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
default: "ECDSA_CURVE_P256";
}
];
}
enum ECDSACurve {
ECDSA_CURVE_UNSPECIFIED = 0;
// NIST P-256 curve resulting in the ES256 algorithm header
ECDSA_CURVE_P256 = 1;
// NIST P-384 curve resulting in the ES384 algorithm header
ECDSA_CURVE_P384 = 2;
// NIST P-512 curve resulting in the ES512 algorithm header
ECDSA_CURVE_P512 = 3;
}
message ED25519 {}

View File

@@ -0,0 +1,359 @@
syntax = "proto3";
package zitadel.webkey.v2beta;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/webkey/v2beta/key.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/webkey/v2beta;webkey";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Web key Service";
version: "2.0-beta";
description: "This API is intended to manage web keys for a ZITADEL instance, used to sign and validate OIDC tokens. This service is in beta state. It can AND will continue breaking until a stable version is released.\n\nThe public key endpoint (outside of this service) is used to retrieve the public keys of the active and inactive keys.\n\nPlease make sure to enable the `web_key` feature flag on your instance to use this service.";
contact:{
name: "ZITADEL"
url: "https://zitadel.com"
email: "hi@zitadel.com"
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSING.md";
};
};
schemes: HTTPS;
schemes: HTTP;
consumes: "application/json";
produces: "application/json";
consumes: "application/grpc";
produces: "application/grpc";
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "$CUSTOM-DOMAIN";
base_path: "/";
external_docs: {
description: "Detailed information about ZITADEL",
url: "https://zitadel.com/docs"
}
security_definitions: {
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
value: "openid";
}
scope: {
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "openid";
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
};
// Service to manage web keys for OIDC token signing and validation.
// The service provides methods to create, activate, delete and list web keys.
// The public key endpoint (outside of this service) is used to retrieve the public keys of the active and inactive keys.
//
// Please make sure to enable the `web_key` feature flag on your instance to use this service.
service WebKeyService {
// Create Web Key
//
// Generate a private and public key pair. The private key can be used to sign OIDC tokens after activation.
// The public key can be used to validate OIDC tokens.
// The newly created key will have the state `STATE_INITIAL` and is published to the public key endpoint.
// Note that the JWKs OIDC endpoint returns a cacheable response.
//
// If no key type is provided, a RSA key pair with 2048 bits and SHA256 hashing will be created.
//
// Required permission:
// - `iam.web_key.write`
//
// Required feature flag:
// - `web_key`
rpc CreateWebKey(CreateWebKeyRequest) returns (CreateWebKeyResponse) {
option (google.api.http) = {
post: "/v2beta/web_keys"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "Web key created successfully.";
}
};
responses: {
key: "400"
value: {
description: "The feature flag `web_key` is not enabled.";
}
};
};
}
// Activate Web Key
//
// Switch the active signing web key. The previously active key will be deactivated.
// Note that the JWKs OIDC endpoint returns a cacheable response.
// Therefore it is not advised to activate a key that has been created within the cache duration (default is 5min),
// as the public key may not have been propagated to caches and clients yet.
//
// Required permission:
// - `iam.web_key.write`
//
// Required feature flag:
// - `web_key`
rpc ActivateWebKey(ActivateWebKeyRequest) returns (ActivateWebKeyResponse) {
option (google.api.http) = {
post: "/v2beta/web_keys/{id}/activate"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "Web key activated successfully.";
}
};
responses: {
key: "400"
value: {
description: "The feature flag `web_key` is not enabled.";
}
};
responses: {
key: "404"
value: {
description: "The web key to active does not exist.";
}
};
};
}
// Delete Web Key
//
// Delete a web key pair. Only inactive keys can be deleted. Once a key is deleted,
// any tokens signed by this key will be invalid.
// Note that the JWKs OIDC endpoint returns a cacheable response.
// In case the web key is not found, the request will return a successful response as
// the desired state is already achieved.
// You can check the change date in the response to verify if the web key was deleted during the request.
//
// Required permission:
// - `iam.web_key.delete`
//
// Required feature flag:
// - `web_key`
rpc DeleteWebKey(DeleteWebKeyRequest) returns (DeleteWebKeyResponse) {
option (google.api.http) = {
delete: "/v2beta/web_keys/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "Web key deleted successfully.";
}
};
responses: {
key: "400"
value: {
description: "The feature flag `web_key` is not enabled or the web key is currently active.";
}
};
};
}
// List Web Keys
//
// List all web keys and their states.
//
// Required permission:
// - `iam.web_key.read`
//
// Required feature flag:
// - `web_key`
rpc ListWebKeys(ListWebKeysRequest) returns (ListWebKeysResponse) {
option (google.api.http) = {
get: "/v2beta/web_keys"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "iam.web_key.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "List of all web keys.";
}
};
responses: {
key: "400"
value: {
description: "The feature flag `web_key` is not enabled.";
}
};
};
}
}
message CreateWebKeyRequest {
// The key type to create (RSA, ECDSA, ED25519).
// If no key type is provided, a RSA key pair with 2048 bits and SHA256 hashing will be created.
oneof key {
// Create a RSA key pair and specify the bit size and hashing algorithm.
// If no bits and hasher are provided, a RSA key pair with 2048 bits and SHA256 hashing will be created.
RSA rsa = 1;
// Create a ECDSA key pair and specify the curve.
// If no curve is provided, a ECDSA key pair with P-256 curve will be created.
ECDSA ecdsa = 2;
// Create a ED25519 key pair.
ED25519 ed25519 = 3;
}
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
example: "{\"rsa\":{\"bits\":\"RSA_BITS_2048\",\"hasher\":\"RSA_HASHER_SHA256\"}}";
};
}
message CreateWebKeyResponse {
// The unique identifier of the newly created key.
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629012906488334\"";
}
];
// The timestamp of the key creation.
google.protobuf.Timestamp creation_date = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2024-12-18T07:50:47.492Z\"";
}
];
}
message ActivateWebKeyRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message ActivateWebKeyResponse {
// The timestamp of the activation of the key.
google.protobuf.Timestamp change_date = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2025-01-23T10:34:18.051Z\"";
}
];
}
message DeleteWebKeyRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message DeleteWebKeyResponse {
// The timestamp of the deletion of the key.
// Note that the deletion date is only guaranteed to be set if the deletion was successful during the request.
// In case the deletion occurred in a previous request, the deletion date might be empty.
google.protobuf.Timestamp deletion_date = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2025-01-23T10:34:18.051Z\"";
}
];
}
message ListWebKeysRequest {}
message ListWebKeysResponse {
repeated WebKey web_keys = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[{\"id\":\"69629012906488334\",\"creationDate\":\"2024-12-18T07:50:47.492Z\",\"changeDate\":\"2024-12-18T08:04:47.492Z\",\"state\":\"STATE_ACTIVE\",\"rsa\":{\"bits\":\"RSA_BITS_2048\",\"hasher\":\"RSA_HASHER_SHA256\"}},{\"id\":\"69629012909346200\",\"creationDate\":\"2025-01-18T12:05:47.492Z\",\"state\":\"STATE_INITIAL\",\"ecdsa\":{\"curve\":\"ECDSA_CURVE_P256\"}}]";
}
];
}