mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 02:57:59 +00:00
VAULT-31075 CE changes (#28845)
This commit is contained in:
@@ -6,6 +6,7 @@ package vault
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -403,7 +404,7 @@ func (c *Core) findKvMounts() []*kvMount {
|
|||||||
for _, entry := range c.mounts.Entries {
|
for _, entry := range c.mounts.Entries {
|
||||||
if entry.Type == "kv" || entry.Type == "generic" {
|
if entry.Type == "kv" || entry.Type == "generic" {
|
||||||
version, ok := entry.Options["version"]
|
version, ok := entry.Options["version"]
|
||||||
if !ok {
|
if !ok || version == "" {
|
||||||
version = "1"
|
version = "1"
|
||||||
}
|
}
|
||||||
mounts = append(mounts, &kvMount{
|
mounts = append(mounts, &kvMount{
|
||||||
@@ -452,9 +453,13 @@ func (c *Core) walkKvMountSecrets(ctx context.Context, m *kvMount) {
|
|||||||
resp, err := c.router.Route(ctx, listRequest)
|
resp, err := c.router.Route(ctx, listRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.kvCollectionErrorCount()
|
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.
|
// 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)
|
c.logger.Error("failed to perform internal KV list", "mount_point", m.MountPoint, "error", err)
|
||||||
break
|
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) {
|
func (c *Core) kvSecretGaugeCollector(ctx context.Context) ([]metricsutil.GaugeLabelValues, error) {
|
||||||
// Find all KV mounts
|
// Find all KV mounts
|
||||||
mounts := c.findKvMounts()
|
mounts := c.findKvMounts()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
"github.com/hashicorp/vault/sdk/logical"
|
"github.com/hashicorp/vault/sdk/logical"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCoreMetrics_KvSecretGauge(t *testing.T) {
|
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) {
|
func metricLabelsMatch(t *testing.T, actual []metrics.Label, expected map[string]string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user