Store Cluster Name in Physical Storage (#26878)

* Store Cluster Name in Physical Storage

* Add changelog
This commit is contained in:
Luis (LT) Carbonell
2024-05-13 14:36:29 -04:00
committed by GitHub
parent 1fa8b1f4cf
commit 33d93652d5
3 changed files with 97 additions and 19 deletions

3
changelog/26878.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:bug
core/metrics: store cluster name in unencrypted storage to prevent blank cluster name
```

View File

@@ -1182,20 +1182,6 @@ func (c *ServerCommand) Run(args []string) int {
"in a Docker container, provide the IPC_LOCK cap to the container."))
}
inmemMetrics, metricSink, prometheusEnabled, err := configutil.SetupTelemetry(&configutil.SetupTelemetryOpts{
Config: config.Telemetry,
Ui: c.UI,
ServiceName: "vault",
DisplayName: "Vault",
UserAgent: useragent.String(),
ClusterName: config.ClusterName,
})
if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing telemetry: %s", err))
return 1
}
metricsHelper := metricsutil.NewMetricsHelper(inmemMetrics, prometheusEnabled)
// Initialize the storage backend
var backend physical.Backend
if !c.flagDev || config.Storage != nil {
@@ -1211,6 +1197,27 @@ func (c *ServerCommand) Run(args []string) int {
}
}
clusterName := config.ClusterName
// Attempt to retrieve cluster name from insecure storage
if clusterName == "" {
clusterName, err = c.readClusterNameFromInsecureStorage(backend)
}
inmemMetrics, metricSink, prometheusEnabled, err := configutil.SetupTelemetry(&configutil.SetupTelemetryOpts{
Config: config.Telemetry,
Ui: c.UI,
ServiceName: "vault",
DisplayName: "Vault",
UserAgent: useragent.String(),
ClusterName: clusterName,
})
if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing telemetry: %s", err))
return 1
}
metricsHelper := metricsutil.NewMetricsHelper(inmemMetrics, prometheusEnabled)
// Initialize the Service Discovery, if there is one
var configSR sr.ServiceRegistration
if config.ServiceRegistration != nil {
@@ -3530,6 +3537,32 @@ func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, cor
return true, nil
}
// Attempt to read the cluster name from the insecure storage.
func (c *ServerCommand) readClusterNameFromInsecureStorage(b physical.Backend) (string, error) {
ctx := context.Background()
entry, err := b.Get(ctx, "core/cluster/local/name")
if err != nil {
return "", err
}
var result map[string]interface{}
// Decode JSON data into the map
if entry != nil {
if err := jsonutil.DecodeJSON(entry.Value, &result); err != nil {
return "", fmt.Errorf("failed to decode JSON data: %w", err)
}
}
// Retrieve the value of the "name" field from the map
name, ok := result["name"].(string)
if !ok {
return "", fmt.Errorf("failed to extract name field from decoded JSON")
}
return name, nil
}
func SetStorageMigration(b physical.Backend, active bool) error {
if !active {
return b.Delete(context.Background(), storageMigrationLock)

View File

@@ -23,12 +23,14 @@ import (
uuid "github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/physical"
"github.com/hashicorp/vault/vault/cluster"
)
const (
// Storage path where the local cluster name and identifier are stored
coreLocalClusterInfoPath = "core/cluster/local/info"
coreLocalClusterNamePath = "core/cluster/local/name"
corePrivateKeyTypeP521 = "p521"
corePrivateKeyTypeED25519 = "ed25519"
@@ -61,18 +63,30 @@ type Cluster struct {
// when Vault is sealed.
func (c *Core) Cluster(ctx context.Context) (*Cluster, error) {
var cluster Cluster
var logicalEntry *logical.StorageEntry
var physicalEntry *physical.Entry
// Fetch the storage entry. This call fails when Vault is sealed.
entry, err := c.barrier.Get(ctx, coreLocalClusterInfoPath)
logicalEntry, err := c.barrier.Get(ctx, coreLocalClusterInfoPath)
if err != nil {
return nil, err
// Vault is sealed, pull cluster name from unencrypted storage
physicalEntry, err = c.physical.Get(ctx, coreLocalClusterNamePath)
if err != nil {
return nil, err
}
}
if entry == nil {
if logicalEntry == nil && physicalEntry == nil {
return &cluster, nil
}
// Decode the cluster information
if err = jsonutil.DecodeJSON(entry.Value, &cluster); err != nil {
var value []byte
if logicalEntry != nil {
value = logicalEntry.Value
} else {
value = physicalEntry.Value
}
if err = jsonutil.DecodeJSON(value, &cluster); err != nil {
return nil, fmt.Errorf("failed to decode cluster details: %w", err)
}
@@ -162,6 +176,7 @@ func (c *Core) setupCluster(ctx context.Context) error {
}
var modified bool
var generatedClusterName bool
if cluster == nil {
cluster = &Cluster{}
@@ -178,6 +193,7 @@ func (c *Core) setupCluster(ctx context.Context) error {
}
c.clusterName = fmt.Sprintf("vault-cluster-%08x", clusterNameBytes)
generatedClusterName = true
}
cluster.Name = c.clusterName
@@ -270,7 +286,7 @@ func (c *Core) setupCluster(ctx context.Context) error {
return err
}
// Store it
// Store cluster information in logical storage
err = c.barrier.Put(ctx, &logical.StorageEntry{
Key: coreLocalClusterInfoPath,
Value: rawCluster,
@@ -279,6 +295,32 @@ func (c *Core) setupCluster(ctx context.Context) error {
c.logger.Error("failed to store cluster details", "error", err)
return err
}
// Store only cluster name in physical storage, but only if name isn't provided in config
if generatedClusterName {
rawCluster, err = json.Marshal(&Cluster{Name: cluster.Name})
if err != nil {
c.logger.Error("failed to marshal cluster name", "error", err)
return err
}
err = c.physical.Put(ctx, &physical.Entry{
Key: coreLocalClusterNamePath,
Value: rawCluster,
})
if err != nil {
c.logger.Error("failed to store cluster name", "error", err)
return err
}
} else {
// check to ensure there is no entry at coreLocalClusterNamePath
err = c.physical.Delete(ctx, coreLocalClusterNamePath)
if err != nil {
c.logger.Error("failed to clear cluster name", "error", err)
return err
}
}
}
c.clusterID.Store(cluster.ID)