feat: add quotas (#4779)

adds possibilities to cap authenticated requests and execution seconds of actions on a defined intervall
This commit is contained in:
Elio Bischof
2023-02-15 02:52:11 +01:00
committed by GitHub
parent 45f6a4436e
commit 681541f41b
117 changed files with 4652 additions and 510 deletions

43
proto/zitadel/quota.proto Normal file
View File

@@ -0,0 +1,43 @@
syntax = "proto3";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
package zitadel.quota.v1;
option go_package ="github.com/zitadel/zitadel/pkg/grpc/quota";
enum Unit {
UNIT_UNIMPLEMENTED = 0;
/* The sum of all requests to the ZITADEL API with an authorization header,
excluding the following exceptions
- Calls to the System API
- Calls that cause internal server errors
- Failed authorizations
- Requests after the quota already exceeded
*/
UNIT_REQUESTS_ALL_AUTHENTICATED = 1;
// The sum of all actions run durations in seconds
UNIT_ACTIONS_ALL_RUN_SECONDS = 2;
}
message Notification {
// The percentage relative to the quotas amount on which the call_url should be called.
uint32 percent = 1 [
(validate.rules).uint32.gt = 0,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "The percentage relative to the quotas amount on which the call_url should be called.";
}
];
// If true, the call_url is called each time a factor of percentage is reached.
bool repeat = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "If true, the call_url is called each time a factor of percentage is reached.";
}];
// The URL, which is called with HTTP method POST and a JSON payload with the properties "unit", "id" (notification id), "callURL", "periodStart", "threshold" and "usage".
string call_url = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "The URL, which is called with HTTP method POST and a JSON payload with the properties \"unit\", \"id\" (notification id), \"callURL\", \"periodStart\", \"threshold\" and \"usage\".";
}
];
}

View File

@@ -4,10 +4,12 @@ import "zitadel/object.proto";
import "zitadel/options.proto";
import "zitadel/instance.proto";
import "zitadel/member.proto";
import "zitadel/quota.proto";
import "zitadel/auth_n_key.proto";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
@@ -162,7 +164,7 @@ service SystemService {
};
}
// Removes a instances
// Removes an instance
// This might take some time
rpc RemoveInstance(RemoveInstanceRequest) returns (RemoveInstanceResponse) {
option (google.api.http) = {
@@ -353,6 +355,29 @@ service SystemService {
};
};
}
// Creates a new quota
rpc AddQuota(AddQuotaRequest) returns (AddQuotaResponse) {
option (google.api.http) = {
post: "/instances/{instance_id}/quotas"
body: "*"
};
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
}
// Removes a quota
rpc RemoveQuota(RemoveQuotaRequest) returns (RemoveQuotaResponse) {
option (google.api.http) = {
delete: "/instances/{instance_id}/quotas/{unit}"
};
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
}
}
@@ -520,10 +545,62 @@ message GetUsageRequest {
string instance_id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
}
message GetUsageResponse {
message AddQuotaRequest {
string instance_id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
// the unit a quota should be imposed on
zitadel.quota.v1.Unit unit = 2 [
(validate.rules).enum = {defined_only: true, not_in: [0]},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "the unit a quota should be imposed on";
}
];
// the starting time from which the current quota period is calculated from. This is relevant for querying the current usage.
google.protobuf.Timestamp from = 3 [
(validate.rules).timestamp.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2019-04-01T08:45:00.000000Z\"";
description: "the starting time from which the current quota period is calculated from. This is relevant for querying the current usage.";
}
];
// the quota periods duration
google.protobuf.Duration reset_interval = 4 [
(validate.rules).duration.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "the quota periods duration";
}
];
// the quota amount of units
uint64 amount = 5 [
(validate.rules).uint64.gt = 0,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "the quota amount of units";
}
];
// whether ZITADEL should block further usage when the configured amount is used
bool limit = 6 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "whether ZITADEL should block further usage when the configured amount is used";
}
];
// the handlers, ZITADEL executes when certain quota percentages are reached
repeated zitadel.quota.v1.Notification notifications = 7 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "the handlers, ZITADEL executes when certain quota percentages are reached";
}
];
}
message AddQuotaResponse {
zitadel.v1.ObjectDetails details = 1;
}
message RemoveQuotaRequest {
string instance_id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
zitadel.quota.v1.Unit unit = 2;
}
message RemoveQuotaResponse {
zitadel.v1.ObjectDetails details = 1;
uint64 executed_requests = 2;
uint64 executed_action_mins = 3;
}
message ExistsDomainRequest {