func buildMetricbeatEvent()

in auditbeat/module/auditd/audit_linux.go [546:692]


func buildMetricbeatEvent(msgs []*auparse.AuditMessage, config Config) mb.Event {
	auditEvent, err := aucoalesce.CoalesceMessages(msgs)
	if err != nil {
		// Add messages on error so that it's possible to debug the problem.
		out := mb.Event{RootFields: mapstr.M{}, Error: err}
		addEventOriginal(msgs, out.RootFields)
		return out
	}

	if config.ResolveIDs {
		aucoalesce.ResolveIDs(auditEvent)
	}

	eventOutcome := auditEvent.Result
	if eventOutcome == "fail" {
		eventOutcome = "failure"
	}
	out := mb.Event{
		Timestamp: auditEvent.Timestamp,
		RootFields: mapstr.M{
			"event": mapstr.M{
				"category": auditEvent.Category.String(),
				"action":   auditEvent.Summary.Action,
				"outcome":  eventOutcome,
			},
		},
		ModuleFields: mapstr.M{
			"message_type": strings.ToLower(auditEvent.Type.String()),
			"sequence":     auditEvent.Sequence,
			"result":       auditEvent.Result,
			"data":         createAuditdData(auditEvent.Data),
		},
	}
	if auditEvent.Session != uidUnset {
		_, _ = out.ModuleFields.Put("session", auditEvent.Session)
	}

	// Add root level fields.
	addUser(auditEvent.User, out.RootFields)
	addProcess(auditEvent.Process, out.RootFields)
	addFile(auditEvent.File, out.RootFields)
	addAddress(auditEvent.Source, "source", out.RootFields)
	addAddress(auditEvent.Dest, "destination", out.RootFields)
	addNetwork(auditEvent.Net, out.RootFields)
	if len(auditEvent.Tags) > 0 {
		_, _ = out.RootFields.Put("tags", auditEvent.Tags)
	}
	if config.Warnings && len(auditEvent.Warnings) > 0 {
		warnings := make([]string, 0, len(auditEvent.Warnings))
		for _, err := range auditEvent.Warnings {
			warnings = append(warnings, err.Error())
		}
		_, _ = out.RootFields.Put("error.message", warnings)
		addEventOriginal(msgs, out.RootFields)
	}
	if config.RawMessage {
		addEventOriginal(msgs, out.RootFields)
	}

	// Add module fields.
	m := out.ModuleFields
	if auditEvent.Summary.Actor.Primary != "" {
		_, _ = m.Put("summary.actor.primary", auditEvent.Summary.Actor.Primary)
	}
	if auditEvent.Summary.Actor.Secondary != "" {
		_, _ = m.Put("summary.actor.secondary", auditEvent.Summary.Actor.Secondary)
	}
	if auditEvent.Summary.Object.Primary != "" {
		_, _ = m.Put("summary.object.primary", auditEvent.Summary.Object.Primary)
	}
	if auditEvent.Summary.Object.Secondary != "" {
		_, _ = m.Put("summary.object.secondary", auditEvent.Summary.Object.Secondary)
	}
	if auditEvent.Summary.Object.Type != "" {
		_, _ = m.Put("summary.object.type", auditEvent.Summary.Object.Type)
	}
	if auditEvent.Summary.How != "" {
		_, _ = m.Put("summary.how", auditEvent.Summary.How)
	}
	if len(auditEvent.Paths) > 0 {
		_, _ = m.Put("paths", auditEvent.Paths)
	}

	normalizeEventFields(auditEvent, out.RootFields)

	// User set for related.user
	var userSet common.StringSet
	if config.ResolveIDs {
		userSet = make(common.StringSet)
	}

	// Copy user.*/group.* fields from event
	setECSEntity := func(key string, ent aucoalesce.ECSEntityData, root mapstr.M, set common.StringSet) {
		if ent.ID == "" && ent.Name == "" {
			return
		}
		if ent.ID == uidUnset {
			ent.ID = ""
		}
		nameField := key + ".name"
		idField := key + ".id"
		if ent.ID != "" {
			_, _ = root.Put(idField, ent.ID)
		} else {
			_ = root.Delete(idField)
		}
		if ent.Name != "" {
			_, _ = root.Put(nameField, ent.Name)
			if set != nil {
				set.Add(ent.Name)
			}
		} else {
			_ = root.Delete(nameField)
		}
	}

	setECSEntity("user", auditEvent.ECS.User.ECSEntityData, out.RootFields, userSet)
	setECSEntity("user.effective", auditEvent.ECS.User.Effective, out.RootFields, userSet)
	setECSEntity("user.target", auditEvent.ECS.User.Target, out.RootFields, userSet)
	setECSEntity("user.changes", auditEvent.ECS.User.Changes, out.RootFields, userSet)
	setECSEntity("group", auditEvent.ECS.Group, out.RootFields, nil)

	if userSet != nil {
		if userSet.Count() != 0 {
			_, _ = out.RootFields.Put("related.user", userSet.ToSlice())
		}
	}
	getStringField := func(key string, m mapstr.M) (str string) {
		if asIf, _ := m.GetValue(key); asIf != nil {
			str, _ = asIf.(string)
		}
		return str
	}

	// Remove redundant user.effective.* when it's the same as user.*
	removeRedundantEntity := func(target, original string, m mapstr.M) bool {
		for _, suffix := range []string{".id", ".name"} {
			if value := getStringField(original+suffix, m); value != "" && getStringField(target+suffix, m) == value {
				_ = m.Delete(target)
				return true
			}
		}
		return false
	}
	removeRedundantEntity("user.effective", "user", out.RootFields)
	return out
}