func defaultAuthTable() *MountTable {
	table := &MountTable{
		Type: credentialTableType,
	}
	tokenUUID, err := uuid.GenerateUUID()
	if err != nil {
		panic(fmt.Sprintf("could not generate UUID for default auth table token entry: %v", err))
	}
	tokenAuth := &MountEntry{
		Table:       credentialTableType,
		Path:        "token/",
		Type:        "token",
		Description: "token based credentials",
		UUID:        tokenUUID,
	}
	table.Entries = append(table.Entries, tokenAuth)
	return table
}
defaultAuthTable creates a default auth table
package vault
import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"github.com/hashicorp/go-uuid"
	"github.com/hashicorp/vault/helper/jsonutil"
	"github.com/hashicorp/vault/logical"
)
const (
	coreAuthConfigPath = "core/auth"
	credentialBarrierPrefix = "auth/"
	credentialRoutePrefix = "auth/"
	credentialTableType = "auth"
)
var (
	errLoadAuthFailed = errors.New("failed to setup auth table")
)
func (c *Core) enableCredential(entry *MountEntry) error {
	if !strings.HasSuffix(entry.Path, "/") {
		entry.Path += "/"
	}
	if entry.Path == "/" {
		return fmt.Errorf("backend path must be specified")
	}
	c.authLock.Lock()
	defer c.authLock.Unlock()
	for _, ent := range c.auth.Entries {
		switch {
		case strings.HasPrefix(ent.Path, entry.Path):
			fallthrough
		case strings.HasPrefix(entry.Path, ent.Path):
			return logical.CodedError(409, "path is already in use")
		}
	}
	if entry.Type == "token" {
		return fmt.Errorf("token credential backend cannot be instantiated")
	}
	entryUUID, err := uuid.GenerateUUID()
	if err != nil {
		return err
	}
	entry.UUID = entryUUID
	view := NewBarrierView(c.barrier, credentialBarrierPrefix+entry.UUID+"/")
	backend, err := c.newCredentialBackend(entry.Type, c.mountEntrySysView(entry), view, nil)
	if err != nil {
		return err
	}
	newTable := c.auth.shallowClone()
	newTable.Entries = append(newTable.Entries, entry)
	if err := c.persistAuth(newTable); err != nil {
		return errors.New("failed to update auth table")
	}
	c.auth = newTable
	path := credentialRoutePrefix + entry.Path
	if err := c.router.Mount(backend, path, entry, view); err != nil {
		return err
	}
	if c.logger.IsInfo() {
		c.logger.Info("core: enabled credential backend", "path", entry.Path, "type", entry.Type)
	}
	return nil
}
func (c *Core) disableCredential(path string) (bool, error) {
	if !strings.HasSuffix(path, "/") {
		path += "/"
	}
	if path == "token/" {
		return true, fmt.Errorf("token credential backend cannot be disabled")
	}
	fullPath := credentialRoutePrefix + path
	view := c.router.MatchingStorageView(fullPath)
	if view == nil {
		return false, fmt.Errorf("no matching backend")
	}
	c.authLock.Lock()
	defer c.authLock.Unlock()
	if err := c.taintCredEntry(path); err != nil {
		return true, err
	}
	if err := c.router.Taint(fullPath); err != nil {
		return true, err
	}
	if err := c.expiration.RevokePrefix(fullPath); err != nil {
		return true, err
	}
	if err := c.router.Unmount(fullPath); err != nil {
		return true, err
	}
	if view != nil {
		if err := ClearView(view); err != nil {
			return true, err
		}
	}
	if err := c.removeCredEntry(path); err != nil {
		return true, err
	}
	if c.logger.IsInfo() {
		c.logger.Info("core: disabled credential backend", "path", path)
	}
	return true, nil
}
func (c *Core) removeCredEntry(path string) error {
	newTable := c.auth.shallowClone()
	newTable.remove(path)
	if err := c.persistAuth(newTable); err != nil {
		return errors.New("failed to update auth table")
	}
	c.auth = newTable
	return nil
}
func (c *Core) taintCredEntry(path string) error {
	found := c.auth.setTaint(path, true)
	if !found {
		return fmt.Errorf("no matching backend")
	}
	if err := c.persistAuth(c.auth); err != nil {
		return errors.New("failed to update auth table")
	}
	return nil
}
func (c *Core) loadCredentials() error {
	authTable := &MountTable{}
	raw, err := c.barrier.Get(coreAuthConfigPath)
	if err != nil {
		c.logger.Error("core: failed to read auth table", "error", err)
		return errLoadAuthFailed
	}
	c.authLock.Lock()
	defer c.authLock.Unlock()
	if raw != nil {
		if err := jsonutil.DecodeJSON(raw.Value, authTable); err != nil {
			c.logger.Error("core: failed to decode auth table", "error", err)
			return errLoadAuthFailed
		}
		c.auth = authTable
	}
	if c.auth != nil {
		needPersist := false
		if c.auth.Type == "" {
			c.auth.Type = credentialTableType
			needPersist = true
		}
		for _, entry := range c.auth.Entries {
			if entry.Table == "" {
				entry.Table = c.auth.Type
				needPersist = true
			}
		}
		if needPersist {
			return c.persistAuth(c.auth)
		}
		return nil
	}
	c.auth = defaultAuthTable()
	if err := c.persistAuth(c.auth); err != nil {
		c.logger.Error("core: failed to persist auth table", "error", err)
		return errLoadAuthFailed
	}
	return nil
}
func (c *Core) persistAuth(table *MountTable) error {
	if table.Type != credentialTableType {
		c.logger.Error("core: given table to persist has wrong type", "actual_type", table.Type, "expected_type", credentialTableType)
		return fmt.Errorf("invalid table type given, not persisting")
	}
	for _, entry := range table.Entries {
		if entry.Table != table.Type {
			c.logger.Error("core: given entry to persist in auth table has wrong table value", "path", entry.Path, "entry_table_type", entry.Table, "actual_type", table.Type)
			return fmt.Errorf("invalid auth entry found, not persisting")
		}
	}
	raw, err := json.Marshal(table)
	if err != nil {
		c.logger.Error("core: failed to encode auth table", "error", err)
		return err
	}
	entry := &Entry{
		Key:   coreAuthConfigPath,
		Value: raw,
	}
	if err := c.barrier.Put(entry); err != nil {
		c.logger.Error("core: failed to persist auth table", "error", err)
		return err
	}
	return nil
}
func (c *Core) setupCredentials() error {
	var backend logical.Backend
	var view *BarrierView
	var err error
	var persistNeeded bool
	c.authLock.Lock()
	defer c.authLock.Unlock()
	for _, entry := range c.auth.Entries {
		if strings.HasPrefix(entry.Path, credentialRoutePrefix) {
			entry.Path = strings.TrimPrefix(entry.Path, credentialRoutePrefix)
			persistNeeded = true
		}
		view = NewBarrierView(c.barrier, credentialBarrierPrefix+entry.UUID+"/")
		backend, err = c.newCredentialBackend(entry.Type, c.mountEntrySysView(entry), view, nil)
		if err != nil {
			c.logger.Error("core: failed to create credential entry", "path", entry.Path, "error", err)
			return errLoadAuthFailed
		}
		path := credentialRoutePrefix + entry.Path
		err = c.router.Mount(backend, path, entry, view)
		if err != nil {
			c.logger.Error("core: failed to mount auth entry", "path", entry.Path, "error", err)
			return errLoadAuthFailed
		}
		if entry.Tainted {
			c.router.Taint(path)
		}
		if entry.Type == "token" {
			c.tokenStore = backend.(*TokenStore)
			c.router.tokenStoreSalt = c.tokenStore.salt
			c.tokenStore.cubbyholeBackend = c.router.MatchingBackend("cubbyhole/").(*CubbyholeBackend)
		}
	}
	if persistNeeded {
		return c.persistAuth(c.auth)
	}
	return nil
}
func (c *Core) teardownCredentials() error {
	c.authLock.Lock()
	defer c.authLock.Unlock()
	if c.auth != nil {
		authTable := c.auth.shallowClone()
		for _, e := range authTable.Entries {
			prefix := e.Path
			b, ok := c.router.root.Get(prefix)
			if ok {
				b.(*routeEntry).backend.Cleanup()
			}
		}
	}
	c.auth = nil
	c.tokenStore = nil
	return nil
}
func (c *Core) newCredentialBackend(
	t string, sysView logical.SystemView, view logical.Storage, conf map[string]string) (logical.Backend, error) {
	f, ok := c.credentialBackends[t]
	if !ok {
		return nil, fmt.Errorf("unknown backend type: %s", t)
	}
	config := &logical.BackendConfig{
		StorageView: view,
		Logger:      c.logger,
		Config:      conf,
		System:      sysView,
	}
	b, err := f(config)
	if err != nil {
		return nil, err
	}
	return b, nil
}