mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 09:42:25 +00:00
VAULT-31075 CE changes (#28845)
This commit is contained in:
@@ -6,6 +6,7 @@ package vault
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -403,7 +404,7 @@ func (c *Core) findKvMounts() []*kvMount {
|
||||
for _, entry := range c.mounts.Entries {
|
||||
if entry.Type == "kv" || entry.Type == "generic" {
|
||||
version, ok := entry.Options["version"]
|
||||
if !ok {
|
||||
if !ok || version == "" {
|
||||
version = "1"
|
||||
}
|
||||
mounts = append(mounts, &kvMount{
|
||||
@@ -452,9 +453,13 @@ func (c *Core) walkKvMountSecrets(ctx context.Context, m *kvMount) {
|
||||
resp, err := c.router.Route(ctx, listRequest)
|
||||
if err != nil {
|
||||
c.kvCollectionErrorCount()
|
||||
// ErrUnsupportedPath probably means that the mount is not there any more,
|
||||
// ErrUnsupportedPath probably means that the mount is not there anymore,
|
||||
// don't log those cases.
|
||||
if !strings.Contains(err.Error(), logical.ErrUnsupportedPath.Error()) {
|
||||
if !strings.Contains(err.Error(), logical.ErrUnsupportedPath.Error()) &&
|
||||
// ErrSetupReadOnly means the mount's currently being set up.
|
||||
// Nothing is wrong and there's no cause for alarm, just that we can't get data from it
|
||||
// yet. We also shouldn't log these cases
|
||||
!strings.Contains(err.Error(), logical.ErrSetupReadOnly.Error()) {
|
||||
c.logger.Error("failed to perform internal KV list", "mount_point", m.MountPoint, "error", err)
|
||||
break
|
||||
}
|
||||
@@ -485,6 +490,90 @@ func (c *Core) walkKvMountSecrets(ctx context.Context, m *kvMount) {
|
||||
}
|
||||
}
|
||||
|
||||
// getMinNamespaceSecrets is expected to be called on the output
|
||||
// of GetKvUsageMetrics to get the min number of secrets in a single namespace.
|
||||
func getMinNamespaceSecrets(mapOfNamespacesToSecrets map[string]int) int {
|
||||
currentMin := 0
|
||||
for _, n := range mapOfNamespacesToSecrets {
|
||||
if n < currentMin || currentMin == 0 {
|
||||
currentMin = n
|
||||
}
|
||||
}
|
||||
return currentMin
|
||||
}
|
||||
|
||||
// getMaxNamespaceSecrets is expected to be called on the output
|
||||
// of GetKvUsageMetrics to get the max number of secrets in a single namespace.
|
||||
func getMaxNamespaceSecrets(mapOfNamespacesToSecrets map[string]int) int {
|
||||
currentMax := 0
|
||||
for _, n := range mapOfNamespacesToSecrets {
|
||||
if n > currentMax {
|
||||
currentMax = n
|
||||
}
|
||||
}
|
||||
return currentMax
|
||||
}
|
||||
|
||||
// getTotalSecretsAcrossAllNamespaces is expected to be called on the output
|
||||
// of GetKvUsageMetrics to get the total number of secrets across namespaces.
|
||||
func getTotalSecretsAcrossAllNamespaces(mapOfNamespacesToSecrets map[string]int) int {
|
||||
total := 0
|
||||
for _, n := range mapOfNamespacesToSecrets {
|
||||
total += n
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// getMeanNamespaceSecrets is expected to be called on the output
|
||||
// of GetKvUsageMetrics to get the mean number of secrets across namespaces.
|
||||
func getMeanNamespaceSecrets(mapOfNamespacesToSecrets map[string]int) int {
|
||||
length := len(mapOfNamespacesToSecrets)
|
||||
// Avoid divide by zero:
|
||||
if length == 0 {
|
||||
return length
|
||||
}
|
||||
return getTotalSecretsAcrossAllNamespaces(mapOfNamespacesToSecrets) / length
|
||||
}
|
||||
|
||||
// GetKvUsageMetrics returns a map of namespace paths to KV secret counts within those namespaces.
|
||||
func (c *Core) GetKvUsageMetrics(ctx context.Context, kvVersion string) (map[string]int, error) {
|
||||
mounts := c.findKvMounts()
|
||||
results := make(map[string]int)
|
||||
|
||||
if kvVersion == "1" || kvVersion == "2" {
|
||||
var newMounts []*kvMount
|
||||
for _, mount := range mounts {
|
||||
if mount.Version == kvVersion {
|
||||
newMounts = append(newMounts, mount)
|
||||
}
|
||||
}
|
||||
mounts = newMounts
|
||||
} else if kvVersion != "0" {
|
||||
return results, fmt.Errorf("kv version %s not supported, must be 0, 1, or 2", kvVersion)
|
||||
}
|
||||
|
||||
for _, m := range mounts {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("context expired")
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
c.walkKvMountSecrets(ctx, m)
|
||||
|
||||
_, ok := results[m.Namespace.Path]
|
||||
if ok {
|
||||
// we need to add, not overwrite
|
||||
results[m.Namespace.Path] += m.NumSecrets
|
||||
} else {
|
||||
results[m.Namespace.Path] = m.NumSecrets
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (c *Core) kvSecretGaugeCollector(ctx context.Context) ([]metricsutil.GaugeLabelValues, error) {
|
||||
// Find all KV mounts
|
||||
mounts := c.findKvMounts()
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCoreMetrics_KvSecretGauge(t *testing.T) {
|
||||
@@ -246,6 +247,32 @@ func TestCoreMetrics_KvSecretGaugeError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestCoreMetrics_KvUsageMetricsHelperFunctions tests the KV Product Usage
|
||||
// metrics helper functions designed to be used on the output of GetKvUsageMetrics.
|
||||
func TestCoreMetrics_KvUsageMetricsHelperFunctions(t *testing.T) {
|
||||
// This is just "", but it makes it clearer
|
||||
rootNsPath := namespace.RootNamespace.Path
|
||||
|
||||
testMap := map[string]int{
|
||||
rootNsPath: 10,
|
||||
"ns1": 20,
|
||||
"ns3": 30,
|
||||
}
|
||||
|
||||
require.Equal(t, 60, getTotalSecretsAcrossAllNamespaces(testMap))
|
||||
require.Equal(t, 0, getTotalSecretsAcrossAllNamespaces(map[string]int{}))
|
||||
require.Equal(t, 10, getTotalSecretsAcrossAllNamespaces(map[string]int{rootNsPath: 10}))
|
||||
require.Equal(t, 20, getMeanNamespaceSecrets(testMap))
|
||||
require.Equal(t, 0, getMeanNamespaceSecrets(map[string]int{}))
|
||||
require.Equal(t, 10, getMeanNamespaceSecrets(map[string]int{rootNsPath: 10}))
|
||||
require.Equal(t, 30, getMaxNamespaceSecrets(testMap))
|
||||
require.Equal(t, 0, getMaxNamespaceSecrets(map[string]int{}))
|
||||
require.Equal(t, 10, getMaxNamespaceSecrets(map[string]int{rootNsPath: 10}))
|
||||
require.Equal(t, 10, getMinNamespaceSecrets(testMap))
|
||||
require.Equal(t, 0, getMinNamespaceSecrets(map[string]int{}))
|
||||
require.Equal(t, 10, getMinNamespaceSecrets(map[string]int{rootNsPath: 10}))
|
||||
}
|
||||
|
||||
func metricLabelsMatch(t *testing.T, actual []metrics.Label, expected map[string]string) {
|
||||
t.Helper()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user