diff options
| author | Vladislav Serikov <[email protected]> | 2026-06-26 11:27:39 +0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-06-26 11:27:39 +0300 |
| commit | c74dddfd324c5cc4ecf27ff939e9b5937d3cd060 (patch) | |
| tree | af7ed876c2070e3e0eb0b8bb4737784cdc299d1e | |
| parent | 4a2009061115d25f12d7876659d02e87c17df95d (diff) | |
Enable AS v2 feature flags by default (#44266)
| -rw-r--r-- | ydb/core/http_proxy/ut/datastreams_fixture/datastreams_fixture.cpp | 14 | ||||
| -rw-r--r-- | ydb/core/kafka_proxy/ut/test_server.cpp | 7 | ||||
| -rw-r--r-- | ydb/core/kafka_proxy/ut/test_server.h | 1 | ||||
| -rw-r--r-- | ydb/core/protos/feature_flags.proto | 4 | ||||
| -rw-r--r-- | ydb/core/security/ticket_parser_impl.h | 6 | ||||
| -rw-r--r-- | ydb/core/security/ticket_parser_ut.cpp | 28 | ||||
| -rw-r--r-- | ydb/library/testlib/service_mocks/access_service_mock.h | 30 | ||||
| -rw-r--r-- | ydb/library/ycloud/impl/access_service_ut.cpp | 6 |
8 files changed, 70 insertions, 26 deletions
diff --git a/ydb/core/http_proxy/ut/datastreams_fixture/datastreams_fixture.cpp b/ydb/core/http_proxy/ut/datastreams_fixture/datastreams_fixture.cpp index 178c9d2cedc..3e13a019e1d 100644 --- a/ydb/core/http_proxy/ut/datastreams_fixture/datastreams_fixture.cpp +++ b/ydb/core/http_proxy/ut/datastreams_fixture/datastreams_fixture.cpp @@ -897,15 +897,15 @@ void THttpProxyTestMock::InitAccessServiceService(bool enableAccessServiceV2Inte asMock.AuthorizeData["[email protected]"].Response.mutable_subject()->mutable_service_account()->set_id("Service1_id"); }; - if (enableAccessServiceV2Interface) { - // V2 mock setup - setupAccessServiceMock(AccessServiceMockV2); - builder.AddListeningPort(AccessServiceEndpoint, grpc::InsecureServerCredentials()).RegisterService(&AccessServiceMockV2); - } else { - // V1 mock setup + builder.AddListeningPort(AccessServiceEndpoint, grpc::InsecureServerCredentials()); + + if (!enableAccessServiceV2Interface) { setupAccessServiceMock(AccessServiceMock); - builder.AddListeningPort(AccessServiceEndpoint, grpc::InsecureServerCredentials()).RegisterService(&AccessServiceMock); + builder.RegisterService(&AccessServiceMock); } + // We always should setup v2, because bulkAuthorization works only in v2 and EnableBulkAuthorization=true will call it + setupAccessServiceMock(AccessServiceMockV2); + builder.RegisterService(&AccessServiceMockV2); AccessServiceServer = builder.BuildAndStart(); } diff --git a/ydb/core/kafka_proxy/ut/test_server.cpp b/ydb/core/kafka_proxy/ut/test_server.cpp index 4fcfa55e684..49ba6337537 100644 --- a/ydb/core/kafka_proxy/ut/test_server.cpp +++ b/ydb/core/kafka_proxy/ut/test_server.cpp @@ -196,7 +196,12 @@ TTestServer<TKikimr, secure>::TTestServer(const TTestServerSettings& settings) { { // Access Server Mock grpc::ServerBuilder builder; - builder.AddListeningPort(accessServiceEndpoint, grpc::InsecureServerCredentials()).RegisterService(&accessServiceMock); + builder.AddListeningPort(accessServiceEndpoint, grpc::InsecureServerCredentials()); + if (!KikimrServer->GetRuntime()->GetAppData().FeatureFlags.GetEnableAccessServiceV2Interface()) { + builder.RegisterService(&accessServiceMock); + } + // We should always register v2 because BulkAuth uses V2 AS even with V1 + builder.RegisterService(&accessServiceMockV2); AccessServer = builder.BuildAndStart(); } } diff --git a/ydb/core/kafka_proxy/ut/test_server.h b/ydb/core/kafka_proxy/ut/test_server.h index 9c48cd750d0..de9b9f4e6af 100644 --- a/ydb/core/kafka_proxy/ut/test_server.h +++ b/ydb/core/kafka_proxy/ut/test_server.h @@ -61,6 +61,7 @@ public: THolder<TTempFileHandle> MeteringFile; TTicketParserAccessServiceMock accessServiceMock; + TTicketParserAccessServiceMockV2 accessServiceMockV2; std::unique_ptr<grpc::Server> AccessServer; }; diff --git a/ydb/core/protos/feature_flags.proto b/ydb/core/protos/feature_flags.proto index 57c86b14289..7b16271fcc6 100644 --- a/ydb/core/protos/feature_flags.proto +++ b/ydb/core/protos/feature_flags.proto @@ -137,7 +137,7 @@ message TFeatureFlags { reserved 111; // UseVDisksBalancing optional bool EnableViews = 112 [default = true]; optional bool EnableServerlessExclusiveDynamicNodes = 113 [default = false]; - optional bool EnableAccessServiceBulkAuthorization = 114 [default = false]; + optional bool EnableAccessServiceBulkAuthorization = 114 [default = true]; optional bool EnableAddColumsWithDefaults = 115 [default = true]; optional bool EnableReplaceIfExistsForExternalEntities = 116 [ default = true]; optional bool EnableCMSRequestPriorities = 117 [default = true]; @@ -322,7 +322,7 @@ message TFeatureFlags { optional bool EnableCompactFulltextIndex = 280 [default = false]; optional bool EnableVDiskWaitForRecoveryLogCutOnLocalSyncDataReplay = 281 [default = false]; optional bool EnableFulltextIndexPrefix = 282 [default = false]; - optional bool EnableAccessServiceV2Interface = 283 [default = false, (RequireRestart) = true]; + optional bool EnableAccessServiceV2Interface = 283 [default = true, (RequireRestart) = true]; optional bool EnableAnalyzeLongRunningOperation = 284 [default = true]; optional bool EnableTopicRetentionDeleteLastBlob = 285 [default = false]; } diff --git a/ydb/core/security/ticket_parser_impl.h b/ydb/core/security/ticket_parser_impl.h index 5f36990898d..ffa95e4dc6c 100644 --- a/ydb/core/security/ticket_parser_impl.h +++ b/ydb/core/security/ticket_parser_impl.h @@ -581,10 +581,10 @@ private: template <typename TTokenRecord> void RequestAccessServiceAuthorization(const TString& key, TTokenRecord& record) const { - if (AppData()->FeatureFlags.GetEnableAccessServiceBulkAuthorization()) { - AccessServiceBulkAuthorize(key, record); - } else if (NebiusAccessServiceValidator) { + if (NebiusAccessServiceValidator) { NebiusAccessServiceAuthorize(key, record); + } else if (AppData()->FeatureFlags.GetEnableAccessServiceBulkAuthorization()) { + AccessServiceBulkAuthorize(key, record); } else { AccessServiceAuthorize(key, record); } diff --git a/ydb/core/security/ticket_parser_ut.cpp b/ydb/core/security/ticket_parser_ut.cpp index 1119e26e00d..a5ec40b0a82 100644 --- a/ydb/core/security/ticket_parser_ut.cpp +++ b/ydb/core/security/ticket_parser_ut.cpp @@ -1532,6 +1532,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) { AuthorizationRetryError<NKikimr::TNebiusAccessServiceMock>(); } + Y_UNIT_TEST(NebiusAuthorizationWithBulkRetryError) { + AuthorizationRetryError<NKikimr::TNebiusAccessServiceMock, true>(); + } + template <typename TAccessServiceMock, bool EnableBulkAuthorization = false> void AuthorizationRetryErrorImmediately() { using namespace Tests; @@ -1625,6 +1629,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) { AuthorizationRetryErrorImmediately<NKikimr::TNebiusAccessServiceMock>(); } + Y_UNIT_TEST(NebiusAuthorizationWithBulkRetryErrorImmediately) { + AuthorizationRetryErrorImmediately<NKikimr::TNebiusAccessServiceMock, true>(); + } + Y_UNIT_TEST(AuthenticationUnsupported) { using namespace Tests; @@ -2054,6 +2062,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) { Authorization<NKikimr::TNebiusAccessServiceMock>(); } + Y_UNIT_TEST(NebiusAuthorizationWithBulk) { + Authorization<NKikimr::TNebiusAccessServiceMock, true>(); + } + template <typename TAccessServiceMock, bool EnableBulkAuthorization = false> void AuthorizationWithRequiredPermissions() { using namespace Tests; @@ -2135,6 +2147,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) { AuthorizationWithRequiredPermissions<NKikimr::TNebiusAccessServiceMock>(); } + Y_UNIT_TEST(NebiusAuthorizationWithRequiredPermissionsWithBulk) { + AuthorizationWithRequiredPermissions<NKikimr::TNebiusAccessServiceMock, true>(); + } + template <typename TAccessServiceMock, bool EnableBulkAuthorization = false> void AuthorizationWithUserAccount() { using namespace Tests; @@ -2393,6 +2409,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) { AuthorizationUnavailable<NKikimr::TNebiusAccessServiceMock>(); } + Y_UNIT_TEST(NebiusAuthorizationWithBulkUnavailable) { + AuthorizationUnavailable<NKikimr::TNebiusAccessServiceMock, true>(); + } + template <typename TAccessServiceMock, bool EnableBulkAuthorization = false> void AuthorizationModify() { using namespace Tests; @@ -2473,6 +2493,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) { AuthorizationModify<NKikimr::TNebiusAccessServiceMock>(); } + Y_UNIT_TEST(NebiusAuthorizationWithBulkModify) { + AuthorizationModify<NKikimr::TNebiusAccessServiceMock, true>(); + } + Y_UNIT_TEST(CanProperHandleErrorWithEmptyMessage) { using namespace Tests; @@ -2674,6 +2698,10 @@ Y_UNIT_TEST_SUITE(TTicketParserTest) { AuthorizationWithPeerName<NKikimr::TNebiusAccessServiceMock>(); } + Y_UNIT_TEST(XUserIPHeaderIsSetInTicketParserNebiusAuthorizationWithBulk) { + AuthorizationWithPeerName<NKikimr::TNebiusAccessServiceMock, true>(); + } + THolder<TEvTicketParser::TEvAuthorizeTicketResult> RunPeernameQuery( TTestActorRuntime* runtime, const TString& peername) { diff --git a/ydb/library/testlib/service_mocks/access_service_mock.h b/ydb/library/testlib/service_mocks/access_service_mock.h index e67824856a6..3adbed49159 100644 --- a/ydb/library/testlib/service_mocks/access_service_mock.h +++ b/ydb/library/testlib/service_mocks/access_service_mock.h @@ -115,7 +115,6 @@ public: THashMap<TString, TResponse<yandex::cloud::priv::accessservice::v2::AuthenticateResponse>> AuthenticateData; THashMap<TString, TResponse<yandex::cloud::priv::accessservice::v2::AuthorizeResponse>> AuthorizeData; - THashMap<TString, TResponse<yandex::cloud::priv::accessservice::v2::BulkAuthorizeResponse>> BulkAuthorizeData; TMutex UserIpMutex; TString CapturedXUserIP; @@ -188,22 +187,29 @@ public: CapturedXUserIP = NTestUtils::CaptureXUserIP(ctx); } - TString token = request->signature().access_key_id() + request->iam_token(); for (const auto& action : request->actions().items()) { if (action.resource_path_size() == 0) { - continue; + return grpc::Status(grpc::StatusCode::PERMISSION_DENIED, "Permission Denied"); } + const TString& lastResourceId = action.resource_path(action.resource_path_size() - 1).id(); - token += "-" + action.permission() + "-" + lastResourceId; - } - auto it = BulkAuthorizeData.find(token); - if (it != BulkAuthorizeData.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"); + const TString& token = request->signature().access_key_id() + request->iam_token() + "-" + action.permission() + "-" + lastResourceId; + + auto it = AuthorizeData.find(token); + if (it != AuthorizeData.end() && it->second.Status.ok()) { + CheckRequestId(ctx, it->second, token); + if (it->second.Response.has_subject()) { + response->mutable_subject()->CopyFrom(it->second.Response.subject()); + } + } else { + auto* result_item = response->mutable_results()->add_items(); + result_item->set_permission(action.permission()); + result_item->mutable_resource_path()->CopyFrom(action.resource_path()); + result_item->mutable_permission_denied_error()->set_message((it != AuthorizeData.end()) ? it->second.Status.error_message() : "Permission denied"); + } } + + return grpc::Status::OK; } }; diff --git a/ydb/library/ycloud/impl/access_service_ut.cpp b/ydb/library/ycloud/impl/access_service_ut.cpp index 8d03def7c0c..23dabae0c87 100644 --- a/ydb/library/ycloud/impl/access_service_ut.cpp +++ b/ydb/library/ycloud/impl/access_service_ut.cpp @@ -160,7 +160,7 @@ Y_UNIT_TEST_SUITE(TAccessServiceTestV2) { TTestSetup setup(true); TAutoPtr<IEventHandle> handle; - setup.AccessServiceMockV2.BulkAuthorizeData["user1-something.read-test_folder_1-something.write-test_folder_2"].Response.mutable_subject()->mutable_user_account()->set_id("user1"); + setup.AccessServiceMockV2.AuthorizeData["user1-something.read-test_folder_1"].Response.mutable_subject()->mutable_user_account()->set_id("user1"); auto request = MakeHolder<NCloud::TEvAccessService::TEvBulkAuthorizeRequestV2>(); request->Request.set_iam_token("user1"); @@ -176,6 +176,10 @@ Y_UNIT_TEST_SUITE(TAccessServiceTestV2) { UNIT_ASSERT(result); UNIT_ASSERT(result->Status.Ok()); UNIT_ASSERT_VALUES_EQUAL(result->Response.subject().user_account().id(), "user1"); + UNIT_ASSERT_VALUES_EQUAL(result->Response.results().items_size(), 1); + UNIT_ASSERT_VALUES_EQUAL(result->Response.results().items(0).permission(), "something.write"); + UNIT_ASSERT_VALUES_EQUAL(result->Response.results().items(0).resource_path_size(), 1); + UNIT_ASSERT_VALUES_EQUAL(result->Response.results().items(0).resource_path(0).id(), "test_folder_2"); } Y_UNIT_TEST(PassRequestId) { |
