@@ -81,57 +81,77 @@ TPath DatabasePathFromWorkingDir(TSchemeShard* SS, const TString &opWorkingDir)
8181
8282} // anonymous namespace
8383
84- void AuditLogModifySchemeTransaction (const NKikimrScheme::TEvModifySchemeTransaction& request, const NKikimrScheme::TEvModifySchemeTransactionResult& response, TSchemeShard* SS, const TString& userSID, const TString& sanitizedToken) {
84+ void AuditLogModifySchemeOperation (const NKikimrSchemeOp::TModifyScheme& operation,
85+ NKikimrScheme::EStatus status, const TString& reason, TSchemeShard* SS,
86+ const TString& peerName, const TString& userSID, const TString& sanitizedToken,
87+ ui64 txId, const TParts& additionalParts) {
88+ auto logEntry = MakeAuditLogFragment (operation);
89+
90+ TPath databasePath = DatabasePathFromWorkingDir (SS, operation.GetWorkingDir ());
91+ auto [cloud_id, folder_id, database_id] = GetDatabaseCloudIds (databasePath);
92+ auto address = NKikimr::NAddressClassifier::ExtractAddress (peerName);
93+
94+ AUDIT_LOG (
95+ AUDIT_PART (" component" , SchemeshardComponentName)
96+ AUDIT_PART (" tx_id" , std::to_string (txId))
97+ AUDIT_PART (" remote_address" , (!address.empty () ? address : EmptyValue))
98+ AUDIT_PART (" subject" , (!userSID.empty () ? userSID : EmptyValue))
99+ AUDIT_PART (" sanitized_token" , (!sanitizedToken.empty () ? sanitizedToken : EmptyValue))
100+ AUDIT_PART (" database" , (!databasePath.IsEmpty () ? databasePath.GetDomainPathString () : EmptyValue))
101+ AUDIT_PART (" operation" , logEntry.Operation )
102+ AUDIT_PART (" paths" , RenderList (logEntry.Paths ), !logEntry.Paths .empty ())
103+ AUDIT_PART (" status" , GeneralStatus (status))
104+ AUDIT_PART (" detailed_status" , NKikimrScheme::EStatus_Name (status))
105+ AUDIT_PART (" reason" , reason, !reason.empty ())
106+
107+ for (const auto & [name, value] : additionalParts) {
108+ AUDIT_PART (name, (!value.empty () ? value : EmptyValue))
109+ }
110+
111+ AUDIT_PART (" cloud_id" , cloud_id, !cloud_id.empty ());
112+ AUDIT_PART (" folder_id" , folder_id, !folder_id.empty ());
113+ AUDIT_PART (" resource_id" , database_id, !database_id.empty ());
114+
115+ // Additionally:
116+
117+ // ModifyACL.
118+ // Technically, non-empty ModifyACL field could come with any ModifyScheme operation.
119+ // In practice, ModifyACL will get processed only by:
120+ // 1. explicit operation ESchemeOpModifyACL -- to modify ACL on a path
121+ // 2. ESchemeOpMkDir or ESchemeOpCreate* operations -- to set rights to newly created paths/entities
122+ // 3. ESchemeOpCopyTable -- to be checked against acl size limit, not to be applied in any way
123+ AUDIT_PART (" new_owner" , logEntry.NewOwner , !logEntry.NewOwner .empty ());
124+ AUDIT_PART (" acl_add" , RenderList (logEntry.ACLAdd ), !logEntry.ACLAdd .empty ());
125+ AUDIT_PART (" acl_remove" , RenderList (logEntry.ACLRemove ), !logEntry.ACLRemove .empty ());
126+
127+ // AlterUserAttributes.
128+ // 1. explicit operation ESchemeOpAlterUserAttributes -- to modify user attributes on a path
129+ // 2. ESchemeOpMkDir or some ESchemeOpCreate* operations -- to set user attributes for newly created paths/entities
130+ AUDIT_PART (" user_attrs_add" , RenderList (logEntry.UserAttrsAdd ), !logEntry.UserAttrsAdd .empty ());
131+ AUDIT_PART (" user_attrs_remove" , RenderList (logEntry.UserAttrsRemove ), !logEntry.UserAttrsRemove .empty ());
132+
133+ // AlterLogin.
134+ // explicit operation ESchemeOpAlterLogin -- to modify user and groups
135+ AUDIT_PART (" login_user" , logEntry.LoginUser );
136+ AUDIT_PART (" login_group" , logEntry.LoginGroup );
137+ AUDIT_PART (" login_member" , logEntry.LoginMember );
138+ );
139+ }
140+
141+ void AuditLogModifySchemeTransaction (const NKikimrScheme::TEvModifySchemeTransaction& request,
142+ const NKikimrScheme::TEvModifySchemeTransactionResult& response, TSchemeShard* SS,
143+ const TString& peerName, const TString& userSID, const TString& sanitizedToken) {
85144 // Each TEvModifySchemeTransaction.Transaction is a self sufficient operation and should be logged independently
86145 // (even if it was packed into a single TxProxy transaction with some other operations).
146+ const auto txId = request.GetTxId ();
147+ const auto status = response.GetStatus ();
148+ const auto reason = response.HasReason () ? response.GetReason () : TString ();
87149 for (const auto & operation : request.GetTransaction ()) {
88- auto logEntry = MakeAuditLogFragment (operation);
89-
90- TPath databasePath = DatabasePathFromWorkingDir (SS, operation.GetWorkingDir ());
91- auto [cloud_id, folder_id, database_id] = GetDatabaseCloudIds (databasePath);
92- auto peerName = NKikimr::NAddressClassifier::ExtractAddress (request.GetPeerName ());
93-
94- AUDIT_LOG (
95- AUDIT_PART (" component" , SchemeshardComponentName)
96- AUDIT_PART (" tx_id" , std::to_string (request.GetTxId ()))
97- AUDIT_PART (" remote_address" , (!peerName.empty () ? peerName : EmptyValue))
98- AUDIT_PART (" subject" , (!userSID.empty () ? userSID : EmptyValue))
99- AUDIT_PART (" sanitized_token" , (!sanitizedToken.empty () ? sanitizedToken : EmptyValue))
100- AUDIT_PART (" database" , (!databasePath.IsEmpty () ? databasePath.GetDomainPathString () : EmptyValue))
101- AUDIT_PART (" operation" , logEntry.Operation )
102- AUDIT_PART (" paths" , RenderList (logEntry.Paths ), !logEntry.Paths .empty ())
103- AUDIT_PART (" status" , GeneralStatus (response.GetStatus ()))
104- AUDIT_PART (" detailed_status" , NKikimrScheme::EStatus_Name (response.GetStatus ()))
105- AUDIT_PART (" reason" , response.GetReason (), response.HasReason ())
106-
107- AUDIT_PART (" cloud_id" , cloud_id, !cloud_id.empty ());
108- AUDIT_PART (" folder_id" , folder_id, !folder_id.empty ());
109- AUDIT_PART (" resource_id" , database_id, !database_id.empty ());
110-
111- // Additionally:
112-
113- // ModifyACL.
114- // Technically, non-empty ModifyACL field could come with any ModifyScheme operation.
115- // In practice, ModifyACL will get processed only by:
116- // 1. explicit operation ESchemeOpModifyACL -- to modify ACL on a path
117- // 2. ESchemeOpMkDir or ESchemeOpCreate* operations -- to set rights to newly created paths/entities
118- // 3. ESchemeOpCopyTable -- to be checked against acl size limit, not to be applied in any way
119- AUDIT_PART (" new_owner" , logEntry.NewOwner , !logEntry.NewOwner .empty ());
120- AUDIT_PART (" acl_add" , RenderList (logEntry.ACLAdd ), !logEntry.ACLAdd .empty ());
121- AUDIT_PART (" acl_remove" , RenderList (logEntry.ACLRemove ), !logEntry.ACLRemove .empty ());
122-
123- // AlterUserAttributes.
124- // 1. explicit operation ESchemeOpAlterUserAttributes -- to modify user attributes on a path
125- // 2. ESchemeOpMkDir or some ESchemeOpCreate* operations -- to set user attributes for newly created paths/entities
126- AUDIT_PART (" user_attrs_add" , RenderList (logEntry.UserAttrsAdd ), !logEntry.UserAttrsAdd .empty ());
127- AUDIT_PART (" user_attrs_remove" , RenderList (logEntry.UserAttrsRemove ), !logEntry.UserAttrsRemove .empty ());
128-
129- // AlterLogin.
130- // explicit operation ESchemeOpAlterLogin -- to modify user and groups
131- AUDIT_PART (" login_user" , logEntry.LoginUser );
132- AUDIT_PART (" login_group" , logEntry.LoginGroup );
133- AUDIT_PART (" login_member" , logEntry.LoginMember );
134- );
150+ const auto type = operation.GetOperationType ();
151+ if (NKikimrSchemeOp::EOperationType::ESchemeOpAlterLogin == type) {
152+ continue ;
153+ }
154+ AuditLogModifySchemeOperation (operation, status, reason, SS, peerName, userSID, sanitizedToken, txId, TParts ());
135155 }
136156}
137157
@@ -194,7 +214,7 @@ struct TXxportRecord {
194214 TString Status;
195215 Ydb::StatusIds::StatusCode DetailedStatus;
196216 TString Reason;
197- TVector<std::pair<TString, TString>> AdditionalParts;
217+ TParts AdditionalParts;
198218 TString StartTime;
199219 TString EndTime;
200220 TString CloudId;
0 commit comments