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