summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladislav Serikov <[email protected]>2026-06-26 11:27:39 +0300
committerGitHub <[email protected]>2026-06-26 11:27:39 +0300
commitc74dddfd324c5cc4ecf27ff939e9b5937d3cd060 (patch)
treeaf7ed876c2070e3e0eb0b8bb4737784cdc299d1e
parent4a2009061115d25f12d7876659d02e87c17df95d (diff)
Enable AS v2 feature flags by default (#44266)
-rw-r--r--ydb/core/http_proxy/ut/datastreams_fixture/datastreams_fixture.cpp14
-rw-r--r--ydb/core/kafka_proxy/ut/test_server.cpp7
-rw-r--r--ydb/core/kafka_proxy/ut/test_server.h1
-rw-r--r--ydb/core/protos/feature_flags.proto4
-rw-r--r--ydb/core/security/ticket_parser_impl.h6
-rw-r--r--ydb/core/security/ticket_parser_ut.cpp28
-rw-r--r--ydb/library/testlib/service_mocks/access_service_mock.h30
-rw-r--r--ydb/library/ycloud/impl/access_service_ut.cpp6
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) {