Audit
Note
Available only in the Enterprise version.
Audit (event log) is designed for maintaining log files where system events are recorded, namely:
Search records
Get record attributes by their ID
Modify attributes or create a new record
Delete records
An event record contains a set of information about the event specified in the settings.
The main audit logic is located in the ecos-audit-lib library: https://gitlab.citeck.ru/citeck-projects/ecos-audit-lib
Audit in Citeck is configured via Spring configuration.
Configuration prefix: ecos.webapp.audit
Available settings
enabled: Boolean // включить или выключить аудит. По умолчанию false
pipelines: Map<String, PipelineProps> // конфигурация конвееров
outputs: Map<String, OutputProps> // конфигурация выходов
PipelineProps:
enabled: Boolean // включен или нет конвеер. По умолчанию true
filter: EcosAuditEventFilterProps // настройки фильтрации
processors: List<EcosAuditProcessorProps> // процессоры
outputs: List<String> // выходы
EcosAuditEventFilterProps:
type: TypeFilter // фильтр по типу
authority: AuthorityFilter // фильтр по текущему пользователю
headers: Predicate // фильтр по хидерам. Предикат задается в виде строки.
eventData: Predicate // фильтр по содержимому события. Предикат задается в виде строки.
TypeFilter
includes: List<String> // обрабатывать только события из этого списка
excludes: List<String> // исключить обработку событий из этого списка
Note
Templates are supported in includes and excludes for types. The event type is split by “.” into words and then matched against includes and excludes. If the symbol ‘#’ is encountered in the settings, it means “any number of words including 0”, the symbol ‘*’ means - one any word.
AuthorityFilter
includes: List<String> // обрабатывать только события от пользователей, ролей и/или групп из этого списка
excludes: List<String> // исключать события от пользователей, ролей и/или групп из этого списка
includeSystem: Boolean // фиксировать действия системы. По умолчанию false
Configuration example
ecos:
webapp:
audit:
enabled: true
pipelines:
main:
filter:
type:
includes: [
"records.query-records",
"records.get-records-atts",
"records.mutate-record",
"records.delete-records"
]
headers: |
{ "t": "like","att": "sourceId","val": "%-cipher" }
outputs: [ "rabbitmq", "log" ]
outputs:
rabbitmq:
type: rabbitmq
log:
type: log
type |
Configuration |
Description |
|---|---|---|
rabbitmq |
Send events to RabbitMQ on exchange “ecos-audit” with RoutingKey == {event_type} |
|
log |
Output events to the microservice log |
Event types:
type |
Fields |
Headers |
Description |
|---|---|---|---|
records.query-records |
sourceId: String
query: RecordsQuery
records: List<EntityRef>
attributes: Map<String, String>
|
sourceId: String
appName: String
appInstanceId: String
|
Search records |
records.get-records-atts |
sourceId: String
record: EntityRef
attributes: Map<String, String>
|
sourceId: String
appName: String
appInstanceId: String
|
Get record attributes by their ID |
records.mutate-record |
sourceId: String,
record: EntityRef,
attributes: ObjectData,
attsToLoad: Map<String, String>
|
sourceId: String
appName: String
appInstanceId: String
|
Modify attributes or create a new record |
records.delete-records |
sourceId: String
records: List<EntityRef>
|
sourceId: String
appName: String
appInstanceId: String
|
Delete records |
General event view
id: UUID // уникальный идентификатор события
type: String // тип события
user: String // пользователь
admin: Boolean // флаг определяющий является ли пользователь администратором
client: ClientInfo // информация о клиенте. На данный момент одно поле внутри - ip: String
time: String // ISO8601 время события
success: Boolean // успешно или нет выполнилось действие
actionTimeMs: Long // время выполнения действия в миллисекундах
error: ErrorInfo // информация об ошибке. Присутствует только если success == false
data: ObjectData // данные по событию. Для каждого типа событий свой набор данных
appName: String // имя приложения, в котором произошло событие
appInstanceId: String // инстанс приложения, в котором произошло событие
ErrorInfo
message: String // текст ошибки
javaClass: String // класс ошибки
Audit description
Audit event model
id: UUID // unique event identifier. Automatically generated for each event.
type: String // event type
user: String // user
admin: Boolean // flag defining whether the user is an administrator
client: ClientInfo // client information. Currently one field inside - ip: String
time: String // ISO8601 event time
success: Boolean // whether the action completed successfully or not
actionTimeMs: Long // action execution time in milliseconds
error: ErrorInfo // error information. Present only if success == false. Description of this structure is below.
data: Map<String, Object> // event data. Each event type has its own data set. A list of data by event type will be provided below.
appName: String // name of the application where the event occurred
appInstanceId: String // application instance where the event occurred
ErrorInfo model
message: String // error text. Can be formed arbitrarily and directly depends on the code section where this error occurred. If it is necessary to process and catch certain types of errors, a list of such errors should be formed and a refinement should be made.
javaClass: String // java error class. Like message, it can be anything, but tied to existing classes in the system.
Event types
records.query-records
Data in the data field:
sourceId: String // Data source identifier. It can be used to group or filter all operations (read, modify, create, delete) in a specific data source.
query: RecordsQuery // Search query for data (records) in the data source.
records: List<EntityRef> // List of records returned as a result of the query. EntityRef description
attributes: Map<String, String> // List of attributes that the client requested from the records in the records list.
records.get-records-atts
Data in the data field:
sourceId: String // Data source identifier. It can be used to group or filter all operations (read, modify, create, delete) in a specific data source. sourceId is always part of the record and if a separate field for filtering and grouping
query/get-atts/mutate/deleteactions is not required, then sourceId can be removed from the event.record: EntityRef // Reference to a record in the data source. EntityRef description
attributes: Map<String, String> // Attributes that we request from the record
records.mutate-record
Data in the data field:
sourceId: String // Data source identifier. It can be used to group or filter all operations (read, modify, create, delete) in a specific data source. sourceId is always part of the record and if a separate field for filtering and grouping
query/get-atts/mutate/deleteactions is not required, then sourceId can be removed from the event.record: EntityRef // Reference to a record in the data source. If the record looks like
"{{appName}}/{{sourceId}}@"(i.e., there is nothing after the @ sign), then it means a request to create a new entity has been received. EntityRef descriptionattributes: Map<String, Object> // Attributes sent from the client for updating. I.e., if in attributes we see {“field0”: “field1”}, it means the client is trying to change the field “field0” by assigning it the value “field1”.
attsToLoad: Map<String, String> // Attributes to load after mutation. In some cases, the client sends in the request, in addition to the attributes to be changed, also attributes that should be loaded from the record after successful completion of the mutation.
records.delete-records
Data in the data field:
sourceId: String // Data source identifier. It can be used to group or filter all operations (read, modify, create, delete) in a specific data source. sourceId is always part of each element in records and if a separate field for filtering and grouping query/get-atts/mutate/delete actions is not required, then sourceId can be removed from the event.
records: List<EntityRef> // List of records to delete. EntityRef description
EntityRef description
EntityRef is a unique entity identifier in the Citeck system. It is formed according to the following template:
{{appName}}/{{sourceId}}@{{localId}}appName - the name of the application where the data source is located (see the appName field in the event model). Examples of applications: uiserv, emodel, integrations, etc.
sourceId - this is the data source identifier within the application (see the sourceId field)
localId - this is the local entity identifier within the data source. The absence of localId for mutation means creating a new record.
Description of attributes for loading
Attributes for loading can look like this:
{
"name": "name?disp",
"counterparty": "counterparty.fullOrgName?str"
}
This attribute format is part of the Records API (on which all communication in Citeck is built).
In RecordsAPI, the client can request attributes by specifying a complex nested structure, but for audit, mainly only the keys in this map are useful.
That is, from the example above, we can get information that the client requested two attributes - “name” and “counterparty”
More about Records API