diff options
author | alexv-smirnov <alex@ydb.tech> | 2022-10-26 20:47:36 +0300 |
---|---|---|
committer | alexv-smirnov <alex@ydb.tech> | 2022-10-26 20:47:36 +0300 |
commit | 7d977b6f917a50979779188b685a9201975048d6 (patch) | |
tree | 503a904fe41bb8a010013e60e90fcdb9e48b5b16 | |
parent | 608252fc836bcc17fd845053126f1e60bee2f767 (diff) | |
download | ydb-7d977b6f917a50979779188b685a9201975048d6.tar.gz |
move ycloud client lib + server mocks to ydb/library
60 files changed, 2419 insertions, 0 deletions
diff --git a/CMakeLists.darwin.txt b/CMakeLists.darwin.txt index cd6d87e6526..912b806b6a2 100644 --- a/CMakeLists.darwin.txt +++ b/CMakeLists.darwin.txt @@ -12,3 +12,4 @@ add_subdirectory(util) add_subdirectory(library) add_subdirectory(ydb) add_subdirectory(certs) +add_subdirectory(cloud) diff --git a/CMakeLists.linux-aarch64.txt b/CMakeLists.linux-aarch64.txt index cd6d87e6526..912b806b6a2 100644 --- a/CMakeLists.linux-aarch64.txt +++ b/CMakeLists.linux-aarch64.txt @@ -12,3 +12,4 @@ add_subdirectory(util) add_subdirectory(library) add_subdirectory(ydb) add_subdirectory(certs) +add_subdirectory(cloud) diff --git a/CMakeLists.linux.txt b/CMakeLists.linux.txt index cd6d87e6526..912b806b6a2 100644 --- a/CMakeLists.linux.txt +++ b/CMakeLists.linux.txt @@ -12,3 +12,4 @@ add_subdirectory(util) add_subdirectory(library) add_subdirectory(ydb) add_subdirectory(certs) +add_subdirectory(cloud) diff --git a/cloud/CMakeLists.txt b/cloud/CMakeLists.txt new file mode 100644 index 00000000000..3ad0faf5243 --- /dev/null +++ b/cloud/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(bitbucket) diff --git a/cloud/bitbucket/CMakeLists.txt b/cloud/bitbucket/CMakeLists.txt new file mode 100644 index 00000000000..ab8cce84c4f --- /dev/null +++ b/cloud/bitbucket/CMakeLists.txt @@ -0,0 +1,10 @@ + +# 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-api) +add_subdirectory(private-api) diff --git a/cloud/bitbucket/common-api/CMakeLists.txt b/cloud/bitbucket/common-api/CMakeLists.txt new file mode 100644 index 00000000000..9fee5b33311 --- /dev/null +++ b/cloud/bitbucket/common-api/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(yandex) diff --git a/cloud/bitbucket/common-api/yandex/CMakeLists.txt b/cloud/bitbucket/common-api/yandex/CMakeLists.txt new file mode 100644 index 00000000000..d51f65f4b47 --- /dev/null +++ b/cloud/bitbucket/common-api/yandex/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(cloud) diff --git a/cloud/bitbucket/common-api/yandex/cloud/CMakeLists.txt b/cloud/bitbucket/common-api/yandex/cloud/CMakeLists.txt new file mode 100644 index 00000000000..0a386de02f7 --- /dev/null +++ b/cloud/bitbucket/common-api/yandex/cloud/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(api) diff --git a/cloud/bitbucket/common-api/yandex/cloud/api/CMakeLists.txt b/cloud/bitbucket/common-api/yandex/cloud/api/CMakeLists.txt new file mode 100644 index 00000000000..f0abd297c94 --- /dev/null +++ b/cloud/bitbucket/common-api/yandex/cloud/api/CMakeLists.txt @@ -0,0 +1,51 @@ + +# 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(tools) + +add_library(yandex-cloud-api) +set_property(TARGET yandex-cloud-api PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +set_property(TARGET yandex-cloud-api PROPERTY + PROTO_NAMESPACE cloud/bitbucket/common-api +) +target_include_directories(yandex-cloud-api PUBLIC + ${CMAKE_BINARY_DIR}/cloud/bitbucket/common-api +) +target_link_libraries(yandex-cloud-api PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + cloud-api-tools + contrib-libs-protobuf +) +target_proto_messages(yandex-cloud-api PRIVATE + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api/yandex/cloud/api/operation.proto +) +target_proto_addincls(yandex-cloud-api + ./cloud/bitbucket/common-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api + ${CMAKE_SOURCE_DIR}/contrib/libs/googleapis-common-protos + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src +) +target_proto_outs(yandex-cloud-api + --cpp_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/common-api + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/common-api +) +target_proto_plugin(yandex-cloud-api + grpc_cpp + grpc_cpp +) diff --git a/cloud/bitbucket/common-api/yandex/cloud/api/tools/CMakeLists.txt b/cloud/bitbucket/common-api/yandex/cloud/api/tools/CMakeLists.txt new file mode 100644 index 00000000000..12b18776a01 --- /dev/null +++ b/cloud/bitbucket/common-api/yandex/cloud/api/tools/CMakeLists.txt @@ -0,0 +1,48 @@ + +# 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(cloud-api-tools) +set_property(TARGET cloud-api-tools PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +set_property(TARGET cloud-api-tools PROPERTY + PROTO_NAMESPACE cloud/bitbucket/common-api +) +target_include_directories(cloud-api-tools PUBLIC + ${CMAKE_BINARY_DIR}/cloud/bitbucket/common-api +) +target_link_libraries(cloud-api-tools PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + contrib-libs-protobuf +) +target_proto_messages(cloud-api-tools PRIVATE + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api/yandex/cloud/api/tools/options.proto +) +target_proto_addincls(cloud-api-tools + ./cloud/bitbucket/common-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api + ${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(cloud-api-tools + --cpp_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/common-api + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/common-api +) +target_proto_plugin(cloud-api-tools + grpc_cpp + grpc_cpp +) diff --git a/cloud/bitbucket/private-api/CMakeLists.txt b/cloud/bitbucket/private-api/CMakeLists.txt new file mode 100644 index 00000000000..9fee5b33311 --- /dev/null +++ b/cloud/bitbucket/private-api/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(yandex) diff --git a/cloud/bitbucket/private-api/yandex/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/CMakeLists.txt new file mode 100644 index 00000000000..d51f65f4b47 --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(cloud) diff --git a/cloud/bitbucket/private-api/yandex/cloud/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/cloud/CMakeLists.txt new file mode 100644 index 00000000000..20e0028be29 --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/cloud/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(priv) diff --git a/cloud/bitbucket/private-api/yandex/cloud/priv/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/cloud/priv/CMakeLists.txt new file mode 100644 index 00000000000..7b85366d1f5 --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/cloud/priv/CMakeLists.txt @@ -0,0 +1,53 @@ + +# 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(access) +add_subdirectory(operation) +add_subdirectory(quota) +add_subdirectory(ydb) + +add_library(yandex-cloud-priv) +set_property(TARGET yandex-cloud-priv PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +set_property(TARGET yandex-cloud-priv PROPERTY + PROTO_NAMESPACE cloud/bitbucket/private-api +) +target_include_directories(yandex-cloud-priv PUBLIC + ${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_link_libraries(yandex-cloud-priv PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + contrib-libs-protobuf +) +target_proto_messages(yandex-cloud-priv PRIVATE + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/sensitive.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/validation.proto +) +target_proto_addincls(yandex-cloud-priv + ./cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${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(yandex-cloud-priv + --cpp_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_proto_plugin(yandex-cloud-priv + grpc_cpp + grpc_cpp +) diff --git a/cloud/bitbucket/private-api/yandex/cloud/priv/access/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/cloud/priv/access/CMakeLists.txt new file mode 100644 index 00000000000..d4e907cf4fd --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/cloud/priv/access/CMakeLists.txt @@ -0,0 +1,50 @@ + +# 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(cloud-priv-access) +set_property(TARGET cloud-priv-access PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +set_property(TARGET cloud-priv-access PROPERTY + PROTO_NAMESPACE cloud/bitbucket/private-api +) +target_include_directories(cloud-priv-access PUBLIC + ${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_link_libraries(cloud-priv-access PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + yandex-cloud-priv + contrib-libs-protobuf +) +target_proto_messages(cloud-priv-access PRIVATE + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/access/access.proto +) +target_proto_addincls(cloud-priv-access + ./cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/contrib/libs/googleapis-common-protos + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src +) +target_proto_outs(cloud-priv-access + --cpp_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_proto_plugin(cloud-priv-access + grpc_cpp + grpc_cpp +) diff --git a/cloud/bitbucket/private-api/yandex/cloud/priv/operation/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/cloud/priv/operation/CMakeLists.txt new file mode 100644 index 00000000000..759162a183c --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/cloud/priv/operation/CMakeLists.txt @@ -0,0 +1,48 @@ + +# 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(cloud-priv-operation) +set_property(TARGET cloud-priv-operation PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +set_property(TARGET cloud-priv-operation PROPERTY + PROTO_NAMESPACE cloud/bitbucket/private-api +) +target_include_directories(cloud-priv-operation PUBLIC + ${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_link_libraries(cloud-priv-operation PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + contrib-libs-protobuf +) +target_proto_messages(cloud-priv-operation PRIVATE + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/operation/operation.proto +) +target_proto_addincls(cloud-priv-operation + ./cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${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(cloud-priv-operation + --cpp_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_proto_plugin(cloud-priv-operation + grpc_cpp + grpc_cpp +) diff --git a/cloud/bitbucket/private-api/yandex/cloud/priv/quota/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/cloud/priv/quota/CMakeLists.txt new file mode 100644 index 00000000000..d0897999b23 --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/cloud/priv/quota/CMakeLists.txt @@ -0,0 +1,51 @@ + +# 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(cloud-priv-quota) +set_property(TARGET cloud-priv-quota PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +set_property(TARGET cloud-priv-quota PROPERTY + PROTO_NAMESPACE cloud/bitbucket/private-api +) +target_include_directories(cloud-priv-quota PUBLIC + ${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_link_libraries(cloud-priv-quota PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + yandex-cloud-priv + contrib-libs-protobuf +) +target_proto_messages(cloud-priv-quota PRIVATE + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/quota/quota.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/quota/quota_limit.proto +) +target_proto_addincls(cloud-priv-quota + ./cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/contrib/libs/googleapis-common-protos + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src +) +target_proto_outs(cloud-priv-quota + --cpp_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_proto_plugin(cloud-priv-quota + grpc_cpp + grpc_cpp +) diff --git a/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/CMakeLists.txt new file mode 100644 index 00000000000..0293e4453a3 --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(v1) diff --git a/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/CMakeLists.txt b/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/CMakeLists.txt new file mode 100644 index 00000000000..ff2361c3f36 --- /dev/null +++ b/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/CMakeLists.txt @@ -0,0 +1,67 @@ + +# 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(priv-ydb-v1) +set_property(TARGET priv-ydb-v1 PROPERTY + PROTOC_EXTRA_OUTS .grpc.pb.cc .grpc.pb.h +) +set_property(TARGET priv-ydb-v1 PROPERTY + PROTO_NAMESPACE cloud/bitbucket/private-api +) +target_include_directories(priv-ydb-v1 PUBLIC + ${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_link_libraries(priv-ydb-v1 PUBLIC + contrib-libs-cxxsupp + yutil + contrib-libs-grpc + contrib-libs-googleapis-common-protos + yandex-cloud-api + cloud-api-tools + yandex-cloud-priv + cloud-priv-access + cloud-priv-operation + cloud-priv-quota + contrib-libs-protobuf +) +target_proto_messages(priv-ydb-v1 PRIVATE + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/backup.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/backup_service.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/database.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/database_service.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/location.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/location_service.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/operation_service.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/quota_service.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/resource_preset.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/resource_preset_service.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/storage_type.proto + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/storage_type_service.proto +) +target_proto_addincls(priv-ydb-v1 + ./cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_SOURCE_DIR}/contrib/libs/googleapis-common-protos + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/common-api + ${CMAKE_SOURCE_DIR}/cloud/bitbucket/private-api + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/contrib/libs/protobuf/src +) +target_proto_outs(priv-ydb-v1 + --cpp_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api + --cpp_styleguide_out=${CMAKE_BINARY_DIR}/cloud/bitbucket/private-api +) +target_proto_plugin(priv-ydb-v1 + grpc_cpp + grpc_cpp +) diff --git a/ydb/library/CMakeLists.txt b/ydb/library/CMakeLists.txt index 5186aee93ab..d0c39c49203 100644 --- a/ydb/library/CMakeLists.txt +++ b/ydb/library/CMakeLists.txt @@ -25,6 +25,8 @@ add_subdirectory(pretty_types_print) add_subdirectory(protobuf_printer) add_subdirectory(schlab) add_subdirectory(security) +add_subdirectory(testlib) add_subdirectory(workload) add_subdirectory(yaml_config) +add_subdirectory(ycloud) add_subdirectory(yql) diff --git a/ydb/library/testlib/CMakeLists.txt b/ydb/library/testlib/CMakeLists.txt new file mode 100644 index 00000000000..52ceab64c9f --- /dev/null +++ b/ydb/library/testlib/CMakeLists.txt @@ -0,0 +1,9 @@ + +# 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(service_mocks) diff --git a/ydb/library/testlib/service_mocks/CMakeLists.txt b/ydb/library/testlib/service_mocks/CMakeLists.txt new file mode 100644 index 00000000000..339154ea3b3 --- /dev/null +++ b/ydb/library/testlib/service_mocks/CMakeLists.txt @@ -0,0 +1,19 @@ + +# 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(library-testlib-service_mocks INTERFACE) +target_link_libraries(library-testlib-service_mocks INTERFACE + contrib-libs-cxxsupp + yutil + client-yc_private-servicecontrol + priv-ydb-v1 + api-grpc-draft + client-yc_private-resourcemanager + client-yc_private-iam +) diff --git a/ydb/library/testlib/service_mocks/access_service_mock.h b/ydb/library/testlib/service_mocks/access_service_mock.h new file mode 100644 index 00000000000..5fb88cda0fd --- /dev/null +++ b/ydb/library/testlib/service_mocks/access_service_mock.h @@ -0,0 +1,69 @@ +#pragma once + +#include <ydb/public/api/client/yc_private/servicecontrol/access_service.grpc.pb.h> + +#include <library/cpp/testing/unittest/registar.h> + +#include <iterator> + +class TAccessServiceMock : public yandex::cloud::priv::servicecontrol::v1::AccessService::Service { +public: + template <class TResonseProto> + struct TResponse { + TResonseProto Response; + grpc::Status Status = grpc::Status::OK; + bool RequireRequestId = false; + }; + + THashMap<TString, TResponse<yandex::cloud::priv::servicecontrol::v1::AuthenticateResponse>> AuthenticateData; + THashMap<TString, TResponse<yandex::cloud::priv::servicecontrol::v1::AuthorizeResponse>> AuthorizeData; + + template <class TResonseProto> + void CheckRequestId(grpc::ServerContext* ctx, const TResponse<TResonseProto>& resp, const TString& token) { + if (resp.RequireRequestId) { + auto [reqIdBegin, reqIdEnd] = ctx->client_metadata().equal_range("x-request-id"); + UNIT_ASSERT_C(reqIdBegin != reqIdEnd, "RequestId is expected. Token: " << token); + UNIT_ASSERT_VALUES_EQUAL_C(std::distance(reqIdBegin, reqIdEnd), 1, "Only one RequestId is expected. Token: " << token); + UNIT_ASSERT_C(!reqIdBegin->second.empty(), "RequestId is expected to be not empty. Token: " << token); + } + } + + virtual grpc::Status Authenticate( + grpc::ServerContext* ctx, + const yandex::cloud::priv::servicecontrol::v1::AuthenticateRequest* request, + yandex::cloud::priv::servicecontrol::v1::AuthenticateResponse* response) override + { + TString key; + if (request->has_signature()) { + key = request->signature().v4_parameters().service(); + } else { + key = request->iam_token(); + } + + auto it = AuthenticateData.find(key); + if (it != AuthenticateData.end()) { + response->CopyFrom(it->second.Response); + CheckRequestId(ctx, it->second, key); + return it->second.Status; + } else { + return grpc::Status(grpc::StatusCode::PERMISSION_DENIED, "Permission Denied"); + } + } + + virtual grpc::Status Authorize( + grpc::ServerContext* ctx, + const yandex::cloud::priv::servicecontrol::v1::AuthorizeRequest* request, + yandex::cloud::priv::servicecontrol::v1::AuthorizeResponse* response) override + { + const TString& lastResourceId = request->resource_path(request->resource_path_size() - 1).id(); + const TString& token = request->signature().access_key_id() + request->iam_token() + "-" + request->permission() + "-" + lastResourceId; + auto it = AuthorizeData.find(token); + if (it != AuthorizeData.end()) { + response->CopyFrom(it->second.Response); + CheckRequestId(ctx, it->second, token); + return it->second.Status; + } else { + return grpc::Status(grpc::StatusCode::PERMISSION_DENIED, "Permission Denied"); + } + } +}; diff --git a/ydb/library/testlib/service_mocks/database_service_mock.h b/ydb/library/testlib/service_mocks/database_service_mock.h new file mode 100644 index 00000000000..59fff6dde99 --- /dev/null +++ b/ydb/library/testlib/service_mocks/database_service_mock.h @@ -0,0 +1,75 @@ +#pragma once + +#include <cloud/bitbucket/private-api/yandex/cloud/priv/ydb/v1/database_service.grpc.pb.h> +#include <util/string/join.h> +#include <util/string/vector.h> + +class TDatabaseServiceMock : public yandex::cloud::priv::ydb::v1::DatabaseService::Service { +public: + THashMap<TString, yandex::cloud::priv::ydb::v1::Database> PersistentDatabases; + THashMap<TString, yandex::cloud::priv::ydb::v1::Database> TemporaryDatabases; + TString Identity; + + TMaybe<grpc::Status> CheckAuthorization(grpc::ServerContext* context) { + if (!Identity.empty()) { + auto[reqIdBegin, reqIdEnd] = context->client_metadata().equal_range("authorization"); + UNIT_ASSERT_C(reqIdBegin != reqIdEnd, "Authorization is expected."); + if (Identity != TStringBuf(reqIdBegin->second.cbegin(), reqIdBegin->second.cend())) { + return grpc::Status(grpc::StatusCode::UNAUTHENTICATED, + TStringBuilder() << "Access for user " << Identity << " is forbidden"); + } + } + + return Nothing(); + } + + virtual grpc::Status GetByPath(grpc::ServerContext* context, + const yandex::cloud::priv::ydb::v1::GetDatabaseByPathRequest* request, + yandex::cloud::priv::ydb::v1::Database* response) override + { + auto status = CheckAuthorization(context); + auto parts = SplitString(request->path(), "/"); + Y_ENSURE(parts.size() >= 3); + TString canonizedPath = "/" + JoinRange("/", parts.begin(), parts.begin() + 3); + + if (auto itPersistent = PersistentDatabases.find(canonizedPath); itPersistent != PersistentDatabases.end()) { + *response = itPersistent->second; + return grpc::Status::OK; + } else { + auto it = TemporaryDatabases.find(canonizedPath); + if (it == TemporaryDatabases.end()) { + return grpc::Status(grpc::StatusCode::NOT_FOUND, TStringBuilder() << " database with name " << request->path() << " not found"); + } else { + *response = it->second; + return grpc::Status::OK; + } + } + } + + virtual grpc::Status ListAll(grpc::ServerContext* context, + const yandex::cloud::priv::ydb::v1::ListAllDatabasesRequest* request, + yandex::cloud::priv::ydb::v1::ListAllDatabasesResponse* response) override + { + auto status = CheckAuthorization(context); + if (status.Defined()) { + return *status; + } + + if (PersistentDatabases.empty()) { + return grpc::Status::OK; + } + auto it = PersistentDatabases.begin(); + if (!request->page_token().empty()) { + it = PersistentDatabases.find(request->page_token()); + } + Y_ENSURE(it != PersistentDatabases.end()); + *response->add_databases() = it->second; + it++; + if (it != PersistentDatabases.end()) { + response->set_next_page_token(it->first); + } + return grpc::Status::OK; + } + +}; + diff --git a/ydb/library/testlib/service_mocks/datastreams_service_mock.h b/ydb/library/testlib/service_mocks/datastreams_service_mock.h new file mode 100644 index 00000000000..3f65899cfc4 --- /dev/null +++ b/ydb/library/testlib/service_mocks/datastreams_service_mock.h @@ -0,0 +1,31 @@ +#pragma once + +#include <ydb/public/api/grpc/draft/ydb_datastreams_v1.grpc.pb.h> +#include "access_service_mock.h" +#include "datastreams_service_mock.h" + +class TDataStreamsServiceMock : public Ydb::DataStreams::V1::DataStreamsService::Service { +public: + virtual grpc::Status PutRecords(grpc::ServerContext*, + const Ydb::DataStreams::V1::PutRecordsRequest* request, + Ydb::DataStreams::V1::PutRecordsResponse* response) override + { + Y_UNUSED(response); + for (const auto& record : request->records()) { + if (record.partition_key() == "Sleep") { + Sleep(TDuration::Seconds(3)); + } else if (record.partition_key() == "InvalidArgument") { + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid argument"); + } else if (record.partition_key() == "Unauthenticated") { + return grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "Access denied"); + } + } + response->mutable_operation()->set_status(Ydb::StatusIds::SUCCESS); + response->mutable_operation()->set_ready(true); + response->mutable_operation()->set_id("12345"); + + return grpc::Status::OK; + } + +}; + diff --git a/ydb/library/testlib/service_mocks/folder_service_mock.h b/ydb/library/testlib/service_mocks/folder_service_mock.h new file mode 100644 index 00000000000..90ba4c6fde1 --- /dev/null +++ b/ydb/library/testlib/service_mocks/folder_service_mock.h @@ -0,0 +1,23 @@ +#pragma once + +#include <ydb/public/api/client/yc_private/resourcemanager/folder_service.grpc.pb.h> + +class TFolderServiceMock : public yandex::cloud::priv::resourcemanager::v1::transitional::FolderService::Service { +public: + THashMap<TString, yandex::cloud::priv::resourcemanager::v1::Folder> Folders; + + virtual grpc::Status List( + grpc::ServerContext*, + const yandex::cloud::priv::resourcemanager::v1::transitional::ListFoldersRequest* request, + yandex::cloud::priv::resourcemanager::v1::transitional::ListFoldersResponse* response) override { + TString key = request->id(); + auto it = Folders.find(key); + if (it != Folders.end()) { + response->add_result()->CopyFrom(it->second); + return grpc::Status::OK; + } else { + return grpc::Status(grpc::StatusCode::NOT_FOUND, "Not Found"); + } + } +}; + diff --git a/ydb/library/testlib/service_mocks/iam_token_service_mock.h b/ydb/library/testlib/service_mocks/iam_token_service_mock.h new file mode 100644 index 00000000000..c2cc6e3b80b --- /dev/null +++ b/ydb/library/testlib/service_mocks/iam_token_service_mock.h @@ -0,0 +1,43 @@ +#pragma once + +#include <ydb/public/api/client/yc_private/iam/iam_token_service.grpc.pb.h> + +class TIamTokenServiceMock : public yandex::cloud::priv::iam::v1::IamTokenService::Service { +public: + THashMap<TString, yandex::cloud::priv::iam::v1::CreateIamTokenResponse> IamTokens; + TString Identity; + + TMaybe<grpc::Status> CheckAuthorization(grpc::ServerContext* context) { + if (!Identity.empty()) { + auto[reqIdBegin, reqIdEnd] = context->client_metadata().equal_range("authorization"); + UNIT_ASSERT_C(reqIdBegin != reqIdEnd, "Authorization is expected."); + if (Identity != TStringBuf(reqIdBegin->second.cbegin(), reqIdBegin->second.cend())) { + return grpc::Status(grpc::StatusCode::UNAUTHENTICATED, + TStringBuilder() << "Access for user " << Identity << " is forbidden"); + } + } + + return Nothing(); + } + + virtual grpc::Status CreateForServiceAccount(grpc::ServerContext* context, + const yandex::cloud::priv::iam::v1::CreateIamTokenForServiceAccountRequest* request, + yandex::cloud::priv::iam::v1::CreateIamTokenResponse* response) override + { + auto status = CheckAuthorization(context); + if (status.Defined()) { + return *status; + } + + TString id = request->service_account_id(); + auto it = IamTokens.find(id); + if (it != IamTokens.end()) { + response->CopyFrom(it->second); + return grpc::Status::OK; + } else { + return grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "Iam token not found"); + } + } + +}; + diff --git a/ydb/library/testlib/service_mocks/service_account_service_mock.h b/ydb/library/testlib/service_mocks/service_account_service_mock.h new file mode 100644 index 00000000000..9ba55a1176c --- /dev/null +++ b/ydb/library/testlib/service_mocks/service_account_service_mock.h @@ -0,0 +1,65 @@ +#pragma once + +#include <ydb/public/api/client/yc_private/iam/service_account_service.grpc.pb.h> + +class TServiceAccountServiceMock : public yandex::cloud::priv::iam::v1::ServiceAccountService::Service { +public: + THashMap<TString, yandex::cloud::priv::iam::v1::ServiceAccount> ServiceAccountData; + THashMap<TString, yandex::cloud::priv::iam::v1::IamToken> IamTokens; + TString Identity; + + TMaybe<grpc::Status> CheckAuthorization(grpc::ServerContext* context) { + if (!Identity.empty()) { + auto[reqIdBegin, reqIdEnd] = context->client_metadata().equal_range("authorization"); + if (reqIdBegin == reqIdEnd) { + return grpc::Status(grpc::StatusCode::UNAUTHENTICATED, + TStringBuilder() << "Authorization data is not provided"); + } else if (Identity != TStringBuf(reqIdBegin->second.cbegin(), reqIdBegin->second.cend())) { + return grpc::Status(grpc::StatusCode::UNAUTHENTICATED, + TStringBuilder() << "Access for user " << Identity << " is forbidden"); + } + } + + return Nothing(); + } + + virtual grpc::Status Get(grpc::ServerContext* context, + const yandex::cloud::priv::iam::v1::GetServiceAccountRequest* request, + yandex::cloud::priv::iam::v1::ServiceAccount* response) override + { + auto status = CheckAuthorization(context); + if (status.Defined()) { + return *status; + } + + TString id = request->service_account_id(); + auto it = ServiceAccountData.find(id); + if (it != ServiceAccountData.end()) { + response->CopyFrom(it->second); + return grpc::Status::OK; + } else { + return grpc::Status(grpc::StatusCode::NOT_FOUND, "Not Found"); + } + } + + virtual grpc::Status IssueToken(grpc::ServerContext* context, + const yandex::cloud::priv::iam::v1::IssueTokenRequest* request, + yandex::cloud::priv::iam::v1::IamToken* response) override + { + auto status = CheckAuthorization(context); + if (status.Defined()) { + return *status; + } + + TString id = request->service_account_id(); + auto it = IamTokens.find(id); + if (it != IamTokens.end()) { + response->CopyFrom(it->second); + return grpc::Status::OK; + } else { + return grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "Iam token not found"); + } + } + +}; + diff --git a/ydb/library/testlib/service_mocks/user_account_service_mock.h b/ydb/library/testlib/service_mocks/user_account_service_mock.h new file mode 100644 index 00000000000..e4710aada9e --- /dev/null +++ b/ydb/library/testlib/service_mocks/user_account_service_mock.h @@ -0,0 +1,22 @@ +#pragma once + +#include <ydb/public/api/client/yc_private/iam/user_account_service.grpc.pb.h> + +class TUserAccountServiceMock : public yandex::cloud::priv::iam::v1::UserAccountService::Service { +public: + THashMap<TString, yandex::cloud::priv::iam::v1::UserAccount> UserAccountData; + + virtual grpc::Status Get(grpc::ServerContext*, + const yandex::cloud::priv::iam::v1::GetUserAccountRequest* request, + yandex::cloud::priv::iam::v1::UserAccount* response) override { + TString id = request->user_account_id(); + auto it = UserAccountData.find(id); + if (it != UserAccountData.end()) { + response->CopyFrom(it->second); + return grpc::Status::OK; + } else { + return grpc::Status(grpc::StatusCode::NOT_FOUND, "Not Found"); + } + } +}; + diff --git a/ydb/library/ycloud/CMakeLists.txt b/ydb/library/ycloud/CMakeLists.txt new file mode 100644 index 00000000000..eabee160c70 --- /dev/null +++ b/ydb/library/ycloud/CMakeLists.txt @@ -0,0 +1,10 @@ + +# 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(api) +add_subdirectory(impl) diff --git a/ydb/library/ycloud/api/CMakeLists.txt b/ydb/library/ycloud/api/CMakeLists.txt new file mode 100644 index 00000000000..e97a72b103a --- /dev/null +++ b/ydb/library/ycloud/api/CMakeLists.txt @@ -0,0 +1,21 @@ + +# 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(library-ycloud-api INTERFACE) +target_link_libraries(library-ycloud-api INTERFACE + contrib-libs-cxxsupp + yutil + client-yc_private-iam + client-yc_private-servicecontrol + client-yc_private-resourcemanager + cpp-actors-core + cpp-grpc-client + ydb-core-base + ydb-core-grpc_caching +) diff --git a/ydb/library/ycloud/api/access_service.h b/ydb/library/ycloud/api/access_service.h new file mode 100644 index 00000000000..67149a8e107 --- /dev/null +++ b/ydb/library/ycloud/api/access_service.h @@ -0,0 +1,33 @@ +#pragma once +#include <ydb/core/base/defs.h> +#include <ydb/core/base/events.h> +#include <ydb/public/api/client/yc_private/servicecontrol/access_service.grpc.pb.h> +#include "events.h" + +namespace NCloud { + using namespace NKikimr; + + struct TEvAccessService { + enum EEv { + // requests + EvAuthenticateRequest = EventSpaceBegin(TKikimrEvents::ES_ACCESS_SERVICE), + EvAuthorizeRequest, + + // replies + EvAuthenticateResponse = EventSpaceBegin(TKikimrEvents::ES_ACCESS_SERVICE) + 512, + EvAuthorizeResponse, + + EvEnd + }; + + static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_ACCESS_SERVICE), "expect EvEnd < EventSpaceEnd(TKikimrEvents::ES_ACCESS_SERVICE)"); + + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/servicecontrol/proto/servicecontrol/v1/access_service.proto + + struct TEvAuthenticateRequest : TEvGrpcProtoRequest<TEvAuthenticateRequest, EvAuthenticateRequest, yandex::cloud::priv::servicecontrol::v1::AuthenticateRequest> {}; + struct TEvAuthenticateResponse : TEvGrpcProtoResponse<TEvAuthenticateResponse, EvAuthenticateResponse, yandex::cloud::priv::servicecontrol::v1::AuthenticateResponse> {}; + + struct TEvAuthorizeRequest : TEvGrpcProtoRequest<TEvAuthorizeRequest, EvAuthorizeRequest, yandex::cloud::priv::servicecontrol::v1::AuthorizeRequest> {}; + struct TEvAuthorizeResponse : TEvGrpcProtoResponse<TEvAuthorizeResponse, EvAuthorizeResponse, yandex::cloud::priv::servicecontrol::v1::AuthorizeResponse> {}; + }; +} diff --git a/ydb/library/ycloud/api/events.h b/ydb/library/ycloud/api/events.h new file mode 100644 index 00000000000..c7812b70546 --- /dev/null +++ b/ydb/library/ycloud/api/events.h @@ -0,0 +1,24 @@ +#pragma once +#include <util/generic/ptr.h> +#include <util/generic/string.h> +#include <library/cpp/actors/core/actor.h> +#include <library/cpp/actors/core/event_local.h> +#include <library/cpp/grpc/client/grpc_client_low.h> + +namespace NCloud { + +template <typename TEv, ui32 TEventType, typename TProtoMessage> +struct TEvGrpcProtoRequest : NActors::TEventLocal<TEv, TEventType> { + TProtoMessage Request; + TString Token; + TString RequestId; +}; + +template <typename TEv, ui32 TEventType, typename TProtoMessage> +struct TEvGrpcProtoResponse : NActors::TEventLocal<TEv, TEventType> { + THolder<NActors::IEventHandle> Request; + TProtoMessage Response; + NGrpc::TGrpcStatus Status; +}; + +} diff --git a/ydb/library/ycloud/api/folder_service.h b/ydb/library/ycloud/api/folder_service.h new file mode 100644 index 00000000000..a1922103c5e --- /dev/null +++ b/ydb/library/ycloud/api/folder_service.h @@ -0,0 +1,29 @@ +#pragma once +#include <ydb/core/base/defs.h> +#include <ydb/core/base/events.h> +#include <ydb/public/api/client/yc_private/resourcemanager/folder_service.grpc.pb.h> +#include "events.h" + +namespace NCloud { + using namespace NKikimr; + + struct TEvFolderService { + enum EEv { + // requests + EvListFolderRequest = EventSpaceBegin(TKikimrEvents::ES_FOLDER_SERVICE), + + // replies + EvListFolderResponse = EventSpaceBegin(TKikimrEvents::ES_FOLDER_SERVICE) + 512, + + EvEnd + }; + + static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_FOLDER_SERVICE), "expect EvEnd < EventSpaceEnd(TKikimrEvents::ES_FOLDER_SERVICE)"); + + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/identity/proto/resourcemanager/v1/folder.proto + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/identity/proto/resourcemanager/v1/transitional/folder_service.proto + + struct TEvListFolderRequest : TEvGrpcProtoRequest<TEvListFolderRequest, EvListFolderRequest, yandex::cloud::priv::resourcemanager::v1::transitional::ListFoldersRequest> {}; + struct TEvListFolderResponse : TEvGrpcProtoResponse<TEvListFolderResponse, EvListFolderResponse, yandex::cloud::priv::resourcemanager::v1::transitional::ListFoldersResponse> {}; + }; +} diff --git a/ydb/library/ycloud/api/iam_token_service.h b/ydb/library/ycloud/api/iam_token_service.h new file mode 100644 index 00000000000..a525ebebbc8 --- /dev/null +++ b/ydb/library/ycloud/api/iam_token_service.h @@ -0,0 +1,30 @@ +#pragma once +#include <ydb/core/base/defs.h> +#include <ydb/core/base/events.h> +#include <ydb/public/api/client/yc_private/iam/iam_token_service.grpc.pb.h> +#include "events.h" + +namespace NCloud { + using namespace NKikimr; + + class TIamTokenService; + + struct TEvIamTokenService { + enum EEv { + // requests + EvCreateForServiceAccountRequest = EventSpaceBegin(TKikimrEvents::ES_IAM_TOKEN_SERVICE), + + // replies + EvCreateResponse = EventSpaceBegin(TKikimrEvents::ES_IAM_TOKEN_SERVICE) + 1024, + + EvEnd + }; + + static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_IAM_TOKEN_SERVICE), "expect EvEnd < EventSpaceEnd(TKikimrEvents::ES_SERVICE_ACCOUNT_SERVICE)"); + + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/bitbucket/private-api/yandex/cloud/priv/iam/v1/iam_token_service.proto + + struct TEvCreateForServiceAccountRequest : TEvGrpcProtoRequest<TEvCreateForServiceAccountRequest, EvCreateForServiceAccountRequest, yandex::cloud::priv::iam::v1::CreateIamTokenForServiceAccountRequest> {}; + struct TEvCreateResponse : TEvGrpcProtoResponse<TEvCreateResponse, EvCreateResponse, yandex::cloud::priv::iam::v1::CreateIamTokenResponse> {}; + }; +} diff --git a/ydb/library/ycloud/api/service_account_service.h b/ydb/library/ycloud/api/service_account_service.h new file mode 100644 index 00000000000..5f0f6bbb97d --- /dev/null +++ b/ydb/library/ycloud/api/service_account_service.h @@ -0,0 +1,34 @@ +#pragma once +#include <ydb/core/base/defs.h> +#include <ydb/core/base/events.h> +#include <ydb/public/api/client/yc_private/iam/service_account_service.grpc.pb.h> +#include "events.h" + +namespace NCloud { + using namespace NKikimr; + + struct TEvServiceAccountService { + enum EEv { + // requests + EvGetServiceAccountRequest = EventSpaceBegin(TKikimrEvents::ES_SERVICE_ACCOUNT_SERVICE), + EvIssueTokenRequest, + + // replies + EvGetServiceAccountResponse = EventSpaceBegin(TKikimrEvents::ES_SERVICE_ACCOUNT_SERVICE) + 1024, + EvIssueTokenResponse, + + EvEnd + }; + + static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_SERVICE_ACCOUNT_SERVICE), "expect EvEnd < EventSpaceEnd(TKikimrEvents::ES_SERVICE_ACCOUNT_SERVICE)"); + + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/bitbucket/private-api/yandex/cloud/priv/iam/v1/service_account.proto + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/bitbucket/private-api/yandex/cloud/priv/iam/v1/service_account_service.proto + + struct TEvGetServiceAccountRequest : TEvGrpcProtoRequest<TEvGetServiceAccountRequest, EvGetServiceAccountRequest, yandex::cloud::priv::iam::v1::GetServiceAccountRequest> {}; + struct TEvGetServiceAccountResponse : TEvGrpcProtoResponse<TEvGetServiceAccountResponse, EvGetServiceAccountResponse, yandex::cloud::priv::iam::v1::ServiceAccount> {}; + + struct TEvIssueTokenRequest : TEvGrpcProtoRequest<TEvIssueTokenRequest, EvIssueTokenRequest, yandex::cloud::priv::iam::v1::IssueTokenRequest> {}; + struct TEvIssueTokenResponse : TEvGrpcProtoResponse<TEvIssueTokenResponse, EvIssueTokenResponse, yandex::cloud::priv::iam::v1::IamToken> {}; + }; +} diff --git a/ydb/library/ycloud/api/user_account_service.h b/ydb/library/ycloud/api/user_account_service.h new file mode 100644 index 00000000000..59ed30b0482 --- /dev/null +++ b/ydb/library/ycloud/api/user_account_service.h @@ -0,0 +1,29 @@ +#pragma once +#include <ydb/core/base/defs.h> +#include <ydb/core/base/events.h> +#include <ydb/public/api/client/yc_private/iam/user_account_service.grpc.pb.h> +#include "events.h" + +namespace NCloud { + using namespace NKikimr; + + struct TEvUserAccountService { + enum EEv { + // requests + EvGetUserAccountRequest = EventSpaceBegin(TKikimrEvents::ES_USER_ACCOUNT_SERVICE), + + // replies + EvGetUserAccountResponse = EventSpaceBegin(TKikimrEvents::ES_USER_ACCOUNT_SERVICE) + 512, + + EvEnd + }; + + static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_USER_ACCOUNT_SERVICE), "expect EvEnd < EventSpaceEnd(TKikimrEvents::ES_USER_ACCOUNT_SERVICE)"); + + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/identity/proto/iam/v1/user_account.proto + // https://a.yandex-team.ru/arc/trunk/arcadia/cloud/identity/proto/iam/v1/user_account_service.proto + + struct TEvGetUserAccountRequest : TEvGrpcProtoRequest<TEvGetUserAccountRequest, EvGetUserAccountRequest, yandex::cloud::priv::iam::v1::GetUserAccountRequest> {}; + struct TEvGetUserAccountResponse : TEvGrpcProtoResponse<TEvGetUserAccountResponse, EvGetUserAccountResponse, yandex::cloud::priv::iam::v1::UserAccount> {}; + }; +} diff --git a/ydb/library/ycloud/impl/CMakeLists.txt b/ydb/library/ycloud/impl/CMakeLists.txt new file mode 100644 index 00000000000..09f018185e2 --- /dev/null +++ b/ydb/library/ycloud/impl/CMakeLists.txt @@ -0,0 +1,32 @@ + +# 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(ut) + +add_library(library-ycloud-impl) +target_link_libraries(library-ycloud-impl PUBLIC + contrib-libs-cxxsupp + yutil + library-ycloud-api + cpp-actors-core + cpp-digest-crc32c + cpp-grpc-client + library-cpp-json + ydb-core-base + ydb-core-grpc_services + lib-deprecated-client + lib-deprecated-kicli +) +target_sources(library-ycloud-impl PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/access_service.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/folder_service.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/folder_service_adapter.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/iam_token_service.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/service_account_service.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/user_account_service.cpp +) diff --git a/ydb/library/ycloud/impl/access_service.cpp b/ydb/library/ycloud/impl/access_service.cpp new file mode 100644 index 00000000000..fd169fb4c13 --- /dev/null +++ b/ydb/library/ycloud/impl/access_service.cpp @@ -0,0 +1,91 @@ +#include <library/cpp/actors/core/actorsystem.h> +#include <library/cpp/actors/core/actor.h> +#include <library/cpp/json/json_value.h> +#include <ydb/public/api/client/yc_private/servicecontrol/access_service.grpc.pb.h> +#include "access_service.h" +#include "grpc_service_client.h" +#include "grpc_service_cache.h" + +namespace NCloud { + +using namespace NKikimr; + +class TAccessService : public NActors::TActor<TAccessService>, TGrpcServiceClient<yandex::cloud::priv::servicecontrol::v1::AccessService> { + using TThis = TAccessService; + using TBase = NActors::TActor<TAccessService>; + + struct TAuthenticateRequest : TGrpcRequest { + static constexpr auto Request = &yandex::cloud::priv::servicecontrol::v1::AccessService::Stub::AsyncAuthenticate; + using TRequestEventType = TEvAccessService::TEvAuthenticateRequest; + using TResponseEventType = TEvAccessService::TEvAuthenticateResponse; + + static yandex::cloud::priv::servicecontrol::v1::AuthenticateRequest Obfuscate(const yandex::cloud::priv::servicecontrol::v1::AuthenticateRequest& p) { + yandex::cloud::priv::servicecontrol::v1::AuthenticateRequest r(p); + if (r.iam_token()) { + r.set_iam_token(MaskToken(r.iam_token())); + } + r.clear_iam_cookie(); + return r; + } + + static const yandex::cloud::priv::servicecontrol::v1::AuthenticateResponse& Obfuscate(const yandex::cloud::priv::servicecontrol::v1::AuthenticateResponse& p) { + return p; + } + }; + + void Handle(TEvAccessService::TEvAuthenticateRequest::TPtr& ev) { + MakeCall<TAuthenticateRequest>(std::move(ev)); + } + + struct TAuthorizeRequest : TGrpcRequest { + static constexpr auto Request = &yandex::cloud::priv::servicecontrol::v1::AccessService::Stub::AsyncAuthorize; + using TRequestEventType = TEvAccessService::TEvAuthorizeRequest; + using TResponseEventType = TEvAccessService::TEvAuthorizeResponse; + + static yandex::cloud::priv::servicecontrol::v1::AuthorizeRequest Obfuscate(const yandex::cloud::priv::servicecontrol::v1::AuthorizeRequest& p) { + yandex::cloud::priv::servicecontrol::v1::AuthorizeRequest r(p); + if (r.iam_token()) { + r.set_iam_token(MaskToken(r.iam_token())); + } + return r; + } + + static const yandex::cloud::priv::servicecontrol::v1::AuthorizeResponse& Obfuscate(const yandex::cloud::priv::servicecontrol::v1::AuthorizeResponse& p) { + return p; + } + }; + + void Handle(TEvAccessService::TEvAuthorizeRequest::TPtr& ev) { + MakeCall<TAuthorizeRequest>(std::move(ev)); + } + +public: + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::ACCESS_SERVICE_ACTOR; } + + TAccessService(const TAccessServiceSettings& settings) + : TBase(&TThis::StateWork) + , TGrpcServiceClient(settings) + {} + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext&) { + switch (ev->GetTypeRewrite()) { + hFunc(TEvAccessService::TEvAuthenticateRequest, Handle); + hFunc(TEvAccessService::TEvAuthorizeRequest, Handle); + cFunc(TEvents::TSystem::PoisonPill, PassAway); + } + } +}; + + +IActor* CreateAccessService(const TAccessServiceSettings& settings) { + return new TAccessService(settings); +} + +IActor* CreateAccessServiceWithCache(const TAccessServiceSettings& settings) { + IActor* accessService = CreateAccessService(settings); + accessService = CreateGrpcServiceCache<TEvAccessService::TEvAuthenticateRequest, TEvAccessService::TEvAuthenticateResponse>(accessService); + accessService = CreateGrpcServiceCache<TEvAccessService::TEvAuthorizeRequest, TEvAccessService::TEvAuthorizeResponse>(accessService); + return accessService; +} + +} diff --git a/ydb/library/ycloud/impl/access_service.h b/ydb/library/ycloud/impl/access_service.h new file mode 100644 index 00000000000..bdcf2b1c003 --- /dev/null +++ b/ydb/library/ycloud/impl/access_service.h @@ -0,0 +1,21 @@ +#pragma once +#include <ydb/library/ycloud/api/access_service.h> +#include "grpc_service_settings.h" + +namespace NCloud { + +using namespace NKikimr; + +struct TAccessServiceSettings : TGrpcClientSettings {}; + +IActor* CreateAccessService(const TAccessServiceSettings& settings); + +inline IActor* CreateAccessService(const TString& endpoint) { + TAccessServiceSettings settings; + settings.Endpoint = endpoint; + return CreateAccessService(settings); +} + +IActor* CreateAccessServiceWithCache(const TAccessServiceSettings& settings); // for compatibility with older code + +} diff --git a/ydb/library/ycloud/impl/access_service_ut.cpp b/ydb/library/ycloud/impl/access_service_ut.cpp new file mode 100644 index 00000000000..7ebf90fd29f --- /dev/null +++ b/ydb/library/ycloud/impl/access_service_ut.cpp @@ -0,0 +1,111 @@ +#include <library/cpp/actors/core/event.h> +#include <library/cpp/actors/core/event_local.h> +#include <ydb/core/testlib/test_client.h> +#include <ydb/library/testlib/service_mocks/access_service_mock.h> +#include <ydb/core/grpc_services/grpc_helper.h> +#include <library/cpp/grpc/server/grpc_server.h> +#include <ydb/public/lib/deprecated/kicli/kicli.h> +#include <library/cpp/testing/unittest/registar.h> +#include <library/cpp/testing/unittest/tests_data.h> +#include <util/string/builder.h> +#include "access_service.h" + +using namespace NKikimr; +using namespace Tests; + +struct TTestSetup { + TPortManager PortManager; + ui16 KikimrPort; + ui16 ServicePort; + + // Kikimr + THolder<TServer> Server; + THolder<TClient> Client; + THolder<NClient::TKikimr> Kikimr; + TActorId EdgeActor; + IActor* AccessServiceActor = nullptr; + + // Access service + TAccessServiceMock AccessServiceMock; + std::unique_ptr<grpc::Server> AccessServer; + + TTestSetup() + : KikimrPort(PortManager.GetPort(2134)) + , ServicePort(PortManager.GetPort(4286)) + { + StartKikimr(); + StartAccessService(); + } + + TTestActorRuntime* GetRuntime() { + return Server->GetRuntime(); + } + + void StartKikimr() { + NKikimrProto::TAuthConfig authConfig; + auto settings = TServerSettings(KikimrPort, authConfig); + settings.SetDomainName("Root"); + Server = MakeHolder<TServer>(settings); + Server->GetRuntime()->SetLogPriority(NKikimrServices::GRPC_CLIENT, NLog::PRI_DEBUG); + Client = MakeHolder<TClient>(settings); + Kikimr = MakeHolder<NClient::TKikimr>(Client->GetClientConfig()); + Client->InitRootScheme(); + EdgeActor = GetRuntime()->AllocateEdgeActor(); + + //AccessServiceActor = NCloud::CreateAccessService("localhost:" + ToString(ServicePort)); + NCloud::TAccessServiceSettings sets; + sets.Endpoint = "localhost:" + ToString(ServicePort); + AccessServiceActor = NCloud::CreateAccessServiceWithCache(sets); + GetRuntime()->Register(AccessServiceActor); + } + + void StartAccessService() { + grpc::ServerBuilder builder; + builder.AddListeningPort("[::]:" + ToString(ServicePort), grpc::InsecureServerCredentials()).RegisterService(&AccessServiceMock); + AccessServer = builder.BuildAndStart(); + } +}; + +Y_UNIT_TEST_SUITE(TAccessServiceTest) { + Y_UNIT_TEST(Authenticate) { + TTestSetup setup; + + TAutoPtr<IEventHandle> handle; + setup.AccessServiceMock.AuthenticateData["good1"].Response.mutable_subject()->mutable_user_account()->set_id("1234"); + + // check for not found + auto request = MakeHolder<NCloud::TEvAccessService::TEvAuthenticateRequest>(); + request->Request.set_iam_token("bad1"); + setup.GetRuntime()->Send(new IEventHandle(setup.AccessServiceActor->SelfId(), setup.EdgeActor, request.Release())); + auto result = setup.GetRuntime()->GrabEdgeEvent<NCloud::TEvAccessService::TEvAuthenticateResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT_VALUES_EQUAL(result->Status.Msg, "Permission Denied"); + + // check for found + request = MakeHolder<NCloud::TEvAccessService::TEvAuthenticateRequest>(); + request->Request.set_iam_token("good1"); + setup.GetRuntime()->Send(new IEventHandle(setup.AccessServiceActor->SelfId(), setup.EdgeActor, request.Release())); + result = setup.GetRuntime()->GrabEdgeEvent<NCloud::TEvAccessService::TEvAuthenticateResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT(result->Status.Ok()); + UNIT_ASSERT_VALUES_EQUAL(result->Response.subject().user_account().id(), "1234"); + } + + Y_UNIT_TEST(PassRequestId) { + TTestSetup setup; + + TAutoPtr<IEventHandle> handle; + auto& req = setup.AccessServiceMock.AuthenticateData["token"]; + req.Response.mutable_subject()->mutable_user_account()->set_id("1234"); + req.RequireRequestId = true; + + // check for not found + auto request = MakeHolder<NCloud::TEvAccessService::TEvAuthenticateRequest>(); + request->Request.set_iam_token("token"); + request->RequestId = "trololo"; + setup.GetRuntime()->Send(new IEventHandle(setup.AccessServiceActor->SelfId(), setup.EdgeActor, request.Release())); + auto result = setup.GetRuntime()->GrabEdgeEvent<NCloud::TEvAccessService::TEvAuthenticateResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT(result->Status.Ok()); + } +} diff --git a/ydb/library/ycloud/impl/folder_service.cpp b/ydb/library/ycloud/impl/folder_service.cpp new file mode 100644 index 00000000000..2af7c005f0c --- /dev/null +++ b/ydb/library/ycloud/impl/folder_service.cpp @@ -0,0 +1,53 @@ +#include <library/cpp/actors/core/actorsystem.h> +#include <library/cpp/actors/core/actor.h> +#include <ydb/public/api/client/yc_private/resourcemanager/folder_service.grpc.pb.h> +#include "folder_service.h" +#include "grpc_service_client.h" +#include "grpc_service_cache.h" + +namespace NCloud { + +using namespace NKikimr; + +class TFolderService : public NActors::TActor<TFolderService>, TGrpcServiceClient<yandex::cloud::priv::resourcemanager::v1::transitional::FolderService> { + using TThis = TFolderService; + using TBase = NActors::TActor<TFolderService>; + + struct TListFolderRequest : TGrpcRequest { + static constexpr auto Request = &yandex::cloud::priv::resourcemanager::v1::transitional::FolderService::Stub::AsyncList; + using TRequestEventType = TEvFolderService::TEvListFolderRequest; + using TResponseEventType = TEvFolderService::TEvListFolderResponse; + }; + + void Handle(TEvFolderService::TEvListFolderRequest::TPtr& ev) { + MakeCall<TListFolderRequest>(std::move(ev)); + } + +public: + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::FOLDER_SERVICE_ACTOR; } + + TFolderService(const TFolderServiceSettings& settings) + : TBase(&TThis::StateWork) + , TGrpcServiceClient(settings) + {} + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext&) { + switch (ev->GetTypeRewrite()) { + hFunc(TEvFolderService::TEvListFolderRequest, Handle); + cFunc(TEvents::TSystem::PoisonPill, PassAway); + } + } +}; + + +IActor* CreateFolderService(const TFolderServiceSettings& settings) { + return new TFolderService(settings); +} + +IActor* CreateFolderServiceWithCache(const TFolderServiceSettings& settings) { + IActor* folderService = CreateFolderService(settings); + folderService = CreateGrpcServiceCache<TEvFolderService::TEvListFolderRequest, TEvFolderService::TEvListFolderResponse>(folderService); + return folderService; +} + +} diff --git a/ydb/library/ycloud/impl/folder_service.h b/ydb/library/ycloud/impl/folder_service.h new file mode 100644 index 00000000000..9836b82d86c --- /dev/null +++ b/ydb/library/ycloud/impl/folder_service.h @@ -0,0 +1,21 @@ +#pragma once +#include <ydb/library/ycloud/api/folder_service.h> +#include "grpc_service_settings.h" + +namespace NCloud { + +using namespace NKikimr; + +struct TFolderServiceSettings : TGrpcClientSettings {}; + +IActor* CreateFolderService(const TFolderServiceSettings& settings); + +inline IActor* CreateFolderService(const TString& endpoint) { + TFolderServiceSettings settings; + settings.Endpoint = endpoint; + return CreateFolderService(settings); +} + +IActor* CreateFolderServiceWithCache(const TFolderServiceSettings& settings); // for compatibility with older code + +} diff --git a/ydb/library/ycloud/impl/folder_service_adapter.cpp b/ydb/library/ycloud/impl/folder_service_adapter.cpp new file mode 100644 index 00000000000..87c5b59e8de --- /dev/null +++ b/ydb/library/ycloud/impl/folder_service_adapter.cpp @@ -0,0 +1,114 @@ +#include <ydb/library/folder_service/folder_service.h> +#include <ydb/library/folder_service/events.h> +#include <ydb/library/folder_service/mock/mock_folder_service.h> + +#include <ydb/library/ycloud/impl/folder_service.h> + +#include <library/cpp/actors/core/actor_bootstrapped.h> +#include <library/cpp/actors/core/hfunc.h> + +#include <util/stream/file.h> + +namespace { + +class TFolderServiceRequestHandler : public NActors::TActor<TFolderServiceRequestHandler> { + using TThis = TFolderServiceRequestHandler; + using TBase = NActors::TActor<TFolderServiceRequestHandler>; + + NActors::TActorId Sender; + NActors::TActorId Delegatee; + + void Handle(NKikimr::NFolderService::TEvFolderService::TEvGetFolderRequest::TPtr& ev) { + auto request = std::make_unique<NCloud::TEvFolderService::TEvListFolderRequest>(); + request->Request.set_id(ev->Get()->Request.folder_id()); + request->Token = ev->Get()->Token; + request->RequestId = ev->Get()->RequestId; + Send(Delegatee, request.release()); + } + + void Handle(NCloud::TEvFolderService::TEvListFolderResponse::TPtr& ev) { + auto responseEvent = std::make_unique<NKikimr::NFolderService::TEvFolderService::TEvGetFolderResponse>(); + + const auto& status = ev->Get()->Status; + responseEvent->Status = status; + + if (status.Ok()) { + const auto& response = ev->Get()->Response; + if (response.result_size() > 0) { + Y_VERIFY(responseEvent->Response.mutable_folder()->ParseFromString(response.result(0).SerializeAsString())); + } + } + + Send(Sender, responseEvent.release()); + PassAway(); + } + + void Handle(NActors::TEvents::TEvUndelivered::TPtr&) { + Y_FAIL("Can't deliver local message"); + } + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext&) { + switch (ev->GetTypeRewrite()) { + hFunc(NKikimr::NFolderService::TEvFolderService::TEvGetFolderRequest, Handle); + hFunc(NCloud::TEvFolderService::TEvListFolderResponse, Handle); + hFunc(NActors::TEvents::TEvUndelivered, Handle); + cFunc(NActors::TEvents::TSystem::PoisonPill, PassAway); + } + } + +public: + TFolderServiceRequestHandler(NActors::TActorId sender, NActors::TActorId delegatee) + : TBase(&TThis::StateWork) + , Sender(sender) + , Delegatee(delegatee) { + } +}; +}; // namespace + +namespace NKikimr::NFolderService { + +class TFolderServiceAdapter : public NActors::TActorBootstrapped<TFolderServiceAdapter> { + using TThis = TFolderServiceAdapter; + using TBase = NActors::TActor<TFolderServiceAdapter>; + + NKikimrProto::NFolderService::TFolderServiceConfig Config; + NActors::TActorId Delegatee; + + void Handle(::NKikimr::NFolderService::TEvFolderService::TEvGetFolderRequest::TPtr& ev) { + auto actor = Register(new TFolderServiceRequestHandler(ev->Sender, Delegatee)); + Send(actor, ev->Release().Release()); + } + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext&) { + switch (ev->GetTypeRewrite()) { + hFunc(::NKikimr::NFolderService::TEvFolderService::TEvGetFolderRequest, Handle) + cFunc(NActors::TEvents::TSystem::PoisonPill, PassAway) + } + } + +public: + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { + return NKikimrServices::TActivity::FOLDER_SERVICE_ACTOR; + } + + void Bootstrap() { + NCloud::TFolderServiceSettings settings; + settings.Endpoint = Config.GetEndpoint(); + settings.CertificateRootCA = TUnbufferedFileInput(Config.GetPathToRootCA()).ReadAll(); + Delegatee = Register(NCloud::CreateFolderServiceWithCache(settings)); + Become(&TThis::StateWork); + } + + explicit TFolderServiceAdapter(const NKikimrProto::NFolderService::TFolderServiceConfig& config) + : Config(config) { + } +}; + +NActors::IActor* CreateFolderServiceActor(const NKikimrProto::NFolderService::TFolderServiceConfig& config) { + if (config.GetEnable()) { + return new NKikimr::NFolderService::TFolderServiceAdapter(config); + } else { + return NKikimr::NFolderService::CreateMockFolderServiceActor(config); + } +} +} // namespace NKikimr::NFolderService diff --git a/ydb/library/ycloud/impl/folder_service_ut.cpp b/ydb/library/ycloud/impl/folder_service_ut.cpp new file mode 100644 index 00000000000..3c1261e3297 --- /dev/null +++ b/ydb/library/ycloud/impl/folder_service_ut.cpp @@ -0,0 +1,80 @@ +#include <library/cpp/actors/core/event.h> +#include <library/cpp/actors/core/event_local.h> +#include <ydb/core/testlib/test_client.h> +#include <ydb/library/testlib/service_mocks/folder_service_mock.h> +#include <ydb/core/grpc_services/grpc_helper.h> +#include <library/cpp/grpc/server/grpc_server.h> +#include <ydb/public/lib/deprecated/kicli/kicli.h> +#include <library/cpp/testing/unittest/registar.h> +#include <library/cpp/testing/unittest/tests_data.h> +#include <library/cpp/retry/retry.h> +#include <util/string/builder.h> +#include "folder_service.h" + +Y_UNIT_TEST_SUITE(TFolderServiceTest) { + Y_UNIT_TEST(ListFolder) { + using namespace NKikimr; + using namespace Tests; + + TPortManager tp; + // Kikimr + ui16 kikimrPort = tp.GetPort(2134); + NKikimrProto::TAuthConfig authConfig; + auto settings = TServerSettings(kikimrPort, authConfig); + settings.SetDomainName("Root"); + TServer server(settings); + TClient client(settings); + NClient::TKikimr kikimr(client.GetClientConfig()); + client.InitRootScheme(); + + TTestActorRuntime* runtime = server.GetRuntime(); + TActorId sender = runtime->AllocateEdgeActor(); + TAutoPtr<IEventHandle> handle; + TString badFolderId = "yrm4564"; + TString goodFolderId = "yrm4566"; + TString cloudId = "cloud9999"; + + // Folder Service + ui16 servicePort = tp.GetPort(4284); + IActor* folderService = NCloud::CreateFolderService("localhost:" + ToString(servicePort)); + runtime->Register(folderService); + auto request = MakeHolder<NCloud::TEvFolderService::TEvListFolderRequest>(); + request->Request.set_id("xxx"); + runtime->Send(new IEventHandle(folderService->SelfId(), sender, request.Release())); + auto result = runtime->GrabEdgeEvent<NCloud::TEvFolderService::TEvListFolderResponse>(handle); + UNIT_ASSERT(result); // error because no service is listening + UNIT_ASSERT_EQUAL(result->Status.Msg, "failed to connect to all addresses"); + + // Folder Service Mock + TFolderServiceMock folderServiceMock; + grpc::ServerBuilder builder; + folderServiceMock.Folders[goodFolderId].set_cloud_id(cloudId); + builder.AddListeningPort("[::]:" + ToString(servicePort), grpc::InsecureServerCredentials()).RegisterService(&folderServiceMock); + std::unique_ptr<grpc::Server> folderServer(builder.BuildAndStart()); + + // check for not found + // retry if there is TRANSIENT_FAILURE + auto sendEvent = [&] { + auto request = MakeHolder<NCloud::TEvFolderService::TEvListFolderRequest>(); + request->Request.set_id(badFolderId); + runtime->Send(new IEventHandle(folderService->SelfId(), sender, request.Release())); + result = runtime->GrabEdgeEvent<NCloud::TEvFolderService::TEvListFolderResponse>(handle); + return result->Status.GRpcStatusCode != 14; + }; + DoWithRetryOnRetCode(sendEvent, TRetryOptions{}); + Cerr << result->Status.Msg << " " << result->Status.GRpcStatusCode << "\n"; + + UNIT_ASSERT(result); + UNIT_ASSERT(result->Status.Msg == "Not Found"); + // || "channel is in state TRANSIENT_FAILURE" + + // check for found + request = MakeHolder<NCloud::TEvFolderService::TEvListFolderRequest>(); + request->Request.set_id(goodFolderId); + runtime->Send(new IEventHandle(folderService->SelfId(), sender, request.Release())); + result = runtime->GrabEdgeEvent<NCloud::TEvFolderService::TEvListFolderResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT(result->Status.Ok()); + UNIT_ASSERT_EQUAL(result->Response.result(0).cloud_id(), cloudId); + } +} diff --git a/ydb/library/ycloud/impl/grpc_service_cache.h b/ydb/library/ycloud/impl/grpc_service_cache.h new file mode 100644 index 00000000000..70eb9d5c2b3 --- /dev/null +++ b/ydb/library/ycloud/impl/grpc_service_cache.h @@ -0,0 +1,167 @@ +#pragma once + +#include <variant> +#include <library/cpp/actors/core/actorsystem.h> +#include <library/cpp/actors/core/actor_bootstrapped.h> +#include <library/cpp/actors/core/mailbox.h> +#include <ydb/core/util/simple_cache.h> + +namespace NCloud { + +template <typename TEventRequestType, typename TEventResponseType> +class TGrpcServiceCache : public NActors::TActorBootstrapped<TGrpcServiceCache<TEventRequestType, TEventResponseType>> { + using TThis = TGrpcServiceCache<TEventRequestType, TEventResponseType>; + using TBase = NActors::TActorBootstrapped<TThis>; + TDuration SuccessLifeTime = TDuration::Minutes(1); + TDuration ErrorLifeTime = TDuration::Seconds(10); + + struct TCacheRecord { + TInstant UpdateTimestamp; + THolder<TEventResponseType> Response; + std::deque<typename TEventRequestType::TPtr> Waiters; + + bool IsSafeToRelease() { + return Waiters.empty(); + } + }; + + std::variant<NActors::TActorId, NActors::IActor*> UnderlyingActor; + NKikimr::TNotSoSimpleCache<TString, TCacheRecord> Cache; + + NActors::TActorId GetUnderlyingActor() { + return std::get<NActors::TActorId>(UnderlyingActor); + } + + static TString GetCacheKey(const TEventRequestType* request) { + return request->Token + request->Request.ShortDebugString(); + } + + bool IsTemporaryErrorStatus(const TCacheRecord& record) const { + if (!record.Response) { + return false; + } + return record.Response->Status.InternalError + || record.Response->Status.GRpcStatusCode == grpc::StatusCode::UNKNOWN + || record.Response->Status.GRpcStatusCode == grpc::StatusCode::DEADLINE_EXCEEDED + || record.Response->Status.GRpcStatusCode == grpc::StatusCode::INTERNAL + || record.Response->Status.GRpcStatusCode == grpc::StatusCode::UNAVAILABLE; + } + + bool IsCacheRecordValid(const TCacheRecord& record, TInstant now = NActors::TActivationContext::Now()) const { + if (record.Response && record.UpdateTimestamp) { + TDuration lifeTime = now - record.UpdateTimestamp; + if (!record.Response->Status.Ok()) { + return !IsTemporaryErrorStatus(record) && (lifeTime < ErrorLifeTime); + } else { + return lifeTime < SuccessLifeTime; + } + } else { + return false; + } + } + + void SendReply(typename TEventRequestType::TPtr& ev, TCacheRecord* cacheRecord) { + NActors::TActorId sender = ev->Sender; + THolder<TEventResponseType> response = MakeHolder<TEventResponseType>(); + if (ev->HasEvent()) { + response->Request = ev; + } else { + response->Request = std::move(cacheRecord->Response->Request); + } + response->Response = cacheRecord->Response->Response; + response->Status = cacheRecord->Response->Status; + TBase::Send(sender, response.Release()); + } + + void Handle(typename TEventRequestType::TPtr& ev) { + TString cacheKey = GetCacheKey(ev->Get()); + TCacheRecord* cacheRecord = Cache.FindPtr(cacheKey); + if (cacheRecord) { + if (IsCacheRecordValid(*cacheRecord)) { + SendReply(ev, cacheRecord); + return; + } + } else { + cacheRecord = &Cache.Update(cacheKey); + } + if (cacheRecord->Waiters.empty()) { + THolder<TEventRequestType> request = ev->Release(); + TBase::Send(GetUnderlyingActor(), request.Release()); + } + cacheRecord->Waiters.emplace_back(ev); + } + + void Handle(typename TEventResponseType::TPtr& ev) { + TEventRequestType* request = ev->Get()->Request->template Get<TEventRequestType>(); + TString cacheKey = GetCacheKey(request); + TCacheRecord* cacheRecord = Cache.FindPtr(cacheKey); + if (cacheRecord) { + cacheRecord->Response = ev->Release(); + cacheRecord->UpdateTimestamp = NActors::TActivationContext::Now(); + for (typename TEventRequestType::TPtr& waiter : cacheRecord->Waiters) { + SendReply(waiter, cacheRecord); + } + cacheRecord->Waiters.clear(); + } else { + LOG_ERROR_S(*NActors::TlsActivationContext, NKikimrServices::GRPC_CLIENT, "Couldn't find cache record for request"); + } + } + + void PassAway() { + TBase::Send(GetUnderlyingActor(), new TEvents::TEvPoison()); + TBase::PassAway(); + } + +public: + void Bootstrap() { + if (std::holds_alternative<NActors::IActor*>(UnderlyingActor)) { + // we register underlying actor with the same pool and mailbox type + auto& ctx = NActors::TlsActivationContext; + const auto& mailbox = ctx->Mailbox; + UnderlyingActor = ctx->Register(std::get<NActors::IActor*>(UnderlyingActor), TBase::SelfId(), static_cast<TMailboxType::EType>(mailbox.Type)); + } + TBase::Become(&TThis::StateWork); + } + + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::ACTOR_SERVICE_CACHE; } + + TGrpcServiceCache(const std::variant<NActors::TActorId, NActors::IActor*>& underlyingActor, + size_t grpcCacheSize = 1024, + TDuration grpcCacheSuccessLifeTime = TDuration::Minutes(1), + TDuration grpcCacheErrorLifeTime = TDuration::Seconds(10)) + : UnderlyingActor(underlyingActor) + { + Cache.MaxSize = grpcCacheSize; + SuccessLifeTime = grpcCacheSuccessLifeTime; + ErrorLifeTime = grpcCacheErrorLifeTime; + } + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext& ctx) { + switch (ev->GetTypeRewrite()) { + hFunc(TEventRequestType, Handle); + hFunc(TEventResponseType, Handle); + cFunc(TEvents::TSystem::Poison, PassAway); + default: + ctx.Send(ev->Forward(GetUnderlyingActor())); + break; + } + } +}; + +template <typename TEventRequestType, typename TEventResponseType> +inline IActor* CreateGrpcServiceCache(const NActors::TActorId& underlyingActor, + size_t grpcCacheSize = 1024, + TDuration grpcCacheSuccessLifeTime = TDuration::Minutes(1), + TDuration grpcCacheErrorLifeTime = TDuration::Seconds(10)) { + return new TGrpcServiceCache<TEventRequestType, TEventResponseType>(underlyingActor, grpcCacheSize, grpcCacheSuccessLifeTime, grpcCacheErrorLifeTime); +} + +template <typename TEventRequestType, typename TEventResponseType> +inline IActor* CreateGrpcServiceCache(NActors::IActor* underlyingActor, + size_t grpcCacheSize = 1024, + TDuration grpcCacheSuccessLifeTime = TDuration::Minutes(1), + TDuration grpcCacheErrorLifeTime = TDuration::Seconds(10)) { + return new TGrpcServiceCache<TEventRequestType, TEventResponseType>(underlyingActor, grpcCacheSize, grpcCacheSuccessLifeTime, grpcCacheErrorLifeTime); +} + +} diff --git a/ydb/library/ycloud/impl/grpc_service_client.h b/ydb/library/ycloud/impl/grpc_service_client.h new file mode 100644 index 00000000000..c89515d8654 --- /dev/null +++ b/ydb/library/ycloud/impl/grpc_service_client.h @@ -0,0 +1,126 @@ +#pragma once +#include <library/cpp/actors/core/actorsystem.h> +#include <library/cpp/actors/core/log.h> +#include <library/cpp/actors/core/actor_bootstrapped.h> +#include <library/cpp/grpc/client/grpc_client_low.h> +#include <library/cpp/digest/crc32c/crc32c.h> +#include "grpc_service_settings.h" + +#define BLOG_GRPC_D(stream) LOG_DEBUG_S(*NActors::TlsActivationContext, NKikimrServices::GRPC_CLIENT, stream) +#define BLOG_GRPC_DC(context, stream) LOG_DEBUG_S(context, NKikimrServices::GRPC_CLIENT, stream) + +inline IOutputStream& operator <<(IOutputStream& out, const NGrpc::TGrpcStatus& status) { + return out << status.GRpcStatusCode << " " << status.Msg; +} + +template <typename TGrpcService> +class TGrpcServiceClient { + using TServiceConnection = NGrpc::TServiceConnection<TGrpcService>; + + NGrpc::TGRpcClientConfig Config; + NGrpc::TGRpcClientLow Client; + std::unique_ptr<TServiceConnection> Connection; + + TString Prefix(const TString& requestId = {}) const { + if (requestId) { + return Sprintf("[%08lx]{%s} ", (ptrdiff_t)this, requestId.c_str()); + } else { + return Sprintf("[%08lx] ", (ptrdiff_t)this); + } + } + + static TString Trim(const TString& line) { + if (line.size() > 512) { + return line.substr(0, 512) + "...(truncated)"; + } + return line; + } + + template <typename TProtoMessageType> + static TString Trim(const TProtoMessageType& message) { + TStringBuilder log; + log << message.GetDescriptor()->name() << " { " << Trim(message.ShortDebugString()) << " }"; + return log; + } + +public: + static TString MaskToken(const TString& token) { + TStringBuilder mask; + if (token.size() >= 16) { + mask << token.substr(0, 4); + mask << "****"; + mask << token.substr(token.size() - 4, 4); + } else { + mask << "****"; + } + mask << " ("; + mask << Sprintf("%08X", Crc32c(token.data(), token.size())); + mask << ")"; + return mask; + } + + static constexpr TDuration DEFAULT_TIMEOUT = TDuration::Seconds(10); + + struct TGrpcRequest { + static const google::protobuf::Message& Obfuscate(const google::protobuf::Message& p) { + return p; + } + }; + + template <typename TCallType> + void MakeCall(typename TCallType::TRequestEventType::TPtr ev) { + using TRequestType = decltype(typename TCallType::TRequestEventType().Request); + using TResponseType = decltype(typename TCallType::TResponseEventType().Response); + const auto& requestId = ev->Get()->RequestId; + if (!Connection) { + BLOG_GRPC_D(Prefix(requestId) << "Connect to " + << ((Config.EnableSsl || !Config.SslCaCert.empty()) ? "grpcs://" : "grpc://") + << Config.Locator); + Connection = Client.CreateGRpcServiceConnection<TGrpcService>(Config); + } + + const TRequestType& request = ev->Get()->Request; + NGrpc::TCallMeta meta; + meta.Timeout = Config.Timeout; + if (const auto& token = ev->Get()->Token) { + meta.Aux.push_back({"authorization", "Bearer " + token}); + } + if (requestId) { + meta.Aux.push_back({"x-request-id", requestId}); + } + + NGrpc::TResponseCallback<TResponseType> callback = + [actorSystem = NActors::TActivationContext::ActorSystem(), prefix = Prefix(requestId), request = ev](NGrpc::TGrpcStatus&& status, TResponseType&& response) -> void { + if (status.Ok()) { + BLOG_GRPC_DC(*actorSystem, prefix << "Response " << Trim(TCallType::Obfuscate(response))); + } else { + BLOG_GRPC_DC(*actorSystem, prefix << "Status " << status); + } + auto respEv = MakeHolder<typename TCallType::TResponseEventType>(); + respEv->Request = request; + respEv->Status = status; + respEv->Response = response; + actorSystem->Send(respEv->Request->Sender, respEv.Release()); + }; + + BLOG_GRPC_D(Prefix(requestId) << "Request " << Trim(TCallType::Obfuscate(request))); + Connection->DoRequest(request, std::move(callback), TCallType::Request, meta); + } + + static NGrpc::TGRpcClientConfig InitGrpcConfig(const NCloud::TGrpcClientSettings& settings) { + NGrpc::TGRpcClientConfig config(settings.Endpoint, DEFAULT_TIMEOUT, DEFAULT_GRPC_MESSAGE_SIZE_LIMIT, 0, settings.CertificateRootCA); + config.EnableSsl = settings.EnableSsl; + config.IntChannelParams[GRPC_ARG_KEEPALIVE_TIME_MS] = settings.GrpcKeepAliveTimeMs; + config.IntChannelParams[GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = settings.GrpcKeepAliveTimeoutMs; + config.IntChannelParams[GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS] = 1; + config.IntChannelParams[GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA] = 0; + config.IntChannelParams[GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS] = settings.GrpcKeepAlivePingInterval; + config.IntChannelParams[GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS] = settings.GrpcKeepAlivePingInterval; + return config; + } + + TGrpcServiceClient(const NCloud::TGrpcClientSettings& settings) + : Config(InitGrpcConfig(settings)) + {} +}; + diff --git a/ydb/library/ycloud/impl/grpc_service_settings.h b/ydb/library/ycloud/impl/grpc_service_settings.h new file mode 100644 index 00000000000..07984aaa503 --- /dev/null +++ b/ydb/library/ycloud/impl/grpc_service_settings.h @@ -0,0 +1,14 @@ +#pragma once + +namespace NCloud { + +struct TGrpcClientSettings { + TString Endpoint; + TString CertificateRootCA; // root CA certificate PEM/x509 + ui32 GrpcKeepAliveTimeMs = 10000; + ui32 GrpcKeepAliveTimeoutMs = 1000; + ui32 GrpcKeepAlivePingInterval = 5000; + bool EnableSsl = false; +}; + +} diff --git a/ydb/library/ycloud/impl/iam_token_service.cpp b/ydb/library/ycloud/impl/iam_token_service.cpp new file mode 100644 index 00000000000..4df7c7b0368 --- /dev/null +++ b/ydb/library/ycloud/impl/iam_token_service.cpp @@ -0,0 +1,53 @@ +#include <library/cpp/actors/core/actorsystem.h> +#include <library/cpp/actors/core/actor.h> +#include <ydb/public/api/client/yc_private/iam/iam_token_service.grpc.pb.h> +#include "iam_token_service.h" +#include "grpc_service_client.h" +#include "grpc_service_cache.h" + +namespace NCloud { + +using namespace NKikimr; + +class TIamTokenService : public NActors::TActor<TIamTokenService>, TGrpcServiceClient<yandex::cloud::priv::iam::v1::IamTokenService> { + using TThis = TIamTokenService; + using TBase = NActors::TActor<TIamTokenService>; + + struct TCreateIamTokenForServiceAccountRequest : TGrpcRequest { + static constexpr auto Request = &yandex::cloud::priv::iam::v1::IamTokenService::Stub::AsyncCreateForServiceAccount; + using TRequestEventType = TEvIamTokenService::TEvCreateForServiceAccountRequest; + using TResponseEventType = TEvIamTokenService::TEvCreateResponse; + }; + + void Handle(TEvIamTokenService::TEvCreateForServiceAccountRequest::TPtr& ev) { + MakeCall<TCreateIamTokenForServiceAccountRequest>(std::move(ev)); + } + +public: + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::IAM_TOKEN_SERVICE_ACTOR; } + + TIamTokenService(const TIamTokenServiceSettings& settings) + : TBase(&TThis::StateWork) + , TGrpcServiceClient(settings) + {} + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext&) { + switch (ev->GetTypeRewrite()) { + hFunc(TEvIamTokenService::TEvCreateForServiceAccountRequest, Handle); + cFunc(TEvents::TSystem::PoisonPill, PassAway); + } + } +}; + + +IActor* CreateIamTokenService(const TIamTokenServiceSettings& settings) { + return new TIamTokenService(settings); +} + +IActor* CreateIamTokenServiceWithCache(const TIamTokenServiceSettings& settings) { + IActor* iamTokenService = CreateIamTokenService(settings); + iamTokenService = CreateGrpcServiceCache<TEvIamTokenService::TEvCreateForServiceAccountRequest, TEvIamTokenService::TEvCreateResponse>(iamTokenService); + return iamTokenService; +} + +} diff --git a/ydb/library/ycloud/impl/iam_token_service.h b/ydb/library/ycloud/impl/iam_token_service.h new file mode 100644 index 00000000000..758c0232167 --- /dev/null +++ b/ydb/library/ycloud/impl/iam_token_service.h @@ -0,0 +1,21 @@ +#pragma once +#include <ydb/library/ycloud/api/iam_token_service.h> +#include "grpc_service_settings.h" + +namespace NCloud { + +using namespace NKikimr; + +struct TIamTokenServiceSettings : TGrpcClientSettings {}; + +IActor* CreateIamTokenService(const TIamTokenServiceSettings& settings); + +inline IActor* CreateIamTokenService(const TString& endpoint) { + TIamTokenServiceSettings settings; + settings.Endpoint = endpoint; + return CreateIamTokenService(settings); +} + +IActor* CreateIamTokenServiceWithCache(const TIamTokenServiceSettings& settings); // for compatibility with older code + +} diff --git a/ydb/library/ycloud/impl/service_account_service.cpp b/ydb/library/ycloud/impl/service_account_service.cpp new file mode 100644 index 00000000000..1571c1bcb6e --- /dev/null +++ b/ydb/library/ycloud/impl/service_account_service.cpp @@ -0,0 +1,69 @@ +#include <library/cpp/actors/core/actorsystem.h> +#include <library/cpp/actors/core/actor.h> +#include <ydb/public/api/client/yc_private/iam/service_account_service.grpc.pb.h> +#include "service_account_service.h" +#include "grpc_service_client.h" + +namespace NCloud { + +using namespace NKikimr; + +class TServiceAccountService : public NActors::TActor<TServiceAccountService>, TGrpcServiceClient<yandex::cloud::priv::iam::v1::ServiceAccountService> { + using TThis = TServiceAccountService; + using TBase = NActors::TActor<TServiceAccountService>; + + struct TGetServiceAccountRequest : TGrpcRequest { + static constexpr auto Request = &yandex::cloud::priv::iam::v1::ServiceAccountService::Stub::AsyncGet; + using TRequestEventType = TEvServiceAccountService::TEvGetServiceAccountRequest; + using TResponseEventType = TEvServiceAccountService::TEvGetServiceAccountResponse; + }; + + void Handle(TEvServiceAccountService::TEvGetServiceAccountRequest::TPtr& ev) { + MakeCall<TGetServiceAccountRequest>(std::move(ev)); + } + + struct TIssueTokenRequest : TGrpcRequest { + static constexpr auto Request = &yandex::cloud::priv::iam::v1::ServiceAccountService::Stub::AsyncIssueToken; + using TRequestEventType = TEvServiceAccountService::TEvIssueTokenRequest; + using TResponseEventType = TEvServiceAccountService::TEvIssueTokenResponse; + + static const yandex::cloud::priv::iam::v1::IssueTokenRequest& Obfuscate(const yandex::cloud::priv::iam::v1::IssueTokenRequest& p) { + return p; + } + + static yandex::cloud::priv::iam::v1::IamToken Obfuscate(const yandex::cloud::priv::iam::v1::IamToken& p) { + yandex::cloud::priv::iam::v1::IamToken r(p); + if (r.iam_token()) { + r.set_iam_token(MaskToken(r.iam_token())); + } + return r; + } + }; + + void Handle(TEvServiceAccountService::TEvIssueTokenRequest::TPtr& ev) { + MakeCall<TIssueTokenRequest>(std::move(ev)); + } + +public: + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::SERVICE_ACCOUNT_SERVICE_ACTOR; } + + TServiceAccountService(const TServiceAccountServiceSettings& settings) + : TBase(&TThis::StateWork) + , TGrpcServiceClient(settings) + {} + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext&) { + switch (ev->GetTypeRewrite()) { + hFunc(TEvServiceAccountService::TEvGetServiceAccountRequest, Handle); + hFunc(TEvServiceAccountService::TEvIssueTokenRequest, Handle); + cFunc(TEvents::TSystem::PoisonPill, PassAway); + } + } +}; + + +IActor* CreateServiceAccountService(const TServiceAccountServiceSettings& settings) { + return new TServiceAccountService(settings); +} + +} diff --git a/ydb/library/ycloud/impl/service_account_service.h b/ydb/library/ycloud/impl/service_account_service.h new file mode 100644 index 00000000000..14ecb5e34d1 --- /dev/null +++ b/ydb/library/ycloud/impl/service_account_service.h @@ -0,0 +1,19 @@ +#pragma once +#include <ydb/library/ycloud/api/service_account_service.h> +#include "grpc_service_client.h" + +namespace NCloud { + +using namespace NKikimr; + +struct TServiceAccountServiceSettings : TGrpcClientSettings {}; + +IActor* CreateServiceAccountService(const TServiceAccountServiceSettings& settings); + +inline IActor* CreateServiceAccountService(const TString& endpoint) { + TServiceAccountServiceSettings settings; + settings.Endpoint = endpoint; + return CreateServiceAccountService(settings); +} + +} diff --git a/ydb/library/ycloud/impl/service_account_service_ut.cpp b/ydb/library/ycloud/impl/service_account_service_ut.cpp new file mode 100644 index 00000000000..55199b81e2a --- /dev/null +++ b/ydb/library/ycloud/impl/service_account_service_ut.cpp @@ -0,0 +1,105 @@ +#include <library/cpp/actors/core/event.h> +#include <library/cpp/actors/core/event_local.h> +#include <ydb/core/testlib/test_client.h> +#include <ydb/core/testlib/test_client.h> +#include <ydb/library/testlib/service_mocks/service_account_service_mock.h> +#include <ydb/core/grpc_services/grpc_helper.h> +#include <library/cpp/grpc/server/grpc_server.h> +#include <ydb/public/lib/deprecated/kicli/kicli.h> +#include <library/cpp/testing/unittest/registar.h> +#include <library/cpp/testing/unittest/tests_data.h> +#include <util/string/builder.h> +#include "service_account_service.h" + +using namespace NKikimr; +using namespace Tests; + +namespace { + static const TString IAM_TOKEN = "a-b-c"; +} + +class TServiceAccountServiceFixture : public NUnitTest::TBaseFixture { +public: + TServiceAccountServiceFixture() { + GrpcPort = PortManager.GetPort(2134); + + NKikimrProto::TAuthConfig authConfig; + auto settings = TServerSettings(GrpcPort, authConfig); + settings.SetDomainName("Root"); + Server = MakeHolder<TServer>(settings); + Client = MakeHolder<TClient>(settings); + Client->InitRootScheme(); + + Runtime = Server->GetRuntime(); + SenderActorId = Runtime->AllocateEdgeActor(); + TAutoPtr<IEventHandle> handle; + + // Service Account Service + ui16 servicePort = PortManager.GetPort(8443); + ServiceAccountService = NCloud::CreateServiceAccountService("localhost:" + ToString(servicePort)); + Runtime->Register(ServiceAccountService); + + // Service Account Service Mock + grpc::ServerBuilder builder; + ServiceAccountServiceMock.ServiceAccountData["Service1"].set_id("Service1"); + ServiceAccountServiceMock.IamTokens["Service1"].set_iam_token(IAM_TOKEN); + builder.AddListeningPort("[::]:" + ToString(servicePort), grpc::InsecureServerCredentials()).RegisterService(&ServiceAccountServiceMock); + ServiceAccountServer = builder.BuildAndStart(); + } + +public: + ui16 GrpcPort; + TPortManager PortManager; + THolder<TServer> Server; + THolder<TClient> Client; + TTestActorRuntime* Runtime; + TServiceAccountServiceMock ServiceAccountServiceMock; + IActor* ServiceAccountService; + std::unique_ptr<grpc::Server> ServiceAccountServer; + TActorId SenderActorId; +}; + +namespace { + template<class TEvRequest> + TEvRequest* CreateRequest(const TString& accountId) { + auto* result = new TEvRequest(); + result->Request.set_service_account_id(accountId); + return result; + } +} + +Y_UNIT_TEST_SUITE_F(TServiceAccountServiceTest, TServiceAccountServiceFixture) { + Y_UNIT_TEST(Get) { + TAutoPtr<IEventHandle> handle; + // check for not found + Runtime->Send(new IEventHandle(ServiceAccountService->SelfId(), SenderActorId, CreateRequest<NCloud::TEvServiceAccountService::TEvGetServiceAccountRequest>("bad1"))); + auto result = Runtime->GrabEdgeEvent<NCloud::TEvServiceAccountService::TEvGetServiceAccountResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT_EQUAL(result->Status.Msg, "Not Found"); + + // check for found + Runtime->Send(new IEventHandle(ServiceAccountService->SelfId(), SenderActorId, CreateRequest<NCloud::TEvServiceAccountService::TEvGetServiceAccountRequest>("Service1"))); + result = Runtime->GrabEdgeEvent<NCloud::TEvServiceAccountService::TEvGetServiceAccountResponse>(handle); + + UNIT_ASSERT(result); + UNIT_ASSERT(result->Status.Ok()); + UNIT_ASSERT_EQUAL(result->Response.id(), "Service1"); + } + + Y_UNIT_TEST(IssueToken) { + TAutoPtr<IEventHandle> handle; + // check for not found + Runtime->Send(new IEventHandle(ServiceAccountService->SelfId(), SenderActorId, CreateRequest<NCloud::TEvServiceAccountService::TEvIssueTokenRequest>("bad1"))); + auto result = Runtime->GrabEdgeEvent<NCloud::TEvServiceAccountService::TEvIssueTokenResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT_EQUAL(result->Status.GRpcStatusCode, grpc::StatusCode::UNAUTHENTICATED); + + // check for found + Runtime->Send(new IEventHandle(ServiceAccountService->SelfId(), SenderActorId, CreateRequest<NCloud::TEvServiceAccountService::TEvIssueTokenRequest>("Service1"))); + result = Runtime->GrabEdgeEvent<NCloud::TEvServiceAccountService::TEvIssueTokenResponse>(handle); + + UNIT_ASSERT(result); + UNIT_ASSERT(result->Status.Ok()); + UNIT_ASSERT_EQUAL(result->Response.iam_token(), IAM_TOKEN); + } +} diff --git a/ydb/library/ycloud/impl/user_account_service.cpp b/ydb/library/ycloud/impl/user_account_service.cpp new file mode 100644 index 00000000000..7bddab4a6b9 --- /dev/null +++ b/ydb/library/ycloud/impl/user_account_service.cpp @@ -0,0 +1,46 @@ +#include <library/cpp/actors/core/actorsystem.h> +#include <library/cpp/actors/core/actor.h> +#include <ydb/public/api/client/yc_private/iam/user_account_service.grpc.pb.h> +#include "user_account_service.h" +#include "grpc_service_client.h" + +namespace NCloud { + +using namespace NKikimr; + +class TUserAccountService : public NActors::TActor<TUserAccountService>, TGrpcServiceClient<yandex::cloud::priv::iam::v1::UserAccountService> { + using TThis = TUserAccountService; + using TBase = NActors::TActor<TUserAccountService>; + + struct TGetUserAccountRequest : TGrpcRequest { + static constexpr auto Request = &yandex::cloud::priv::iam::v1::UserAccountService::Stub::AsyncGet; + using TRequestEventType = TEvUserAccountService::TEvGetUserAccountRequest; + using TResponseEventType = TEvUserAccountService::TEvGetUserAccountResponse; + }; + + void Handle(TEvUserAccountService::TEvGetUserAccountRequest::TPtr& ev) { + MakeCall<TGetUserAccountRequest>(std::move(ev)); + } + +public: + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::USER_ACCOUNT_SERVICE_ACTOR; } + + TUserAccountService(const TUserAccountServiceSettings& settings) + : TBase(&TThis::StateWork) + , TGrpcServiceClient(settings) + {} + + void StateWork(TAutoPtr<NActors::IEventHandle>& ev, const NActors::TActorContext&) { + switch (ev->GetTypeRewrite()) { + hFunc(TEvUserAccountService::TEvGetUserAccountRequest, Handle); + cFunc(TEvents::TSystem::PoisonPill, PassAway); + } + } +}; + + +IActor* CreateUserAccountService(const TUserAccountServiceSettings& settings) { + return new TUserAccountService(settings); +} + +} diff --git a/ydb/library/ycloud/impl/user_account_service.h b/ydb/library/ycloud/impl/user_account_service.h new file mode 100644 index 00000000000..9e271bc451a --- /dev/null +++ b/ydb/library/ycloud/impl/user_account_service.h @@ -0,0 +1,19 @@ +#pragma once +#include <ydb/library/ycloud/api/user_account_service.h> +#include "grpc_service_client.h" + +namespace NCloud { + +using namespace NKikimr; + +struct TUserAccountServiceSettings : TGrpcClientSettings {}; + +IActor* CreateUserAccountService(const TUserAccountServiceSettings& settings); + +inline IActor* CreateUserAccountService(const TString& endpoint) { + TUserAccountServiceSettings settings; + settings.Endpoint = endpoint; + return CreateUserAccountService(settings); +} + +} diff --git a/ydb/library/ycloud/impl/user_account_service_ut.cpp b/ydb/library/ycloud/impl/user_account_service_ut.cpp new file mode 100644 index 00000000000..0903b1bb000 --- /dev/null +++ b/ydb/library/ycloud/impl/user_account_service_ut.cpp @@ -0,0 +1,62 @@ +#include <library/cpp/actors/core/event.h> +#include <library/cpp/actors/core/event_local.h> +#include <ydb/core/testlib/test_client.h> +#include <ydb/library/testlib/service_mocks/user_account_service_mock.h> +#include <ydb/core/grpc_services/grpc_helper.h> +#include <library/cpp/grpc/server/grpc_server.h> +#include <ydb/public/lib/deprecated/kicli/kicli.h> +#include <library/cpp/testing/unittest/registar.h> +#include <library/cpp/testing/unittest/tests_data.h> +#include <util/string/builder.h> +#include "user_account_service.h" + +Y_UNIT_TEST_SUITE(TUserAccountServiceTest) { + Y_UNIT_TEST(Get) { + using namespace NKikimr; + using namespace Tests; + + TPortManager tp; + // Kikimr + ui16 kikimrPort = tp.GetPort(2134); + NKikimrProto::TAuthConfig authConfig; + auto settings = TServerSettings(kikimrPort, authConfig); + settings.SetDomainName("Root"); + TServer server(settings); + TClient client(settings); + NClient::TKikimr kikimr(client.GetClientConfig()); + client.InitRootScheme(); + + TTestActorRuntime* runtime = server.GetRuntime(); + TActorId sender = runtime->AllocateEdgeActor(); + TAutoPtr<IEventHandle> handle; + + // User Account Service + ui16 servicePort = tp.GetPort(8443); + IActor* userAccountService = NCloud::CreateUserAccountService("localhost:" + ToString(servicePort)); + runtime->Register(userAccountService); + + // User Account Service Mock + TUserAccountServiceMock userAccountServiceMock; + grpc::ServerBuilder builder; + userAccountServiceMock.UserAccountData["user1"].set_id("user1"); + builder.AddListeningPort("[::]:" + ToString(servicePort), grpc::InsecureServerCredentials()).RegisterService(&userAccountServiceMock); + std::unique_ptr<grpc::Server> userAccountServer(builder.BuildAndStart()); + + // check for not found + auto request = MakeHolder<NCloud::TEvUserAccountService::TEvGetUserAccountRequest>(); + request->Request.set_user_account_id("bad1"); + runtime->Send(new IEventHandle(userAccountService->SelfId(), sender, request.Release())); + auto result = runtime->GrabEdgeEvent<NCloud::TEvUserAccountService::TEvGetUserAccountResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT_EQUAL(result->Status.Msg, "Not Found"); + + // check for found + request = MakeHolder<NCloud::TEvUserAccountService::TEvGetUserAccountRequest>(); + request->Request.set_user_account_id("user1"); + runtime->Send(new IEventHandle(userAccountService->SelfId(), sender, request.Release())); + result = runtime->GrabEdgeEvent<NCloud::TEvUserAccountService::TEvGetUserAccountResponse>(handle); + UNIT_ASSERT(result); + UNIT_ASSERT(result->Status.Ok()); + UNIT_ASSERT_EQUAL(result->Response.id(), "user1"); + } +} diff --git a/ydb/library/ycloud/impl/ut/CMakeLists.darwin.txt b/ydb/library/ycloud/impl/ut/CMakeLists.darwin.txt new file mode 100644 index 00000000000..4bab590bae3 --- /dev/null +++ b/ydb/library/ycloud/impl/ut/CMakeLists.darwin.txt @@ -0,0 +1,51 @@ + +# 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_executable(ydb-library-ycloud-impl-ut) +target_compile_options(ydb-library-ycloud-impl-ut PRIVATE + -DUSE_CURRENT_UDF_ABI_VERSION +) +target_include_directories(ydb-library-ycloud-impl-ut PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl +) +target_link_libraries(ydb-library-ycloud-impl-ut PUBLIC + contrib-libs-cxxsupp + yutil + library-cpp-cpuid_check + cpp-testing-unittest_main + library-ycloud-impl + library-cpp-retry + core-testlib-default +) +target_link_options(ydb-library-ycloud-impl-ut PRIVATE + -Wl,-no_deduplicate + -Wl,-sdk_version,10.15 + -fPIC + -fPIC + -framework + CoreFoundation +) +target_sources(ydb-library-ycloud-impl-ut PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/access_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/folder_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/service_account_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/user_account_service_ut.cpp +) +add_test( + NAME + ydb-library-ycloud-impl-ut + COMMAND + ydb-library-ycloud-impl-ut + --print-before-suite + --print-before-test + --fork-tests + --print-times + --show-fails +) +vcs_info(ydb-library-ycloud-impl-ut) diff --git a/ydb/library/ycloud/impl/ut/CMakeLists.linux-aarch64.txt b/ydb/library/ycloud/impl/ut/CMakeLists.linux-aarch64.txt new file mode 100644 index 00000000000..3aa803b7870 --- /dev/null +++ b/ydb/library/ycloud/impl/ut/CMakeLists.linux-aarch64.txt @@ -0,0 +1,53 @@ + +# 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_executable(ydb-library-ycloud-impl-ut) +target_compile_options(ydb-library-ycloud-impl-ut PRIVATE + -DUSE_CURRENT_UDF_ABI_VERSION +) +target_include_directories(ydb-library-ycloud-impl-ut PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl +) +target_link_libraries(ydb-library-ycloud-impl-ut PUBLIC + contrib-libs-cxxsupp + yutil + library-cpp-lfalloc + cpp-testing-unittest_main + library-ycloud-impl + library-cpp-retry + core-testlib-default +) +target_link_options(ydb-library-ycloud-impl-ut PRIVATE + -ldl + -lrt + -Wl,--no-as-needed + -fPIC + -fPIC + -lpthread + -lrt + -ldl +) +target_sources(ydb-library-ycloud-impl-ut PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/access_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/folder_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/service_account_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/user_account_service_ut.cpp +) +add_test( + NAME + ydb-library-ycloud-impl-ut + COMMAND + ydb-library-ycloud-impl-ut + --print-before-suite + --print-before-test + --fork-tests + --print-times + --show-fails +) +vcs_info(ydb-library-ycloud-impl-ut) diff --git a/ydb/library/ycloud/impl/ut/CMakeLists.linux.txt b/ydb/library/ycloud/impl/ut/CMakeLists.linux.txt new file mode 100644 index 00000000000..0db7d5d9368 --- /dev/null +++ b/ydb/library/ycloud/impl/ut/CMakeLists.linux.txt @@ -0,0 +1,55 @@ + +# 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_executable(ydb-library-ycloud-impl-ut) +target_compile_options(ydb-library-ycloud-impl-ut PRIVATE + -DUSE_CURRENT_UDF_ABI_VERSION +) +target_include_directories(ydb-library-ycloud-impl-ut PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl +) +target_link_libraries(ydb-library-ycloud-impl-ut PUBLIC + contrib-libs-cxxsupp + yutil + cpp-malloc-tcmalloc + libs-tcmalloc-no_percpu_cache + library-cpp-cpuid_check + cpp-testing-unittest_main + library-ycloud-impl + library-cpp-retry + core-testlib-default +) +target_link_options(ydb-library-ycloud-impl-ut PRIVATE + -ldl + -lrt + -Wl,--no-as-needed + -fPIC + -fPIC + -lpthread + -lrt + -ldl +) +target_sources(ydb-library-ycloud-impl-ut PRIVATE + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/access_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/folder_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/service_account_service_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/library/ycloud/impl/user_account_service_ut.cpp +) +add_test( + NAME + ydb-library-ycloud-impl-ut + COMMAND + ydb-library-ycloud-impl-ut + --print-before-suite + --print-before-test + --fork-tests + --print-times + --show-fails +) +vcs_info(ydb-library-ycloud-impl-ut) diff --git a/ydb/library/ycloud/impl/ut/CMakeLists.txt b/ydb/library/ycloud/impl/ut/CMakeLists.txt new file mode 100644 index 00000000000..3e0811fb22e --- /dev/null +++ b/ydb/library/ycloud/impl/ut/CMakeLists.txt @@ -0,0 +1,15 @@ + +# 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. + + +if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND UNIX AND NOT APPLE AND NOT ANDROID) + include(CMakeLists.linux-aarch64.txt) +elseif (APPLE) + include(CMakeLists.darwin.txt) +elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND UNIX AND NOT APPLE AND NOT ANDROID) + include(CMakeLists.linux.txt) +endif() |