func (c *Core) removeAuditReloadFunc(entry *MountEntry) {
	switch entry.Type {
	case "file":
		key := "audit_file|" + entry.Path
		c.reloadFuncsLock.Lock()
		if c.logger.IsDebug() {
			c.logger.Debug("audit: removing reload function", "path", entry.Path)
		}
		delete(c.reloadFuncs, key)
		c.reloadFuncsLock.Unlock()
	}
}
removeAuditReloadFunc removes the reload func from the working set. The
audit lock needs to be held before calling this.
package vault
import (
	"crypto/sha256"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"
	log "github.com/mgutz/logxi/v1"
	"github.com/armon/go-metrics"
	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/go-uuid"
	"github.com/hashicorp/vault/audit"
	"github.com/hashicorp/vault/helper/jsonutil"
	"github.com/hashicorp/vault/helper/salt"
	"github.com/hashicorp/vault/logical"
)
const (
	coreAuditConfigPath = "core/audit"
	auditBarrierPrefix = "audit/"
	auditTableType = "audit"
)
var (
	errLoadAuditFailed = errors.New("failed to setup audit table")
)
func (c *Core) enableAudit(entry *MountEntry) error {
	if !strings.HasSuffix(entry.Path, "/") {
		entry.Path += "/"
	}
	if entry.Path == "/" {
		return fmt.Errorf("backend path must be specified")
	}
	c.auditLock.Lock()
	defer c.auditLock.Unlock()
	for _, ent := range c.audit.Entries {
		switch {
		case strings.HasPrefix(ent.Path, entry.Path):
			fallthrough
		case strings.HasPrefix(entry.Path, ent.Path):
			return fmt.Errorf("path already in use")
		}
	}
	entryUUID, err := uuid.GenerateUUID()
	if err != nil {
		return err
	}
	entry.UUID = entryUUID
	view := NewBarrierView(c.barrier, auditBarrierPrefix+entry.UUID+"/")
	backend, err := c.newAuditBackend(entry, view, entry.Options)
	if err != nil {
		return err
	}
	newTable := c.audit.shallowClone()
	newTable.Entries = append(newTable.Entries, entry)
	if err := c.persistAudit(newTable); err != nil {
		return errors.New("failed to update audit table")
	}
	c.audit = newTable
	c.auditBroker.Register(entry.Path, backend, view)
	if c.logger.IsInfo() {
		c.logger.Info("core: enabled audit backend", "path", entry.Path, "type", entry.Type)
	}
	return nil
}
func (c *Core) disableAudit(path string) (bool, error) {
	if !strings.HasSuffix(path, "/") {
		path += "/"
	}
	c.auditLock.Lock()
	defer c.auditLock.Unlock()
	newTable := c.audit.shallowClone()
	entry := newTable.remove(path)
	if entry == nil {
		return false, fmt.Errorf("no matching backend")
	}
	c.removeAuditReloadFunc(entry)
	if err := c.persistAudit(newTable); err != nil {
		return true, errors.New("failed to update audit table")
	}
	c.audit = newTable
	c.auditBroker.Deregister(path)
	if c.logger.IsInfo() {
		c.logger.Info("core: disabled audit backend", "path", path)
	}
	return true, nil
}
func (c *Core) loadAudits() error {
	auditTable := &MountTable{}
	raw, err := c.barrier.Get(coreAuditConfigPath)
	if err != nil {
		c.logger.Error("core: failed to read audit table", "error", err)
		return errLoadAuditFailed
	}
	c.auditLock.Lock()
	defer c.auditLock.Unlock()
	if raw != nil {
		if err := jsonutil.DecodeJSON(raw.Value, auditTable); err != nil {
			c.logger.Error("core: failed to decode audit table", "error", err)
			return errLoadAuditFailed
		}
		c.audit = auditTable
	}
	if c.audit != nil {
		needPersist := false
		if c.audit.Type == "" {
			c.audit.Type = auditTableType
			needPersist = true
		}
		for _, entry := range c.audit.Entries {
			if entry.Table == "" {
				entry.Table = c.audit.Type
				needPersist = true
			}
		}
		if needPersist {
			return c.persistAudit(c.audit)
		}
		return nil
	}
	c.audit = defaultAuditTable()
	if err := c.persistAudit(c.audit); err != nil {
		return errLoadAuditFailed
	}
	return nil
}
func (c *Core) persistAudit(table *MountTable) error {
	if table.Type != auditTableType {
		c.logger.Error("core: given table to persist has wrong type", "actual_type", table.Type, "expected_type", auditTableType)
		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 audit table has wrong table value", "path", entry.Path, "entry_table_type", entry.Table, "actual_type", table.Type)
			return fmt.Errorf("invalid audit entry found, not persisting")
		}
	}
	raw, err := json.Marshal(table)
	if err != nil {
		c.logger.Error("core: failed to encode audit table", "error", err)
		return err
	}
	entry := &Entry{
		Key:   coreAuditConfigPath,
		Value: raw,
	}
	if err := c.barrier.Put(entry); err != nil {
		c.logger.Error("core: failed to persist audit table", "error", err)
		return err
	}
	return nil
}
func (c *Core) setupAudits() error {
	broker := NewAuditBroker(c.logger)
	c.auditLock.Lock()
	defer c.auditLock.Unlock()
	var successCount int
	for _, entry := range c.audit.Entries {
		view := NewBarrierView(c.barrier, auditBarrierPrefix+entry.UUID+"/")
		audit, err := c.newAuditBackend(entry, view, entry.Options)
		if err != nil {
			c.logger.Error("core: failed to create audit entry", "path", entry.Path, "error", err)
			continue
		}
		broker.Register(entry.Path, audit, view)
		successCount += 1
	}
	if len(c.audit.Entries) > 0 && successCount == 0 {
		return errLoadAuditFailed
	}
	c.auditBroker = broker
	return nil
}
func (c *Core) teardownAudits() error {
	c.auditLock.Lock()
	defer c.auditLock.Unlock()
	if c.audit != nil {
		for _, entry := range c.audit.Entries {
			c.removeAuditReloadFunc(entry)
		}
	}
	c.audit = nil
	c.auditBroker = nil
	return nil
}