Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow most parts of Vault's logging to have its level changed on-the-fly #5280

Merged
merged 2 commits into from
Sep 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion builtin/logical/pki/ca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func TestBackend_CA_Steps(t *testing.T) {
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, cak.Public(), cak)
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions command/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ const (
// maxLineLength is the maximum width of any line.
maxLineLength int = 78

// notSetNamespace is a flag value for a not-set namespace
notSetNamespace = "(not set)"
// notSetValue is a flag value for a not-set value
notSetValue = "(not set)"
)

// reRemoveWhitespace is a regular expression for stripping whitespace from
Expand Down Expand Up @@ -129,10 +129,10 @@ func (c *BaseCommand) Client() (*api.Client, error) {

// flagNS takes precedence over flagNamespace. After resolution, point both
// flags to the same value to be able to use them interchangeably anywhere.
if c.flagNS != notSetNamespace {
if c.flagNS != notSetValue {
c.flagNamespace = c.flagNS
}
if c.flagNamespace != notSetNamespace {
if c.flagNamespace != notSetValue {
client.SetNamespace(namespace.Canonicalize(c.flagNamespace))
}

Expand Down Expand Up @@ -256,7 +256,7 @@ func (c *BaseCommand) flagSet(bit FlagSetBit) *FlagSets {
f.StringVar(&StringVar{
Name: "namespace",
Target: &c.flagNamespace,
Default: notSetNamespace, // this can never be a real value
Default: notSetValue, // this can never be a real value
EnvVar: "VAULT_NAMESPACE",
Completion: complete.PredictAnything,
Usage: "The namespace to use for the command. Setting this is not " +
Expand All @@ -267,7 +267,7 @@ func (c *BaseCommand) flagSet(bit FlagSetBit) *FlagSets {
f.StringVar(&StringVar{
Name: "ns",
Target: &c.flagNS,
Default: notSetNamespace, // this can never be a real value
Default: notSetValue, // this can never be a real value
Completion: complete.PredictAnything,
Hidden: true,
Usage: "Alias for -namespace. This takes precedence over -namespace.",
Expand Down
87 changes: 81 additions & 6 deletions command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func (c *ServerCommand) Flags() *FlagSets {
f.StringVar(&StringVar{
Name: "log-level",
Target: &c.flagLogLevel,
Default: "info",
Default: notSetValue,
EnvVar: "VAULT_LOG_LEVEL",
Completion: complete.PredictSet("trace", "debug", "info", "warn", "err"),
Usage: "Log verbosity level. Supported values (in order of detail) are " +
Expand Down Expand Up @@ -307,8 +307,12 @@ func (c *ServerCommand) Run(args []string) int {
c.logWriter = os.Stdout
}
var level log.Level
var logLevelWasNotSet bool
c.flagLogLevel = strings.ToLower(strings.TrimSpace(c.flagLogLevel))
switch c.flagLogLevel {
case notSetValue:
logLevelWasNotSet = true
level = log.Info
case "trace":
level = log.Trace
case "debug":
Expand All @@ -334,10 +338,7 @@ func (c *ServerCommand) Run(args []string) int {
c.logger = logging.NewVaultLoggerWithWriter(c.logWriter, level)
}

grpclog.SetLogger(&grpclogFaker{
logger: c.logger.Named("grpclogfaker"),
log: os.Getenv("VAULT_GRPC_LOGGING") != "",
})
allLoggers := []log.Logger{c.logger}

// Automatically enable dev mode if other dev flags are provided.
if c.flagDevHA || c.flagDevTransactional || c.flagDevLeasedKV || c.flagDevThreeNode || c.flagDevFourCluster {
Expand Down Expand Up @@ -390,6 +391,32 @@ func (c *ServerCommand) Run(args []string) int {
return 1
}

if config.LogLevel != "" && logLevelWasNotSet {
configLogLevel := strings.ToLower(strings.TrimSpace(config.LogLevel))
switch configLogLevel {
case "trace":
c.logger.SetLevel(log.Trace)
case "debug":
c.logger.SetLevel(log.Debug)
case "notice", "info", "":
c.logger.SetLevel(log.Info)
case "warn", "warning":
c.logger.SetLevel(log.Warn)
case "err", "error":
c.logger.SetLevel(log.Error)
default:
c.UI.Error(fmt.Sprintf("Unknown log level: %s", config.LogLevel))
return 1
}
}

namedGRPCLogFaker := c.logger.Named("grpclogfaker")
allLoggers = append(allLoggers, namedGRPCLogFaker)
grpclog.SetLogger(&grpclogFaker{
logger: namedGRPCLogFaker,
log: os.Getenv("VAULT_GRPC_LOGGING") != "",
})

// Ensure that a backend is provided
if config.Storage == nil {
c.UI.Output("A storage backend must be specified")
Expand Down Expand Up @@ -423,7 +450,9 @@ func (c *ServerCommand) Run(args []string) int {
c.UI.Error(fmt.Sprintf("Unknown storage type %s", config.Storage.Type))
return 1
}
backend, err := factory(config.Storage.Config, c.logger.Named("storage."+config.Storage.Type))
namedStorageLogger := c.logger.Named("storage." + config.Storage.Type)
allLoggers = append(allLoggers, namedStorageLogger)
backend, err := factory(config.Storage.Config, namedStorageLogger)
if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing storage of type %s: %s", config.Storage.Type, err))
return 1
Expand Down Expand Up @@ -469,6 +498,7 @@ func (c *ServerCommand) Run(args []string) int {
PluginDirectory: config.PluginDirectory,
EnableUI: config.EnableUI,
EnableRaw: config.EnableRawEndpoint,
AllLoggers: allLoggers,
}
if c.flagDev {
coreConfig.DevToken = c.flagDevRootTokenID
Expand Down Expand Up @@ -1039,6 +1069,51 @@ CLUSTER_SYNTHESIS_COMPLETE:

case <-c.SighupCh:
c.UI.Output("==> Vault reload triggered")

// Check for new log level
var config *server.Config
var level log.Level
for _, path := range c.flagConfigs {
current, err := server.LoadConfig(path, c.logger)
if err != nil {
c.logger.Error("could not reload config", "path", path, "error", err)
goto RUNRELOADFUNCS
}

if config == nil {
config = current
} else {
config = config.Merge(current)
}
}

// Ensure at least one config was found.
if config == nil {
c.logger.Error("no config found at reload time")
goto RUNRELOADFUNCS
}

if config.LogLevel != "" {
configLogLevel := strings.ToLower(strings.TrimSpace(config.LogLevel))
switch configLogLevel {
case "trace":
level = log.Trace
case "debug":
level = log.Debug
case "notice", "info", "":
level = log.Info
case "warn", "warning":
level = log.Warn
case "err", "error":
level = log.Error
default:
c.logger.Error("unknown log level found on reload", "level", config.LogLevel)
goto RUNRELOADFUNCS
}
core.SetLogLevel(level)
}

RUNRELOADFUNCS:
if err := c.Reload(c.reloadFuncsLock, c.reloadFuncs, c.flagConfigs); err != nil {
c.UI.Error(fmt.Sprintf("Error(s) were encountered during reload: %s", err))
}
Expand Down
7 changes: 7 additions & 0 deletions command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ type Config struct {

PluginDirectory string `hcl:"plugin_directory"`

LogLevel string `hcl:"log_level"`

PidFile string `hcl:"pid_file"`
EnableRawEndpoint bool `hcl:"-"`
EnableRawEndpointRaw interface{} `hcl:"raw_storage_endpoint"`
Expand Down Expand Up @@ -299,6 +301,11 @@ func (c *Config) Merge(c2 *Config) *Config {
result.DefaultMaxRequestDuration = c2.DefaultMaxRequestDuration
}

result.LogLevel = c.LogLevel
if c2.LogLevel != "" {
result.LogLevel = c2.LogLevel
}

result.ClusterName = c.ClusterName
if c2.ClusterName != "" {
result.ClusterName = c2.ClusterName
Expand Down
2 changes: 1 addition & 1 deletion helper/storagepacker/storagepacker.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ func NewStoragePacker(view logical.Storage, logger log.Logger, viewPrefix string
packer := &StoragePacker{
view: view,
viewPrefix: viewPrefix,
logger: logger.Named("storagepacker"),
logger: logger,
storageLocks: locksutil.CreateLocks(),
}

Expand Down
5 changes: 4 additions & 1 deletion vault/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,9 @@ func (c *Core) persistAudit(ctx context.Context, table *MountTable, localOnly bo
// setupAudit is invoked after we've loaded the audit able to
// initialize the audit backends
func (c *Core) setupAudits(ctx context.Context) error {
broker := NewAuditBroker(c.baseLogger.Named("audit"))
brokerLogger := c.baseLogger.Named("audit")
c.AddLogger(brokerLogger)
broker := NewAuditBroker(brokerLogger)

c.auditLock.Lock()
defer c.auditLock.Unlock()
Expand Down Expand Up @@ -413,6 +415,7 @@ func (c *Core) newAuditBackend(ctx context.Context, entry *MountEntry, view logi
}

auditLogger := c.baseLogger.Named("audit")
c.AddLogger(auditLogger)

switch entry.Type {
case "file":
Expand Down
4 changes: 3 additions & 1 deletion vault/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,9 +578,11 @@ func (c *Core) newCredentialBackend(ctx context.Context, entry *MountEntry, sysV
conf["plugin_name"] = entry.Config.PluginName
}

authLogger := c.baseLogger.Named(fmt.Sprintf("auth.%s.%s", t, entry.Accessor))
c.AddLogger(authLogger)
config := &logical.BackendConfig{
StorageView: view,
Logger: c.baseLogger.Named(fmt.Sprintf("auth.%s.%s", t, entry.Accessor)),
Logger: authLogger,
Config: conf,
System: sysView,
BackendUUID: entry.BackendAwareUUID,
Expand Down
44 changes: 38 additions & 6 deletions vault/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ type Core struct {

// Stores any funcs that should be run on successful postUnseal
postUnsealFuncs []func()

// Stores loggers so we can reset the level
allLoggers []log.Logger
allLoggersLock sync.RWMutex
}

// CoreConfig is used to parameterize a core
Expand Down Expand Up @@ -420,6 +424,8 @@ type CoreConfig struct {

ReloadFuncs *map[string][]reload.ReloadFunc
ReloadFuncsLock *sync.RWMutex

AllLoggers []log.Logger
}

// NewCore is used to construct a new core
Expand Down Expand Up @@ -488,9 +494,11 @@ func NewCore(conf *CoreConfig) (*Core, error) {
activeNodeReplicationState: new(uint32),
keepHALockOnStepDown: new(uint32),
activeContextCancelFunc: new(atomic.Value),
allLoggers: conf.AllLoggers,
}

atomic.StoreUint32(c.sealed, 1)
c.allLoggers = append(c.allLoggers, c.logger)

atomic.StoreUint32(c.replicationState, uint32(consts.ReplicationDRDisabled|consts.ReplicationPerformanceDisabled))
c.localClusterCert.Store(([]byte)(nil))
Expand Down Expand Up @@ -520,15 +528,19 @@ func NewCore(conf *CoreConfig) (*Core, error) {
}
c.seal.SetCore(c)

c.sealUnwrapper = NewSealUnwrapper(phys, c.baseLogger.Named("storage.sealunwrapper"))
unwrapperLogger := c.baseLogger.Named("storage.sealunwrapper")
c.allLoggers = append(c.allLoggers, unwrapperLogger)
c.sealUnwrapper = NewSealUnwrapper(phys, unwrapperLogger)

var ok bool

// Wrap the physical backend in a cache layer if enabled
cacheLogger := c.baseLogger.Named("storage.cache")
c.allLoggers = append(c.allLoggers, cacheLogger)
if txnOK {
c.physical = physical.NewTransactionalCache(c.sealUnwrapper, conf.CacheSize, c.baseLogger.Named("storage.cache"))
c.physical = physical.NewTransactionalCache(c.sealUnwrapper, conf.CacheSize, cacheLogger)
} else {
c.physical = physical.NewCache(c.sealUnwrapper, conf.CacheSize, c.baseLogger.Named("storage.cache"))
c.physical = physical.NewCache(c.sealUnwrapper, conf.CacheSize, cacheLogger)
}
c.physicalCache = c.physical.(physical.ToggleablePurgemonster)

Expand Down Expand Up @@ -585,15 +597,19 @@ func NewCore(conf *CoreConfig) (*Core, error) {
}
logicalBackends["cubbyhole"] = CubbyholeBackendFactory
logicalBackends["system"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
b := NewSystemBackend(c, conf.Logger.Named("system"))
sysBackendLogger := conf.Logger.Named("system")
c.AddLogger(sysBackendLogger)
b := NewSystemBackend(c, sysBackendLogger)
if err := b.Setup(ctx, config); err != nil {
return nil, err
}
return b, nil
}

logicalBackends["identity"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
return NewIdentityStore(ctx, c, config, conf.Logger.Named("identity"))
identityLogger := conf.Logger.Named("identity")
c.AddLogger(identityLogger)
return NewIdentityStore(ctx, c, config, identityLogger)
}

c.logicalBackends = logicalBackends
Expand All @@ -603,7 +619,9 @@ func NewCore(conf *CoreConfig) (*Core, error) {
credentialBackends[k] = f
}
credentialBackends["token"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
return NewTokenStore(ctx, conf.Logger.Named("token"), c, config)
tsLogger := conf.Logger.Named("token")
c.AddLogger(tsLogger)
return NewTokenStore(ctx, tsLogger, c, config)
}
c.credentialBackends = credentialBackends

Expand Down Expand Up @@ -1456,3 +1474,17 @@ func (c *Core) RouterAccess() *RouterAccess {
func (c *Core) IsDRSecondary() bool {
return c.ReplicationState().HasState(consts.ReplicationDRSecondary)
}

func (c *Core) AddLogger(logger log.Logger) {
c.allLoggersLock.Lock()
defer c.allLoggersLock.Unlock()
c.allLoggers = append(c.allLoggers, logger)
}

func (c *Core) SetLogLevel(level log.Level) {
c.allLoggersLock.RLock()
defer c.allLoggersLock.RUnlock()
for _, logger := range c.allLoggers {
logger.SetLevel(level)
}
}
5 changes: 4 additions & 1 deletion vault/expiration.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ func (c *Core) setupExpiration() error {
view := c.systemBarrierView.SubView(expirationSubPath)

// Create the manager
mgr := NewExpirationManager(c, view, c.baseLogger.Named("expiration"))
expLogger := c.baseLogger.Named("expiration")
c.AddLogger(expLogger)
mgr := NewExpirationManager(c, view, expLogger)
c.expiration = mgr

// Link the token store to this
Expand Down Expand Up @@ -194,6 +196,7 @@ func (m *ExpirationManager) Tidy() error {
var tidyErrors *multierror.Error

logger := m.logger.Named("tidy")
m.core.AddLogger(logger)

if !atomic.CompareAndSwapInt32(m.tidyLock, 0, 1) {
logger.Warn("tidy operation on leases is already in progress")
Expand Down
8 changes: 6 additions & 2 deletions vault/identity_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@ func NewIdentityStore(ctx context.Context, core *Core, config *logical.BackendCo
core: core,
}

iStore.entityPacker, err = storagepacker.NewStoragePacker(iStore.view, iStore.logger, "")
entitiesPackerLogger := iStore.logger.Named("storagepacker").Named("entities")
core.AddLogger(entitiesPackerLogger)
groupsPackerLogger := iStore.logger.Named("storagepacker").Named("groups")
core.AddLogger(groupsPackerLogger)
iStore.entityPacker, err = storagepacker.NewStoragePacker(iStore.view, entitiesPackerLogger, "")
if err != nil {
return nil, errwrap.Wrapf("failed to create entity packer: {{err}}", err)
}

iStore.groupPacker, err = storagepacker.NewStoragePacker(iStore.view, iStore.logger, groupBucketsPrefix)
iStore.groupPacker, err = storagepacker.NewStoragePacker(iStore.view, groupsPackerLogger, groupBucketsPrefix)
if err != nil {
return nil, errwrap.Wrapf("failed to create group packer: {{err}}", err)
}
Expand Down
Loading