diff options
author | alexv-smirnov <alex@ydb.tech> | 2022-10-19 20:15:00 +0300 |
---|---|---|
committer | alexv-smirnov <alex@ydb.tech> | 2022-10-19 20:15:00 +0300 |
commit | c5533b2142bf51a05a75c9b22b0e899b93520829 (patch) | |
tree | 7c08a3ec17b2b0d9eb444bb518d3b4dea4f38636 | |
parent | 33ffd2163c280a9bcc0e7a9e67088b3ac5f6295b (diff) | |
download | ydb-c5533b2142bf51a05a75c9b22b0e899b93520829.tar.gz |
PR from branch users/alexv-smirnov/fix/-move-public-yc-protos-2
1. Протоспеки внешнего публичного API YC размещены в ydb/public/api/client/yc_public.
2. Альтернативный внутренний вариант IAM public (kikimr/public/sdk/cpp/client/iam) удален, зависимости перенаправлены на ydb/public/sdk/cpp/client/iam
3. kikimr/public/sdk/cpp/client/iam_private разделена на две части:
a) iam_private теперь содержит только зависимость на yc private api, в имя методов добавлено Private. Те зависимые приложения, где использование private api задавалось константой true, рефакторены, и теперь у них нет в зависимостях yc public iam proto
b) iam_both содержит зависимости как на private, так и на public yc api, и содержит методы с флагом usePrivateApi для выбора какое вызывать (как было раньше в iam_private)
4. Из kikimr/persqueue/sdk/deprecated/cpp/v2 убрана наружу зависимость на yc iam, явно включена в те проекты где он используется
22 files changed, 1144 insertions, 335 deletions
diff --git a/ydb/public/api/CMakeLists.txt b/ydb/public/api/CMakeLists.txt index bd2e57c6b5..2b33828c9b 100644 --- a/ydb/public/api/CMakeLists.txt +++ b/ydb/public/api/CMakeLists.txt @@ -6,5 +6,6 @@ # original buildsystem will not be accepted. +add_subdirectory(client) add_subdirectory(grpc) add_subdirectory(protos) diff --git a/ydb/public/sdk/cpp/client/iam/proto/CMakeLists.txt b/ydb/public/api/client/CMakeLists.txt index 0293e4453a..8aae0f5e9d 100644 --- a/ydb/public/sdk/cpp/client/iam/proto/CMakeLists.txt +++ b/ydb/public/api/client/CMakeLists.txt @@ -6,4 +6,4 @@ # original buildsystem will not be accepted. -add_subdirectory(v1) +add_subdirectory(yc_public) diff --git a/ydb/public/api/client/yc_public/CMakeLists.txt b/ydb/public/api/client/yc_public/CMakeLists.txt new file mode 100644 index 0000000000..08fdd2ac50 --- /dev/null +++ b/ydb/public/api/client/yc_public/CMakeLists.txt @@ -0,0 +1,12 @@ + +# This file was gererated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + +add_subdirectory(common) +add_subdirectory(events) +add_subdirectory(iam) +add_subdirectory(logging) diff --git a/ydb/public/sdk/cpp/client/iam/proto/v1/CMakeLists.txt b/ydb/public/api/client/yc_public/common/CMakeLists.txt index c12215d066..80619e0736 100644 --- a/ydb/public/sdk/cpp/client/iam/proto/v1/CMakeLists.txt +++ b/ydb/public/api/client/yc_public/common/CMakeLists.txt @@ -7,22 +7,21 @@ -add_library(iam-proto-v1) -set_property(TARGET iam-proto-v1 PROPERTY +add_library(client-yc_public-common) +set_property(TARGET client-yc_public-common PROPERTY PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h ) -target_link_libraries(iam-proto-v1 PUBLIC +target_link_libraries(client-yc_public-common PUBLIC contrib-libs-cxxsupp yutil contrib-libs-grpc contrib-libs-googleapis-common-protos contrib-libs-protobuf ) -target_proto_messages(iam-proto-v1 PRIVATE - ${CMAKE_SOURCE_DIR}/ydb/public/sdk/cpp/client/iam/proto/v1/iam_token_service.proto - ${CMAKE_SOURCE_DIR}/ydb/public/sdk/cpp/client/iam/proto/v1/validation.proto +target_proto_messages(client-yc_public-common PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/common/validation.proto ) -target_proto_addincls(iam-proto-v1 +target_proto_addincls(client-yc_public-common ./ ${CMAKE_SOURCE_DIR}/ ${CMAKE_BINARY_DIR} @@ -32,11 +31,11 @@ target_proto_addincls(iam-proto-v1 ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src ) -target_proto_outs(iam-proto-v1 +target_proto_outs(client-yc_public-common --cpp_out=${CMAKE_BINARY_DIR}/ --cpp_styleguide_out=${CMAKE_BINARY_DIR}/ ) -target_proto_plugin(iam-proto-v1 +target_proto_plugin(client-yc_public-common grpc_cpp grpc_cpp ) diff --git a/ydb/public/sdk/cpp/client/iam/proto/v1/validation.proto b/ydb/public/api/client/yc_public/common/validation.proto index ae8e6402c2..ae8e6402c2 100644 --- a/ydb/public/sdk/cpp/client/iam/proto/v1/validation.proto +++ b/ydb/public/api/client/yc_public/common/validation.proto diff --git a/ydb/public/api/client/yc_public/events/CMakeLists.txt b/ydb/public/api/client/yc_public/events/CMakeLists.txt new file mode 100644 index 0000000000..8a85f9e72a --- /dev/null +++ b/ydb/public/api/client/yc_public/events/CMakeLists.txt @@ -0,0 +1,44 @@ + +# This file was gererated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_library(client-yc_public-events) +set_property(TARGET client-yc_public-events PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +target_link_libraries(client-yc_public-events PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + client-yc_public-common + contrib-libs-protobuf +) +target_proto_messages(client-yc_public-events PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/events/options.proto + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/events/common.proto + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/events/yq.proto +) +target_proto_addincls(client-yc_public-events + ./ + ${CMAKE_SOURCE_DIR}/ + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/googleapis-common-protos + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src +) +target_proto_outs(client-yc_public-events + --cpp_out=${CMAKE_BINARY_DIR}/ + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/ +) +target_proto_plugin(client-yc_public-events + grpc_cpp + grpc_cpp +) diff --git a/ydb/public/api/client/yc_public/events/common.proto b/ydb/public/api/client/yc_public/events/common.proto new file mode 100644 index 0000000000..dbb31e8aad --- /dev/null +++ b/ydb/public/api/client/yc_public/events/common.proto @@ -0,0 +1,95 @@ +syntax = "proto3"; + +package yandex.cloud.events; + +import "google/protobuf/timestamp.proto"; +import "ydb/public/api/client/yc_public/common/validation.proto"; +import "ydb/public/api/client/yc_public/events/options.proto"; + +option go_package = "a.yandex-team.ru/cloud/bitbucket/public-api/yandex/cloud/events;events"; +option java_package = "yandex.cloud.api.events"; +option java_outer_classname = "CommonEvents"; + +message EventMetadata { + // Global unique identifier of current event. + // Should be treated as opaque string. + // Could be used for deduplication. + string event_id = 1 [(required) = true]; + + // Well-known event type in form of fully qualified protobuf + // message name (eg: yandex.cloud.events.compute.CreateInstance). + string event_type = 2 [(required) = true]; + + // Wall time of event as seen on producing system. + google.protobuf.Timestamp created_at = 3 [(required) = true]; + + // Additional information about trace tree. + TracingContext tracing_context = 4 [(hide) = true]; + + string cloud_id = 5 [(required) = true]; + + string folder_id = 6; +} + +message TracingContext { + // The ID of the trace. Every span in a trace shares this ID. + string trace_id = 1; + + // Indicates the position of the current operation in the trace tree. + string span_id = 2; + + // Optional reference to the cause of current event. + // Absent value means that this is root cause of whole trace. + string parent_span_id = 3; +} + +message Authentication { + enum SubjectType { + SUBJECT_TYPE_UNSPECIFIED = 0; + YANDEX_PASSPORT_USER_ACCOUNT = 1; + SERVICE_ACCOUNT = 2; + FEDERATED_USER_ACCOUNT = 3; + } + + bool authenticated = 1; + SubjectType subject_type = 2; + string subject_id = 3; +} + +message Authorization { + bool authorized = 1; + + repeated RequestedPermissions permissions = 2 [(hide) = true]; +} + +message RequestedPermissions { + // <service>.<resource>.<action> + string permission = 1 [(required) = true]; + + // <service>.<resource> + string resource_type = 2 [(required) = true]; + + string resource_id = 3 [(required) = true]; + + // is request for permission authorized + bool authorized = 4; +} + +message RequestMetadata { + string remote_address = 1 [(required) = true]; + string user_agent = 2 [(required) = true]; + string request_id = 3 [(required) = true]; + string idempotency_id = 4 [(hide) = true]; +} + +enum EventStatus { + EVENT_STATUS_UNSPECIFIED = 0; + STARTED = 1; + ERROR = 2; + DONE = 3; + CANCELLED = 4; +} + +message Response { + string operation_id = 1 [(required) = true]; +} diff --git a/ydb/public/api/client/yc_public/events/options.proto b/ydb/public/api/client/yc_public/events/options.proto new file mode 100644 index 0000000000..17e67d5df2 --- /dev/null +++ b/ydb/public/api/client/yc_public/events/options.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package yandex.cloud.events; + +import "google/protobuf/descriptor.proto"; + +option go_package = "a.yandex-team.ru/cloud/bitbucket/public-api/yandex/cloud/events;events"; +option java_package = "yandex.cloud.api.events"; + +extend google.protobuf.FieldOptions { + bool hide = 100700; +} + +extend google.protobuf.MessageOptions { + bool include = 100800; +} diff --git a/ydb/public/api/client/yc_public/events/yq.proto b/ydb/public/api/client/yc_public/events/yq.proto new file mode 100644 index 0000000000..deea6d237a --- /dev/null +++ b/ydb/public/api/client/yc_public/events/yq.proto @@ -0,0 +1,338 @@ +syntax = "proto3"; + +package yandex.cloud.events.yq; + +import "google/rpc/status.proto"; +import "ydb/public/api/client/yc_public/events/common.proto"; +import "ydb/public/api/client/yc_public/events/options.proto"; +import "ydb/public/api/client/yc_public/common/validation.proto"; + +option go_package = "a.yandex-team.ru/cloud/bitbucket/public-api/yandex/cloud/events/yq;yq"; +option java_package = "yandex.cloud.api.events.yq"; + +// Query +// Query is the text of an SQL request, the results of the last run and the state after the last run (partitions offsets, consumer in YDS) +// Create a query object with a given SQL +message CreateQuery { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string query_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + string execute_mode = 5; + string compute_status = 6; + int64 text_length = 7; + } + + message RequestParameters { + string name = 1; + string visibility = 2; + string type = 3; + string execute_mode = 4; + int64 text_length = 5; + } +} + +// Change the attributes of the query (acl, name, ...) +message UpdateQuery { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string query_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + string execute_mode = 5; + string compute_status = 6; + int64 text_length = 7; + } + + message RequestParameters { + string query_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + string execute_mode = 5; + reserved 6; + string state_load_mode = 8; + int64 text_length = 7; + } +} + +// Completely delete the query +message DeleteQuery { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string query_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + string execute_mode = 5; + string compute_status = 6; + int64 text_length = 7; + } + + message RequestParameters { + string query_id = 1; + } +} + +// Change the state of the query lifecycle +message ControlQuery { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string query_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + string execute_mode = 5; + string compute_status = 6; + int64 text_length = 7; + } + + message RequestParameters { + string query_id = 1; + string action = 2; + } +} + + +// Connection +// Connection - entity that describes connection points. This can be imagined as an analogue of a network address. +// Create a connection object (ObjectStorage, YDB, YDS, ...) +message CreateConnection { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string connection_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + } + + message RequestParameters { + string name = 1; + string visibility = 2; + string type = 3; + } +} + +// Change the attributes of the connection +message UpdateConnection { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string connection_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + } + + message RequestParameters { + string connection_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + } +} + +// Completely delete the connection +message DeleteConnection { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string connection_id = 1; + string name = 2; + string visibility = 3; + string type = 4; + } + + message RequestParameters { + string connection_id = 1; + } +} + + +// Binding +// Binding - entity using which a schema is assigned to non-schematic data +// Create a binding object - bind schema with ObjectStorage object or YDS stream +message CreateBinding { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string binding_id = 1; + string name = 2; + string visibility = 3; + string connection_id = 4; + string type = 5; + } + + message RequestParameters { + string name = 1; + string visibility = 2; + string connection_id = 3; + string type = 4; + } +} + +// Change the attributes of the binding +message UpdateBinding { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string binding_id = 1; + string name = 2; + string visibility = 3; + string connection_id = 4; + string type = 5; + } + + message RequestParameters { + string binding_id = 1; + string name = 2; + string visibility = 3; + string connection_id = 4; + string type = 5; + } +} + +// Completely delete the binding +message DeleteBinding { + option (include) = true; + + Authentication authentication = 1 [(required) = true]; + Authorization authorization = 2 [(required) = true]; + + EventMetadata event_metadata = 3 [(required) = true]; + RequestMetadata request_metadata = 4 [(required) = true]; + + EventStatus event_status = 5 [(required) = true]; + EventDetails details = 6 [(required) = true]; + RequestParameters request_parameters = 7 [(required) = true]; + google.rpc.Status error = 8; + Response response = 9 [(required) = true]; + + message EventDetails { + string binding_id = 1; + string name = 2; + string visibility = 3; + string connection_id = 4; + string type = 5; + } + + message RequestParameters { + string binding_id = 1; + } +} diff --git a/ydb/public/api/client/yc_public/iam/CMakeLists.txt b/ydb/public/api/client/yc_public/iam/CMakeLists.txt new file mode 100644 index 0000000000..4771591364 --- /dev/null +++ b/ydb/public/api/client/yc_public/iam/CMakeLists.txt @@ -0,0 +1,42 @@ + +# This file was gererated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_library(client-yc_public-iam) +set_property(TARGET client-yc_public-iam PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +target_link_libraries(client-yc_public-iam PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + client-yc_public-common + contrib-libs-protobuf +) +target_proto_messages(client-yc_public-iam PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/iam/iam_token_service.proto +) +target_proto_addincls(client-yc_public-iam + ./ + ${CMAKE_SOURCE_DIR}/ + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/googleapis-common-protos + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src +) +target_proto_outs(client-yc_public-iam + --cpp_out=${CMAKE_BINARY_DIR}/ + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/ +) +target_proto_plugin(client-yc_public-iam + grpc_cpp + grpc_cpp +) diff --git a/ydb/public/sdk/cpp/client/iam/proto/v1/iam_token_service.proto b/ydb/public/api/client/yc_public/iam/iam_token_service.proto index 67ffcd6542..96c382617b 100644 --- a/ydb/public/sdk/cpp/client/iam/proto/v1/iam_token_service.proto +++ b/ydb/public/api/client/yc_public/iam/iam_token_service.proto @@ -4,7 +4,7 @@ package yandex.cloud.iam.v1; import "google/api/annotations.proto"; import "google/protobuf/timestamp.proto"; -import "ydb/public/sdk/cpp/client/iam/proto/v1/validation.proto"; +import "ydb/public/api/client/yc_public/common/validation.proto"; option go_package = "github.com/yandex-cloud/go-genproto/yandex/cloud/iam/v1;iam"; option java_package = "yandex.cloud.api.iam.v1"; diff --git a/ydb/public/api/client/yc_public/logging/CMakeLists.txt b/ydb/public/api/client/yc_public/logging/CMakeLists.txt new file mode 100644 index 0000000000..fdad3bf8d0 --- /dev/null +++ b/ydb/public/api/client/yc_public/logging/CMakeLists.txt @@ -0,0 +1,44 @@ + +# This file was gererated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_library(client-yc_public-logging) +set_property(TARGET client-yc_public-logging PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +target_link_libraries(client-yc_public-logging PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + client-yc_public-common + contrib-libs-protobuf +) +target_proto_messages(client-yc_public-logging PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/logging/log_entry.proto + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/logging/log_ingestion_service.proto + ${CMAKE_SOURCE_DIR}/ydb/public/api/client/yc_public/logging/log_resource.proto +) +target_proto_addincls(client-yc_public-logging + ./ + ${CMAKE_SOURCE_DIR}/ + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/googleapis-common-protos + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src +) +target_proto_outs(client-yc_public-logging + --cpp_out=${CMAKE_BINARY_DIR}/ + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/ +) +target_proto_plugin(client-yc_public-logging + grpc_cpp + grpc_cpp +) diff --git a/ydb/public/api/client/yc_public/logging/log_entry.proto b/ydb/public/api/client/yc_public/logging/log_entry.proto new file mode 100644 index 0000000000..58b1aa4ac9 --- /dev/null +++ b/ydb/public/api/client/yc_public/logging/log_entry.proto @@ -0,0 +1,142 @@ +syntax = "proto3"; + +package yandex.cloud.logging.v1; + +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "ydb/public/api/client/yc_public/logging/log_resource.proto"; +import "ydb/public/api/client/yc_public/common/validation.proto"; + +option go_package = "a.yandex-team.ru/cloud/bitbucket/public-api/yandex/cloud/logging/v1;logging"; +option java_package = "yandex.cloud.api.logging.v1"; + +message LogEntry { + // Unique entry ID. + // + // Useful for logs deduplication. + string uid = 1; + + // Entry resource specification. + // + // May contain information about source service and resource ID. + // Also may be provided by the user. + LogEntryResource resource = 2; + + // Timestamp of the entry. + google.protobuf.Timestamp timestamp = 3; + + // Entry ingestion time observed by [LogIngestionService]. + google.protobuf.Timestamp ingested_at = 4; + + // Entry save time. + // + // Entry is ready to be read since this moment. + google.protobuf.Timestamp saved_at = 5; + + // Entry severity. + // + // See [LogLevel.Level] for details. + LogLevel.Level level = 6; + + // Entry text message. + string message = 7; + + // Entry annotation. + google.protobuf.Struct json_payload = 8; + + // Entry stream name. + string stream_name = 9 [(pattern) = "|[a-zA-Z][-a-zA-Z0-9_.]{0,63}"]; +} + +message IncomingLogEntry { + // Timestamp of the entry. + google.protobuf.Timestamp timestamp = 1 [(required) = true]; + + // Entry severity. + // + // See [LogLevel.Level] for details. + LogLevel.Level level = 2; + + // Entry text message. + string message = 3 [(bytes) = "<=65536"]; + + // Entry annotation. + google.protobuf.Struct json_payload = 4 [(bytes) = "<=65536"]; + + // Entry stream name. + string stream_name = 5 [(pattern) = "|[a-zA-Z][-a-zA-Z0-9_.]{0,63}"]; +} + +message LogEntryDefaults { + // Default entry severity. + // Will be applied if entry level is unspecified. + // + // See [LogLevel.Level] for details. + LogLevel.Level level = 2; + + // Default entry annotation. + // Will be merged with entry annotation. + // Any conflict will be resolved in favor of entry own annotation. + google.protobuf.Struct json_payload = 4 [(bytes) = "<=65536"]; + + // Entry stream name. + string stream_name = 5 [(pattern) = "|[a-zA-Z][-a-zA-Z0-9_.]{0,63}"]; +} + +message Destination { + // Entry destination. + oneof destination { + option (exactly_one) = true; + + // Entry should be written to log group resolved by ID. + string log_group_id = 1 [(pattern) = "([a-zA-Z][-a-zA-Z0-9_.]{0,63})?"]; + + // Entry should be written to default log group for the folder. + string folder_id = 2 [(pattern) = "([a-zA-Z][-a-zA-Z0-9_.]{0,63})?"]; + } +} + +message LogLevel { + // Possible log levels for entries. + enum Level { + // Default log level. + // + // Equivalent to not specifying log level at all. + LEVEL_UNSPECIFIED = 0; + + // Trace log level. + // + // Possible use case: verbose logging of some business logic. + TRACE = 1; + + // Debug log level. + // + // Possible use case: debugging special cases in application logic. + DEBUG = 2; + + // Info log level. + // + // Mostly used for information messages. + INFO = 3; + + // Warn log level. + // + // May be used to alert about significant events. + WARN = 4; + + // Error log level. + // + // May be used to alert about errors in infrastructure, logic, etc. + ERROR = 5; + + // Fatal log level. + // + // May be used to alert about unrecoverable failures and events. + FATAL = 6; + } + + // Entry level. + // + // See [Level] for possible values. + Level level = 1; +} diff --git a/ydb/public/api/client/yc_public/logging/log_ingestion_service.proto b/ydb/public/api/client/yc_public/logging/log_ingestion_service.proto new file mode 100644 index 0000000000..30b490fb21 --- /dev/null +++ b/ydb/public/api/client/yc_public/logging/log_ingestion_service.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; + +package yandex.cloud.logging.v1; + +import "google/rpc/status.proto"; +import "ydb/public/api/client/yc_public/logging/log_entry.proto"; +import "ydb/public/api/client/yc_public/logging/log_resource.proto"; +import "ydb/public/api/client/yc_public/common/validation.proto"; + + +option go_package = "a.yandex-team.ru/cloud/bitbucket/public-api/yandex/cloud/logging/v1;logging"; +option java_package = "yandex.cloud.api.logging.v1"; + +// A set of methods for writing to log groups. To make a request use `ingester.logging.yandexcloud.net`. +service LogIngestionService { + // Write log entries to specified destination. + rpc Write (WriteRequest) returns (WriteResponse); +} + +message WriteRequest { + // Log entries destination. + // + // See [Destination] for details. + Destination destination = 1 [(required) = true]; + + // Common resource (type, ID) specification for log entries. + LogEntryResource resource = 2; + + // List of log entries. + repeated IncomingLogEntry entries = 3 [(size) = "1-100"]; + + // Log entries defaults. + // + // See [LogEntryDefaults] for details. + LogEntryDefaults defaults = 4; +} + +message WriteResponse { + // Map<idx, status> of ingest failures. + // + // If entry with idx N is absent, it was ingested successfully. + map<int64, google.rpc.Status> errors = 1; +} diff --git a/ydb/public/api/client/yc_public/logging/log_resource.proto b/ydb/public/api/client/yc_public/logging/log_resource.proto new file mode 100644 index 0000000000..cb7196d8ad --- /dev/null +++ b/ydb/public/api/client/yc_public/logging/log_resource.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package yandex.cloud.logging.v1; + +import "ydb/public/api/client/yc_public/common/validation.proto"; + +option go_package = "a.yandex-team.ru/cloud/bitbucket/public-api/yandex/cloud/logging/v1;logging"; +option java_package = "yandex.cloud.api.logging.v1"; + +// Log entry resource specification. +// +// May be used either by services and by user. +message LogEntryResource { + // Resource type, i.e., `serverless.function` + string type = 1 [(pattern) = "([a-zA-Z][-a-zA-Z0-9_.]{0,63})?"]; + + // Resource ID, i.e., ID of the function producing logs. + string id = 2 [(pattern) = "([a-zA-Z0-9][-a-zA-Z0-9_.]{0,63})?"]; +} + +// Log group resource. +message LogGroupResource { + // Resource type. + // + // Collected from log entries inside log group. + string type = 1; + + // List of resource IDs with the same resource type. + repeated string ids = 2; +} diff --git a/ydb/public/sdk/cpp/client/iam/CMakeLists.txt b/ydb/public/sdk/cpp/client/iam/CMakeLists.txt index 6f1758e5bf..ce20d4fa57 100644 --- a/ydb/public/sdk/cpp/client/iam/CMakeLists.txt +++ b/ydb/public/sdk/cpp/client/iam/CMakeLists.txt @@ -8,13 +8,12 @@ add_subdirectory(common) add_subdirectory(impl) -add_subdirectory(proto) add_library(cpp-client-iam) target_link_libraries(cpp-client-iam PUBLIC contrib-libs-cxxsupp yutil - iam-proto-v1 + client-yc_public-iam client-iam-impl client-iam-common ) diff --git a/ydb/public/sdk/cpp/client/iam/common/CMakeLists.txt b/ydb/public/sdk/cpp/client/iam/common/CMakeLists.txt index 5b2c68f344..82884daaf9 100644 --- a/ydb/public/sdk/cpp/client/iam/common/CMakeLists.txt +++ b/ydb/public/sdk/cpp/client/iam/common/CMakeLists.txt @@ -7,8 +7,17 @@ -add_library(client-iam-common INTERFACE) -target_link_libraries(client-iam-common INTERFACE +add_library(client-iam-common) +target_link_libraries(client-iam-common PUBLIC contrib-libs-cxxsupp yutil + cpp-grpc-client + cpp-http-simple + library-cpp-json + cpp-threading-atomic + public-lib-jwt + client-ydb_types-credentials +) +target_sources(client-iam-common PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/public/sdk/cpp/client/iam/common/iam.cpp ) diff --git a/ydb/public/sdk/cpp/client/iam/common/iam.cpp b/ydb/public/sdk/cpp/client/iam/common/iam.cpp new file mode 100644 index 0000000000..de10cad605 --- /dev/null +++ b/ydb/public/sdk/cpp/client/iam/common/iam.cpp @@ -0,0 +1,86 @@ +#include <ydb/public/sdk/cpp/client/iam/common/iam.h> + +#include <library/cpp/http/simple/http_client.h> + +using namespace NGrpc; + +namespace NYdb { + +class TIAMCredentialsProvider : public ICredentialsProvider { +public: + TIAMCredentialsProvider(const TIamHost& params) + : HttpClient_(TSimpleHttpClient(params.Host, params.Port)) + , Request_("/computeMetadata/v1/instance/service-accounts/default/token") + , NextTicketUpdate_(TInstant::Zero()) + , RefreshPeriod_(params.RefreshPeriod) + { + GetTicket(); + } + + TStringType GetAuthInfo() const override { + if (TInstant::Now() >= NextTicketUpdate_) { + GetTicket(); + } + return Ticket_; + } + + bool IsValid() const override { + return true; + } + +private: + TSimpleHttpClient HttpClient_; + TStringType Request_; + mutable TStringType Ticket_; + mutable TInstant NextTicketUpdate_; + TDuration RefreshPeriod_; + + void GetTicket() const { + try { + TStringStream out; + TSimpleHttpClient::THeaders headers; + headers["Metadata-Flavor"] = "Google"; + HttpClient_.DoGet(Request_, &out, headers); + NJson::TJsonValue resp; + NJson::ReadJsonTree(&out, &resp, true); + + auto respMap = resp.GetMap(); + + if (auto it = respMap.find("access_token"); it == respMap.end()) + ythrow yexception() << "Result doesn't contain access_token"; + else if (TString ticket = it->second.GetStringSafe(); ticket.empty()) + ythrow yexception() << "Got empty ticket"; + else + Ticket_ = std::move(ticket); + + if (auto it = respMap.find("expires_in"); it == respMap.end()) + ythrow yexception() << "Result doesn't contain expires_in"; + else { + const TDuration expiresIn = TDuration::Seconds(it->second.GetUInteger()); + + NextTicketUpdate_ = TInstant::Now() + std::max(expiresIn, RefreshPeriod_); + } + } catch (...) { + } + } +}; + + +class TIamCredentialsProviderFactory : public ICredentialsProviderFactory { +public: + TIamCredentialsProviderFactory(const TIamHost& params): Params_(params) {} + + TCredentialsProviderPtr CreateProvider() const final { + return std::make_shared<TIAMCredentialsProvider>(Params_); + } + +private: + TIamHost Params_; +}; + +/// Acquire an IAM token using a local metadata service on a virtual machine. +TCredentialsProviderFactoryPtr CreateIamCredentialsProviderFactory(const TIamHost& params ) { + return std::make_shared<TIamCredentialsProviderFactory>(params); +} + +}
\ No newline at end of file diff --git a/ydb/public/sdk/cpp/client/iam/common/iam.h b/ydb/public/sdk/cpp/client/iam/common/iam.h index 46ca7d4cac..5357ffdab8 100644 --- a/ydb/public/sdk/cpp/client/iam/common/iam.h +++ b/ydb/public/sdk/cpp/client/iam/common/iam.h @@ -2,9 +2,18 @@ #include <ydb/public/sdk/cpp/client/ydb_types/credentials/credentials.h> +#include <library/cpp/grpc/client/grpc_client_low.h> +#include <library/cpp/threading/atomic/bool.h> +#include <library/cpp/threading/future/core/future.h> +#include <library/cpp/json/json_reader.h> + #include <ydb/public/lib/jwt/jwt.h> #include <util/datetime/base.h> +#include <util/system/spinlock.h> +#include <util/stream/file.h> +#include <util/string/builder.h> + namespace NYdb { namespace NIam { @@ -33,6 +42,12 @@ struct TIamJwtFilename : TIamEndpoint { TString JwtFilename; }; struct TIamJwtContent : TIamEndpoint { TString JwtContent; }; +struct TIamJwtParams : TIamEndpoint { TJwtParams JwtParams; }; + +inline TJwtParams ReadJwtKeyFile(const TString& filename) { + return ParseJwtParams(TFileInput(filename).ReadAll()); +} + struct TIamOAuth : TIamEndpoint { TString OAuthToken; }; /// Acquire an IAM token using a local metadata service on a virtual machine. @@ -47,4 +62,215 @@ TCredentialsProviderFactoryPtr CreateIamJwtParamsCredentialsProviderFactory(cons // Acquire an IAM token using a user OAuth token. TCredentialsProviderFactoryPtr CreateIamOAuthCredentialsProviderFactory(const TIamOAuth& params); +constexpr TDuration BACKOFF_START = TDuration::MilliSeconds(50); +constexpr TDuration BACKOFF_MAX = TDuration::Seconds(10); + +template<typename TRequest, typename TResponse, typename TService> +class TGrpcIamCredentialsProvider : public ICredentialsProvider { +protected: + using TRequestFiller = std::function<void(TRequest&)>; + +private: + class TImpl : public std::enable_shared_from_this<TGrpcIamCredentialsProvider<TRequest, TResponse, TService>::TImpl> { + public: + TImpl(const TIamEndpoint& iamEndpoint, const TRequestFiller& requestFiller) + : Client(MakeHolder<NGrpc::TGRpcClientLow>()) + , Connection_(nullptr) + , Ticket_("") + , NextTicketUpdate_(TInstant::Zero()) + , IamEndpoint_(iamEndpoint) + , RequestFiller_(requestFiller) + , RequestInflight_(false) + , LastRequestError_("") + , NeedStop_(false) + , BackoffTimeout_(BACKOFF_START) + , Lock_() + { + NGrpc::TGRpcClientConfig grpcConf; + grpcConf.Locator = IamEndpoint_.Endpoint; + grpcConf.EnableSsl = true; + Connection_ = THolder<NGrpc::TServiceConnection<TService>>(Client->CreateGRpcServiceConnection<TService>(grpcConf).release()); + } + + void UpdateTicket(bool sync = false) { + with_lock(Lock_) { + if (NeedStop_ || RequestInflight_) { + return; + } + RequestInflight_ = true; + } + + auto resultPromise = NThreading::NewPromise(); + + std::shared_ptr<TImpl> self = TGrpcIamCredentialsProvider<TRequest, TResponse, TService>::TImpl::shared_from_this(); + + auto cb = [self, resultPromise, sync]( + NGrpc::TGrpcStatus&& status, TResponse&& result) mutable { + self->ProcessIamResponse(std::move(status), std::move(result), sync); + resultPromise.SetValue(); + }; + + TRequest req; + + RequestFiller_(req); + + Connection_->template DoRequest<TRequest, TResponse>( + std::move(req), + std::move(cb), + &TService::Stub::AsyncCreate, + { {}, {}, IamEndpoint_.RequestTimeout } + ); + + if (sync) { + resultPromise.GetFuture().Wait(2 * IamEndpoint_.RequestTimeout); + } + } + + TStringType GetTicket() { + TInstant nextTicketUpdate; + TString ticket; + with_lock(Lock_) { + ticket = Ticket_; + nextTicketUpdate = NextTicketUpdate_; + if (ticket.empty()) + ythrow yexception() << "IAM-token not ready yet. " << LastRequestError_; + } + if (TInstant::Now() >= nextTicketUpdate) { + UpdateTicket(); + } + return ticket; + } + + void Stop() { + with_lock(Lock_) { + if (NeedStop_) { + return; + } + NeedStop_ = true; + } + + Client.Reset(); // Will trigger destroy + } + + private: + void ProcessIamResponse(NGrpc::TGrpcStatus&& status, TResponse&& result, bool sync) { + if (!status.Ok()) { + TDuration sleepDuration; + with_lock(Lock_) { + LastRequestError_ = TStringBuilder() + << "Last request error was at " << TInstant::Now() + << ". GrpcStatusCode: " << status.GRpcStatusCode + << " Message: \"" << status.Msg + << "\" internal: " << status.InternalError + << " iam-endpoint: \"" << IamEndpoint_.Endpoint << "\""; + + RequestInflight_ = false; + sleepDuration = std::min(BackoffTimeout_, BACKOFF_MAX); + BackoffTimeout_ *= 2; + } + + Sleep(sleepDuration); + + UpdateTicket(sync); + } else { + with_lock(Lock_) { + LastRequestError_ = ""; + Ticket_ = result.iam_token(); + RequestInflight_ = false; + BackoffTimeout_ = BACKOFF_START; + + const auto now = Now(); + NextTicketUpdate_ = std::min( + now + IamEndpoint_.RefreshPeriod, + TInstant::Seconds(result.expires_at().seconds()) + ) - IamEndpoint_.RequestTimeout; + NextTicketUpdate_ = std::max(NextTicketUpdate_, now + TDuration::MilliSeconds(100)); + } + } + } + + private: + + THolder<NGrpc::TGRpcClientLow> Client; + THolder<NGrpc::TServiceConnection<TService>> Connection_; + TStringType Ticket_; + TInstant NextTicketUpdate_; + const TIamEndpoint IamEndpoint_; + const TRequestFiller RequestFiller_; + bool RequestInflight_; + TStringType LastRequestError_; + bool NeedStop_; + TDuration BackoffTimeout_; + TAdaptiveLock Lock_; + }; + +public: + TGrpcIamCredentialsProvider(const TIamEndpoint& endpoint, const TRequestFiller& requestFiller) + : Impl_(std::make_shared<TImpl>(endpoint, requestFiller)) + { + Impl_->UpdateTicket(true); + } + + ~TGrpcIamCredentialsProvider() { + Impl_->Stop(); + } + + TStringType GetAuthInfo() const override { + return Impl_->GetTicket(); + } + + bool IsValid() const override { + return true; + } + +private: + std::shared_ptr<TImpl> Impl_; +}; + +template<typename TRequest, typename TResponse, typename TService> +class TIamJwtCredentialsProvider : public TGrpcIamCredentialsProvider<TRequest, TResponse, TService> { +public: + TIamJwtCredentialsProvider(const TIamJwtParams& params) + : TGrpcIamCredentialsProvider<TRequest, TResponse, TService>(params, + [jwtParams = params.JwtParams](TRequest& req) { + req.set_jwt(MakeSignedJwt(jwtParams)); + }) {} +}; + +template<typename TRequest, typename TResponse, typename TService> +class TIamOAuthCredentialsProvider : public TGrpcIamCredentialsProvider<TRequest, TResponse, TService> { +public: + TIamOAuthCredentialsProvider(const TIamOAuth& params) + : TGrpcIamCredentialsProvider<TRequest, TResponse, TService>(params, + [token = params.OAuthToken](TRequest& req) { + req.set_yandex_passport_oauth_token(token); + }) {} +}; + +template<typename TRequest, typename TResponse, typename TService> +class TIamJwtCredentialsProviderFactory : public ICredentialsProviderFactory { +public: + TIamJwtCredentialsProviderFactory(const TIamJwtParams& params): Params_(params) {} + + TCredentialsProviderPtr CreateProvider() const final { + return std::make_shared<TIamJwtCredentialsProvider<TRequest, TResponse, TService>>(Params_); + } + +private: + TIamJwtParams Params_; +}; + +template<typename TRequest, typename TResponse, typename TService> +class TIamOAuthCredentialsProviderFactory : public ICredentialsProviderFactory { +public: + TIamOAuthCredentialsProviderFactory(const TIamOAuth& params): Params_(params) {} + + TCredentialsProviderPtr CreateProvider() const final { + return std::make_shared<TIamOAuthCredentialsProvider<TRequest, TResponse, TService>>(Params_); + } + +private: + TIamOAuth Params_; +}; + } // namespace NYdb diff --git a/ydb/public/sdk/cpp/client/iam/iam.cpp b/ydb/public/sdk/cpp/client/iam/iam.cpp index 630faba02a..02626df8fa 100644 --- a/ydb/public/sdk/cpp/client/iam/iam.cpp +++ b/ydb/public/sdk/cpp/client/iam/iam.cpp @@ -1,7 +1,7 @@ -#include "impl/iam_impl.h" +#include <ydb/public/sdk/cpp/client/iam/common/iam.h> -#include <ydb/public/sdk/cpp/client/iam/proto/v1/iam_token_service.pb.h> -#include <ydb/public/sdk/cpp/client/iam/proto/v1/iam_token_service.grpc.pb.h> +#include <ydb/public/api/client/yc_public/iam/iam_token_service.pb.h> +#include <ydb/public/api/client/yc_public/iam/iam_token_service.grpc.pb.h> using namespace yandex::cloud::iam::v1; @@ -21,10 +21,6 @@ TCredentialsProviderFactoryPtr CreateIamJwtParamsCredentialsProviderFactory(cons IamTokenService>>(std::move(jwtParams)); } -TCredentialsProviderFactoryPtr CreateIamCredentialsProviderFactory(const TIamHost& params) { - return std::make_shared<TIamCredentialsProviderFactory>(params); -} - TCredentialsProviderFactoryPtr CreateIamOAuthCredentialsProviderFactory(const TIamOAuth& params) { return std::make_shared<TIamOAuthCredentialsProviderFactory<CreateIamTokenRequest, CreateIamTokenResponse, diff --git a/ydb/public/sdk/cpp/client/iam/impl/iam_impl.h b/ydb/public/sdk/cpp/client/iam/impl/iam_impl.h index 60b001282c..e69de29bb2 100644 --- a/ydb/public/sdk/cpp/client/iam/impl/iam_impl.h +++ b/ydb/public/sdk/cpp/client/iam/impl/iam_impl.h @@ -1,311 +0,0 @@ -#pragma once -#include <ydb/public/sdk/cpp/client/iam/common/iam.h> - -#include <library/cpp/grpc/client/grpc_client_low.h> -#include <library/cpp/threading/atomic/bool.h> -#include <library/cpp/threading/future/core/future.h> -#include <library/cpp/json/json_reader.h> -#include <library/cpp/http/simple/http_client.h> - -#include <util/system/spinlock.h> -#include <util/stream/file.h> -#include <util/string/builder.h> - -#include <chrono> - -using namespace NGrpc; - -namespace NYdb { - -constexpr TDuration BACKOFF_START = TDuration::MilliSeconds(50); -constexpr TDuration BACKOFF_MAX = TDuration::Seconds(10); - -class TIAMCredentialsProvider : public ICredentialsProvider { -public: - TIAMCredentialsProvider(const TIamHost& params) - : HttpClient_(TSimpleHttpClient(params.Host, params.Port)) - , Request_("/computeMetadata/v1/instance/service-accounts/default/token") - , NextTicketUpdate_(TInstant::Zero()) - , RefreshPeriod_(params.RefreshPeriod) - { - GetTicket(); - } - - TStringType GetAuthInfo() const override { - if (TInstant::Now() >= NextTicketUpdate_) { - GetTicket(); - } - return Ticket_; - } - - bool IsValid() const override { - return true; - } - -private: - TSimpleHttpClient HttpClient_; - TStringType Request_; - mutable TStringType Ticket_; - mutable TInstant NextTicketUpdate_; - TDuration RefreshPeriod_; - - void GetTicket() const { - try { - TStringStream out; - TSimpleHttpClient::THeaders headers; - headers["Metadata-Flavor"] = "Google"; - HttpClient_.DoGet(Request_, &out, headers); - NJson::TJsonValue resp; - NJson::ReadJsonTree(&out, &resp, true); - - auto respMap = resp.GetMap(); - - if (auto it = respMap.find("access_token"); it == respMap.end()) - ythrow yexception() << "Result doesn't contain access_token"; - else if (TString ticket = it->second.GetStringSafe(); ticket.empty()) - ythrow yexception() << "Got empty ticket"; - else - Ticket_ = std::move(ticket); - - if (auto it = respMap.find("expires_in"); it == respMap.end()) - ythrow yexception() << "Result doesn't contain expires_in"; - else { - const TDuration expiresIn = TDuration::Seconds(it->second.GetUInteger()); - - NextTicketUpdate_ = TInstant::Now() + std::max(expiresIn, RefreshPeriod_); - } - } catch (...) { - } - } -}; - - -template<typename TRequest, typename TResponse, typename TService> -class TGrpcIamCredentialsProvider : public ICredentialsProvider { -protected: - using TRequestFiller = std::function<void(TRequest&)>; - -private: - class TImpl : public std::enable_shared_from_this<TGrpcIamCredentialsProvider<TRequest, TResponse, TService>::TImpl> { - public: - TImpl(const TIamEndpoint& iamEndpoint, const TRequestFiller& requestFiller) - : Client(MakeHolder<NGrpc::TGRpcClientLow>()) - , Connection_(nullptr) - , Ticket_("") - , NextTicketUpdate_(TInstant::Zero()) - , IamEndpoint_(iamEndpoint) - , RequestFiller_(requestFiller) - , RequestInflight_(false) - , LastRequestError_("") - , NeedStop_(false) - , BackoffTimeout_(BACKOFF_START) - , Lock_() - { - TGRpcClientConfig grpcConf; - grpcConf.Locator = IamEndpoint_.Endpoint; - grpcConf.EnableSsl = true; - Connection_ = THolder<TServiceConnection<TService>>(Client->CreateGRpcServiceConnection<TService>(grpcConf).release()); - } - - void UpdateTicket(bool sync = false) { - with_lock(Lock_) { - if (NeedStop_ || RequestInflight_) { - return; - } - RequestInflight_ = true; - } - - auto resultPromise = NThreading::NewPromise(); - - std::shared_ptr<TImpl> self = TGrpcIamCredentialsProvider<TRequest, TResponse, TService>::TImpl::shared_from_this(); - - auto cb = [self, resultPromise, sync]( - NGrpc::TGrpcStatus&& status, TResponse&& result) mutable { - self->ProcessIamResponse(std::move(status), std::move(result), sync); - resultPromise.SetValue(); - }; - - TRequest req; - - RequestFiller_(req); - - Connection_->template DoRequest<TRequest, TResponse>( - std::move(req), - std::move(cb), - &TService::Stub::AsyncCreate, - { {}, {}, IamEndpoint_.RequestTimeout } - ); - - if (sync) { - resultPromise.GetFuture().Wait(2 * IamEndpoint_.RequestTimeout); - } - } - - TStringType GetTicket() { - TInstant nextTicketUpdate; - TString ticket; - with_lock(Lock_) { - ticket = Ticket_; - nextTicketUpdate = NextTicketUpdate_; - if (ticket.empty()) - ythrow yexception() << "IAM-token not ready yet. " << LastRequestError_; - } - if (TInstant::Now() >= nextTicketUpdate) { - UpdateTicket(); - } - return ticket; - } - - void Stop() { - with_lock(Lock_) { - if (NeedStop_) { - return; - } - NeedStop_ = true; - } - - Client.Reset(); // Will trigger destroy - } - - private: - void ProcessIamResponse(NGrpc::TGrpcStatus&& status, TResponse&& result, bool sync) { - if (!status.Ok()) { - TDuration sleepDuration; - with_lock(Lock_) { - LastRequestError_ = TStringBuilder() - << "Last request error was at " << TInstant::Now() - << ". GrpcStatusCode: " << status.GRpcStatusCode - << " Message: \"" << status.Msg - << "\" internal: " << status.InternalError - << " iam-endpoint: \"" << IamEndpoint_.Endpoint << "\""; - - RequestInflight_ = false; - sleepDuration = std::min(BackoffTimeout_, BACKOFF_MAX); - BackoffTimeout_ *= 2; - } - - Sleep(sleepDuration); - - UpdateTicket(sync); - } else { - with_lock(Lock_) { - LastRequestError_ = ""; - Ticket_ = result.iam_token(); - RequestInflight_ = false; - BackoffTimeout_ = BACKOFF_START; - - const auto now = Now(); - NextTicketUpdate_ = std::min( - now + IamEndpoint_.RefreshPeriod, - TInstant::Seconds(result.expires_at().seconds()) - ) - IamEndpoint_.RequestTimeout; - NextTicketUpdate_ = std::max(NextTicketUpdate_, now + TDuration::MilliSeconds(100)); - } - } - } - - private: - - THolder<TGRpcClientLow> Client; - THolder<TServiceConnection<TService>> Connection_; - TStringType Ticket_; - TInstant NextTicketUpdate_; - const TIamEndpoint IamEndpoint_; - const TRequestFiller RequestFiller_; - bool RequestInflight_; - TStringType LastRequestError_; - bool NeedStop_; - TDuration BackoffTimeout_; - TAdaptiveLock Lock_; - }; - -public: - TGrpcIamCredentialsProvider(const TIamEndpoint& endpoint, const TRequestFiller& requestFiller) - : Impl_(std::make_shared<TImpl>(endpoint, requestFiller)) - { - Impl_->UpdateTicket(true); - } - - ~TGrpcIamCredentialsProvider() { - Impl_->Stop(); - } - - TStringType GetAuthInfo() const override { - return Impl_->GetTicket(); - } - - bool IsValid() const override { - return true; - } - -private: - std::shared_ptr<TImpl> Impl_; -}; - -struct TIamJwtParams : TIamEndpoint { - TJwtParams JwtParams; -}; - -template<typename TRequest, typename TResponse, typename TService> -class TIamJwtCredentialsProvider : public TGrpcIamCredentialsProvider<TRequest, TResponse, TService> { -public: - TIamJwtCredentialsProvider(const TIamJwtParams& params) - : TGrpcIamCredentialsProvider<TRequest, TResponse, TService>(params, - [jwtParams = params.JwtParams](TRequest& req) { - req.set_jwt(MakeSignedJwt(jwtParams)); - }) {} -}; - -template<typename TRequest, typename TResponse, typename TService> -class TIamOAuthCredentialsProvider : public TGrpcIamCredentialsProvider<TRequest, TResponse, TService> { -public: - TIamOAuthCredentialsProvider(const TIamOAuth& params) - : TGrpcIamCredentialsProvider<TRequest, TResponse, TService>(params, - [token = params.OAuthToken](TRequest& req) { - req.set_yandex_passport_oauth_token(token); - }) {} -}; - -inline TJwtParams ReadJwtKeyFile(const TString& filename) { - return ParseJwtParams(TFileInput(filename).ReadAll()); -} - -class TIamCredentialsProviderFactory : public ICredentialsProviderFactory { -public: - TIamCredentialsProviderFactory(const TIamHost& params): Params_(params) {} - - TCredentialsProviderPtr CreateProvider() const final { - return std::make_shared<TIAMCredentialsProvider>(Params_); - } - -private: - TIamHost Params_; -}; - -template<typename TRequest, typename TResponse, typename TService> -class TIamJwtCredentialsProviderFactory : public ICredentialsProviderFactory { -public: - TIamJwtCredentialsProviderFactory(const TIamJwtParams& params): Params_(params) {} - - TCredentialsProviderPtr CreateProvider() const final { - return std::make_shared<TIamJwtCredentialsProvider<TRequest, TResponse, TService>>(Params_); - } - -private: - TIamJwtParams Params_; -}; - -template<typename TRequest, typename TResponse, typename TService> -class TIamOAuthCredentialsProviderFactory : public ICredentialsProviderFactory { -public: - TIamOAuthCredentialsProviderFactory(const TIamOAuth& params): Params_(params) {} - - TCredentialsProviderPtr CreateProvider() const final { - return std::make_shared<TIamOAuthCredentialsProvider<TRequest, TResponse, TService>>(Params_); - } - -private: - TIamOAuth Params_; -}; - -} // namespace NYdb diff --git a/ydb/public/sdk/cpp/client/iam/proto/v1/README.md b/ydb/public/sdk/cpp/client/iam/proto/v1/README.md deleted file mode 100644 index 308749f373..0000000000 --- a/ydb/public/sdk/cpp/client/iam/proto/v1/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains copy of ycloud public protobuf from https://github.com/yandex-cloud/cloudapi/tree/master/yandex/cloud -Used to provide access to IAM service from C++ SDK |