open-vault/vault/cluster.go
2016-08-10 15:22:12 -04:00

119 lines
3 KiB
Go

package vault
import (
"encoding/json"
"fmt"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/jsonutil"
)
const (
// Storage path where the local cluster name and identifier are stored
coreLocalClusterInfoPath = "core/cluster/local/info"
)
// Structure representing the storage entry that holds cluster information
type Cluster struct {
// Name of the cluster
Name string `json:"name" structs:"name" mapstructure:"name"`
// Identifier of the cluster
ID string `json:"id" structs:"id" mapstructure:"id"`
}
// Cluster fetches the details of either local or global cluster based on the
// input. This method errors out when Vault is sealed.
func (c *Core) Cluster() (*Cluster, error) {
var cluster Cluster
// Fetch the storage entry. This call fails when Vault is sealed.
entry, err := c.barrier.Get(coreLocalClusterInfoPath)
if err != nil {
return nil, err
}
if entry == nil {
return &cluster, nil
}
// Decode the cluster information
if err = jsonutil.DecodeJSON(entry.Value, &cluster); err != nil {
return nil, fmt.Errorf("failed to decode cluster details: %v", err)
}
// Set in config file
if c.clusterName != "" {
cluster.Name = c.clusterName
}
return &cluster, nil
}
// setupCluster creates storage entries for holding Vault cluster information.
// Entries will be created only if they are not already present. If clusterName
// is not supplied, this method will auto-generate it.
func (c *Core) setupCluster() error {
// Check if storage index is already present or not
cluster, err := c.Cluster()
if err != nil {
c.logger.Printf("[ERR] core: failed to get cluster details: %v", err)
return err
}
if cluster == nil {
cluster = &Cluster{}
}
var modified bool
if cluster.Name == "" {
// If cluster name is not supplied, generate one
if c.clusterName == "" {
c.logger.Printf("[TRACE] core: cluster name not found/set, generating new")
clusterNameBytes, err := uuid.GenerateRandomBytes(4)
if err != nil {
c.logger.Printf("[ERR] core: failed to generate cluster name: %v", err)
return err
}
c.clusterName = fmt.Sprintf("vault-cluster-%08x", clusterNameBytes)
}
cluster.Name = c.clusterName
c.logger.Printf("[DEBUG] core: cluster name set to %s", cluster.Name)
modified = true
}
if cluster.ID == "" {
// Generate a clusterID
clusterID, err := uuid.GenerateUUID()
if err != nil {
c.logger.Printf("[ERR] core: failed to generate cluster identifier: %v", err)
return err
}
cluster.ID = clusterID
c.logger.Printf("[DEBUG] core: cluster ID set to %s", cluster.ID)
modified = true
}
if modified {
// Encode the cluster information into as a JSON string
rawCluster, err := json.Marshal(cluster)
if err != nil {
c.logger.Printf("[ERR] core: failed to encode cluster details: %v", err)
return err
}
// Store it
err = c.barrier.Put(&Entry{
Key: coreLocalClusterInfoPath,
Value: rawCluster,
})
if err != nil {
c.logger.Printf("[ERR] core: failed to store cluster details: %v", err)
return err
}
}
return nil
}