mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 14:47:33 +00:00
feat: exchange gRPC server implementation to connectRPC (#10145)
# Which Problems Are Solved The current maintained gRPC server in combination with a REST (grpc) gateway is getting harder and harder to maintain. Additionally, there have been and still are issues with supporting / displaying `oneOf`s correctly. We therefore decided to exchange the server implementation to connectRPC, which apart from supporting connect as protocol, also also "standard" gRCP clients as well as HTTP/1.1 / rest like clients, e.g. curl directly call the server without any additional gateway. # How the Problems Are Solved - All v2 services are moved to connectRPC implementation. (v1 services are still served as pure grpc servers) - All gRPC server interceptors were migrated / copied to a corresponding connectRPC interceptor. - API.ListGrpcServices and API. ListGrpcMethods were changed to include the connect services and endpoints. - gRPC server reflection was changed to a `StaticReflector` using the `ListGrpcServices` list. - The `grpc.Server` interfaces was split into different combinations to be able to handle the different cases (grpc server and prefixed gateway, connect server with grpc gateway, connect server only, ...) - Docs of services serving connectRPC only with no additional gateway (instance, webkey, project, app, org v2 beta) are changed to expose that - since the plugin is not yet available on buf, we download it using `postinstall` hook of the docs # Additional Changes - WebKey service is added as v2 service (in addition to the current v2beta) # Additional Context closes #9483 --------- Co-authored-by: Elio Bischof <elio@zitadel.com>
This commit is contained in:
@@ -118,7 +118,7 @@ service SystemService {
|
||||
|
||||
// Returns a list of ZITADEL instances
|
||||
//
|
||||
// Deprecated: Use [ListInstances](apis/resources/instance_service_v2/instance-service-list-instances.api.mdx) instead to list instances
|
||||
// Deprecated: Use [ListInstances](apis/resources/instance_service_v2/zitadel-instance-v-2-beta-instance-service-list-instances.api.mdx) instead to list instances
|
||||
rpc ListInstances(ListInstancesRequest) returns (ListInstancesResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/instances/_search"
|
||||
@@ -136,7 +136,7 @@ service SystemService {
|
||||
|
||||
// Returns the detail of an instance
|
||||
//
|
||||
// Deprecated: Use [GetInstance](apis/resources/instance_service_v2/instance-service-get-instance.api.mdx) instead to get the details of the instance in context
|
||||
// Deprecated: Use [GetInstance](apis/resources/instance_service_v2/zitadel-instance-v-2-beta-instance-service-get-instance.api.mdx) instead to get the details of the instance in context
|
||||
rpc GetInstance(GetInstanceRequest) returns (GetInstanceResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/instances/{instance_id}";
|
||||
@@ -171,7 +171,7 @@ service SystemService {
|
||||
|
||||
// Updates name of an existing instance
|
||||
//
|
||||
// Deprecated: Use [UpdateInstance](apis/resources/instance_service_v2/instance-service-update-instance.api.mdx) instead to update the name of the instance in context
|
||||
// Deprecated: Use [UpdateInstance](apis/resources/instance_service_v2/zitadel-instance-v-2-beta-instance-service-update-instance.api.mdx) instead to update the name of the instance in context
|
||||
rpc UpdateInstance(UpdateInstanceRequest) returns (UpdateInstanceResponse) {
|
||||
option (google.api.http) = {
|
||||
put: "/instances/{instance_id}"
|
||||
@@ -203,7 +203,7 @@ service SystemService {
|
||||
// Removes an instance
|
||||
// This might take some time
|
||||
//
|
||||
// Deprecated: Use [DeleteInstance](apis/resources/instance_service_v2/instance-service-delete-instance.api.mdx) instead to delete an instance
|
||||
// Deprecated: Use [DeleteInstance](apis/resources/instance_service_v2/zitadel-instance-v-2-beta-instance-service-delete-instance.api.mdx) instead to delete an instance
|
||||
rpc RemoveInstance(RemoveInstanceRequest) returns (RemoveInstanceResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/instances/{instance_id}"
|
||||
@@ -234,7 +234,7 @@ service SystemService {
|
||||
|
||||
// Checks if a domain exists
|
||||
//
|
||||
// Deprecated: Use [ListCustomDomains](apis/resources/instance_service_v2/instance-service-list-custom-domains.api.mdx) instead to check existence of an instance
|
||||
// Deprecated: Use [ListCustomDomains](apis/resources/instance_service_v2/zitadel-instance-v-2-beta-instance-service-list-custom-domains.api.mdx) instead to check existence of an instance
|
||||
rpc ExistsDomain(ExistsDomainRequest) returns (ExistsDomainResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/domains/{domain}/_exists";
|
||||
@@ -270,7 +270,7 @@ service SystemService {
|
||||
|
||||
// Adds a domain to an instance
|
||||
//
|
||||
// Deprecated: Use [AddCustomDomain](apis/resources/instance_service_v2/instance-service-add-custom-domain.api.mdx) instead to add a custom domain to the instance in context
|
||||
// Deprecated: Use [AddCustomDomain](apis/resources/instance_service_v2/zitadel-instance-v-2-beta-instance-service-add-custom-domain.api.mdx) instead to add a custom domain to the instance in context
|
||||
rpc AddDomain(AddDomainRequest) returns (AddDomainResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/instances/{instance_id}/domains";
|
||||
@@ -288,7 +288,7 @@ service SystemService {
|
||||
|
||||
// Removes the domain of an instance
|
||||
//
|
||||
// Deprecated: Use [RemoveDomain](apis/resources/instance_service_v2/instance-service-remove-custom-domain.api.mdx) instead to remove a custom domain from the instance in context
|
||||
// Deprecated: Use [RemoveDomain](apis/resources/instance_service_v2/zitadel-instance-v-2-beta-instance-service-remove-custom-domain.api.mdx) instead to remove a custom domain from the instance in context
|
||||
rpc RemoveDomain(RemoveDomainRequest) returns (RemoveDomainResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/instances/{instance_id}/domains/{domain}";
|
||||
|
109
proto/zitadel/webkey/v2/key.proto
Normal file
109
proto/zitadel/webkey/v2/key.proto
Normal file
@@ -0,0 +1,109 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.webkey.v2;
|
||||
|
||||
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/v2;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 {}
|
335
proto/zitadel/webkey/v2/webkey_service.proto
Normal file
335
proto/zitadel/webkey/v2/webkey_service.proto
Normal file
@@ -0,0 +1,335 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.webkey.v2;
|
||||
|
||||
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/v2/key.proto";
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/webkey/v2;webkey";
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Web Key Service";
|
||||
version: "2.0";
|
||||
description: "This API is intended to manage web keys for a ZITADEL instance, used to sign and validate OIDC tokens.\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 (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "iam.web_key.write"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 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 (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: "/v2/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: "/v2/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\"}}]";
|
||||
}
|
||||
];
|
||||
}
|
Reference in New Issue
Block a user