diff --git a/changelog/30071.txt b/changelog/30071.txt new file mode 100644 index 0000000000..acdf6277a2 --- /dev/null +++ b/changelog/30071.txt @@ -0,0 +1,3 @@ +```release-note:improvement +activity: mount_type was added to the API response of sys/internal/counters/activity +``` diff --git a/vault/activity/query.go b/vault/activity/query.go index 8b9b773fd3..e82e7fc424 100644 --- a/vault/activity/query.go +++ b/vault/activity/query.go @@ -59,6 +59,7 @@ type MonthlyNamespaceRecord struct { type MountRecord struct { MountPath string `json:"mount_path"` + MountType string `json:"mount_type"` Counts *CountsRecord `json:"counts"` } diff --git a/vault/activity_log.go b/vault/activity_log.go index 5f90b9a011..2a97796b13 100644 --- a/vault/activity_log.go +++ b/vault/activity_log.go @@ -1902,6 +1902,7 @@ type ResponseNewClients struct { type ResponseMount struct { MountPath string `json:"mount_path" mapstructure:"mount_path"` + MountType string `json:"mount_type" mapstructure:"mount_type"` Counts *ResponseCounts `json:"counts"` } @@ -2898,11 +2899,19 @@ func (a *ActivityLog) calculateByNamespaceResponseForQuery(ctx context.Context, if err != nil { return nil, nil, err } + var displayPath string + if ns == nil { + displayPath = fmt.Sprintf(DeletedNamespaceFmt, nsRecord.NamespaceID) + } else { + displayPath = ns.Path + } if a.includeInResponse(queryNS, ns) { mountResponse := make([]*ResponseMount, 0, len(nsRecord.Mounts)) for _, mountRecord := range nsRecord.Mounts { + mountType := a.mountPathToMountType(ctx, strings.Join([]string{namespace.Canonicalize(displayPath), mountRecord.MountPath}, "")) mountResponse = append(mountResponse, &ResponseMount{ MountPath: mountRecord.MountPath, + MountType: mountType, Counts: a.countsRecordToCountsResponse(mountRecord.Counts), }) } @@ -2911,12 +2920,6 @@ func (a *ActivityLog) calculateByNamespaceResponseForQuery(ctx context.Context, return mountResponse[i].Counts.Clients > mountResponse[j].Counts.Clients }) - var displayPath string - if ns == nil { - displayPath = fmt.Sprintf(DeletedNamespaceFmt, nsRecord.NamespaceID) - } else { - displayPath = ns.Path - } nsCounts := a.namespaceRecordToCountsResponse(nsRecord) byNamespaceResponse = append(byNamespaceResponse, &ResponseNamespace{ NamespaceID: nsRecord.NamespaceID, @@ -2981,23 +2984,26 @@ func (a *ActivityLog) prepareNamespaceResponse(ctx context.Context, nsRecords [] } if a.includeInResponse(queryNS, ns) { mountResponse := make([]*ResponseMount, 0, len(nsRecord.Mounts)) - for _, mountRecord := range nsRecord.Mounts { - if !mountRecord.Counts.HasCounts() { - continue - } - - mountResponse = append(mountResponse, &ResponseMount{ - MountPath: mountRecord.MountPath, - Counts: a.countsRecordToCountsResponse(mountRecord.Counts), - }) - } - var displayPath string if ns == nil { displayPath = fmt.Sprintf(DeletedNamespaceFmt, nsRecord.NamespaceID) } else { displayPath = ns.Path } + + for _, mountRecord := range nsRecord.Mounts { + if !mountRecord.Counts.HasCounts() { + continue + } + + mountType := a.mountPathToMountType(ctx, strings.Join([]string{namespace.Canonicalize(displayPath), mountRecord.MountPath}, "")) + mountResponse = append(mountResponse, &ResponseMount{ + MountPath: mountRecord.MountPath, + MountType: mountType, + Counts: a.countsRecordToCountsResponse(mountRecord.Counts), + }) + } + nsResponse := &ResponseNamespace{ NamespaceID: nsRecord.NamespaceID, NamespacePath: displayPath, diff --git a/vault/activity_log_util_common.go b/vault/activity_log_util_common.go index d6452b6bf2..45f393ac4b 100644 --- a/vault/activity_log_util_common.go +++ b/vault/activity_log_util_common.go @@ -392,7 +392,9 @@ func (a *ActivityLog) sortActivityLogMonthsResponse(months []*ResponseMonth) { const ( noMountAccessor = "no mount accessor (pre-1.10 upgrade?)" + noMountPath = "no mount path (pre-1.10 upgrade?)" DeletedMountFmt = "deleted mount; accessor %q" + DeletedMountPath = "deleted mount" DeletedNamespaceFmt = "deleted namespace %q" ) @@ -416,6 +418,26 @@ func (a *ActivityLog) mountAccessorToMountPath(mountAccessor string) string { return displayPath } +// mountPathToMountType transforms the mount path to the mount type +// returns a placeholder string if the mount path is empty or deleted +func (a *ActivityLog) mountPathToMountType(ctx context.Context, mountPath string) string { + var mountType string + if mountPath == "" { + mountType = noMountPath + } else { + path, valResp := a.core.router.MatchingMountAndEntry(ctx, mountPath) + if path == "" { + mountType = DeletedMountPath + } else { + mountType = valResp.Type + if !strings.HasSuffix(mountType, "/") { + mountType += "/" + } + } + } + return mountType +} + type singleTypeSegmentReader struct { basePath string startTime time.Time