vault: Loading mount tables on start

This commit is contained in:
Armon Dadgar 2015-03-11 15:19:41 -07:00
parent 370693ebb4
commit f54e4e0f6a
3 changed files with 120 additions and 1 deletions

View File

@ -87,6 +87,10 @@ type Core struct {
// the threshold number of parts is available.
unlockParts [][]byte
// mounts is loaded after unseal since it is a protected
// configuration
mounts *MountTable
logger *log.Logger
}
@ -339,6 +343,13 @@ func (c *Core) Unseal(key []byte) (bool, error) {
return false, err
}
// Do post-unseal setup
if err := c.postUnseal(); err != nil {
c.logger.Printf("[ERR] core: post-unseal setup failed: %v", err)
c.barrier.Seal()
return false, err
}
// Success!
c.logger.Printf("[INFO] core: vault is unsealed")
c.sealed = false
@ -357,3 +368,14 @@ func (c *Core) Seal() error {
c.sealed = true
return c.barrier.Seal()
}
// postUnseal is invoked after the barrier is unsealed, but before
// allowing any user operations. This allows us to setup any state that
// requires the Vault to be unsealed such as mount tables, logical backends,
// credential stores, etc.
func (c *Core) postUnseal() error {
if err := c.loadMounts(); err != nil {
return err
}
return nil
}

View File

@ -279,7 +279,7 @@ func TestCore_Route_Sealed(t *testing.T) {
// Should not route anything
req := &Request{
Operation: ReadOperation,
Path: "sys/test",
Path: "sys/mounts",
}
_, err := c.HandleRequest(req)
if err != ErrSealed {

97
vault/mount.go Normal file
View File

@ -0,0 +1,97 @@
package vault
import (
"encoding/json"
"errors"
)
const (
// coreMountConfigPath is used to store the mount configuration.
// Mounts are protected within the Vault itself, which means they
// can only be viewed or modified after an unseal.
coreMountConfigPath = "core/mounts"
)
// MountTable is used to represent the internal mount table
type MountTable struct {
Entries []*MountEntry `json:"entries"`
}
// MountEntry is used to represent a mount table entry
type MountEntry struct {
Path string `json:"path"` // Mount Path
Type string `json:"type"` // Logical backend Type
Description string `json:"description"` // User-provided description
UUID string `json:"uuid"` // Barrier view UUID
}
// loadMounts is invoked as part of postUnseal to load the mount table
func (c *Core) loadMounts() error {
// Load the existing mount table
raw, err := c.barrier.Get(coreMountConfigPath)
if err != nil {
c.logger.Printf("[ERR] core: failed to read mount table: %v", err)
return errors.New("failed to setup mount table")
}
if raw != nil {
if err := json.Unmarshal(raw.Value, c.mounts); err != nil {
c.logger.Printf("[ERR] core: failed to decode mount table: %v", err)
return errors.New("failed to setup mount table")
}
}
// Done if we have restored the mount table
if c.mounts != nil {
return nil
}
// Create and persist the default mount table
c.mounts = defaultMountTable()
if err := c.persistMounts(); err != nil {
return errors.New("failed to setup mount table")
}
return nil
}
// persistMounts is used to persist the mount table after modification
func (c *Core) persistMounts() error {
// Marshal the table
raw, err := json.Marshal(c.mounts)
if err != nil {
c.logger.Printf("[ERR] core: failed to encode mount table: %v", err)
return err
}
// Create an entry
entry := &Entry{
Key: coreMountConfigPath,
Value: raw,
}
// Write to the physical backend
if err := c.barrier.Put(entry); err != nil {
c.logger.Printf("[ERR] core: failed to persist mount table: %v", err)
return err
}
return nil
}
// defaultMountTable creates a default mount table
func defaultMountTable() *MountTable {
table := &MountTable{}
genericMount := &MountEntry{
Path: "secret/",
Type: "generic",
Description: "generic secret storage",
UUID: generateUUID(),
}
sysMount := &MountEntry{
Path: "sys/",
Type: "system",
Description: "system endpoints used for control, policy and debugging",
UUID: generateUUID(),
}
table.Entries = append(table.Entries, genericMount)
table.Entries = append(table.Entries, sysMount)
return table
}