2016-07-26 06:25:33 +00:00
|
|
|
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
|
2016-07-26 13:18:38 +00:00
|
|
|
coreClusterPath = "core/cluster/local"
|
2016-07-26 06:25:33 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// 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.
|
2016-07-26 13:18:38 +00:00
|
|
|
func (c *Core) Cluster() (*Cluster, error) {
|
2016-07-26 06:25:33 +00:00
|
|
|
// Fetch the storage entry. This call fails when Vault is sealed.
|
2016-07-26 13:18:38 +00:00
|
|
|
entry, err := c.barrier.Get(coreClusterPath)
|
2016-07-26 06:25:33 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if entry == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode the cluster information
|
|
|
|
var cluster Cluster
|
|
|
|
if err = jsonutil.DecodeJSON(entry.Value, &cluster); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to decode cluster details: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &cluster, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// setupCluster creates storage entries for holding Vault cluster information.
|
2016-07-26 13:18:38 +00:00
|
|
|
// Entries will be created only if they are not already present. If clusterName
|
|
|
|
// is not supplied, this method will auto-generate it.
|
2016-07-26 06:25:33 +00:00
|
|
|
func (c *Core) setupCluster() error {
|
|
|
|
// Check if storage index is already present or not
|
2016-07-26 13:18:38 +00:00
|
|
|
cluster, err := c.Cluster()
|
2016-07-26 06:25:33 +00:00
|
|
|
if err != nil {
|
|
|
|
c.logger.Printf("[ERR] core: failed to get cluster details: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if cluster != nil {
|
|
|
|
// If index is already present, don't update it
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-07-26 13:18:38 +00:00
|
|
|
// If cluster name is not supplied, generate one
|
|
|
|
if c.clusterName == "" {
|
2016-07-26 06:25:33 +00:00
|
|
|
clusterNameBytes, err := uuid.GenerateRandomBytes(4)
|
|
|
|
if err != nil {
|
|
|
|
c.logger.Printf("[ERR] core: failed to generate cluster name: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
2016-07-26 18:05:27 +00:00
|
|
|
c.clusterName = fmt.Sprintf("vault-cluster-%08x", clusterNameBytes)
|
2016-07-26 06:25:33 +00:00
|
|
|
}
|
|
|
|
|
2016-07-26 13:18:38 +00:00
|
|
|
// Generate a clusterID
|
|
|
|
clusterID, err := uuid.GenerateUUID()
|
|
|
|
if err != nil {
|
|
|
|
c.logger.Printf("[ERR] core: failed to generate cluster identifier: %v", err)
|
|
|
|
return err
|
2016-07-26 06:25:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Encode the cluster information into as a JSON string
|
|
|
|
rawCluster, err := json.Marshal(&Cluster{
|
2016-07-26 13:18:38 +00:00
|
|
|
Name: c.clusterName,
|
2016-07-26 06:25:33 +00:00
|
|
|
ID: clusterID,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
c.logger.Printf("[ERR] core: failed to encode cluster details: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store it
|
|
|
|
return c.barrier.Put(&Entry{
|
2016-07-26 13:18:38 +00:00
|
|
|
Key: coreClusterPath,
|
2016-07-26 06:25:33 +00:00
|
|
|
Value: rawCluster,
|
|
|
|
})
|
2016-07-26 13:18:38 +00:00
|
|
|
|
2016-07-26 06:25:33 +00:00
|
|
|
}
|