mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +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
	 Violet Hynes
					Violet Hynes