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

VAULT-8732: Add log-file to Vault Agent #17841

Merged
merged 25 commits into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ffaff37
Started work on adding log-file support to Agent
peteski22 Nov 7, 2022
e165ca0
Basic HCL test - added log-file
peteski22 Nov 7, 2022
8a3ab39
Basic test for logfile
peteski22 Nov 7, 2022
6d2fa5f
Logger tests
peteski22 Nov 7, 2022
73d396f
changelog
peteski22 Nov 7, 2022
4955ac0
make fmt
peteski22 Nov 7, 2022
511753e
updated raft-autopilot to v0.2.0
peteski22 Nov 8, 2022
dda4b1b
Update changelog/17841.txt
peteski22 Nov 8, 2022
4a82d0e
use T.tempDir()
peteski22 Nov 8, 2022
9a75216
Removed unneeded BytesWritten as we're not interested in tracking this
peteski22 Nov 8, 2022
e298b82
Removed reliance on consul testing helpers
peteski22 Nov 8, 2022
77a580d
Remember to return when we error
peteski22 Nov 9, 2022
ad8dc49
Allow log file to be picked up and appended
peteski22 Nov 9, 2022
e3ef2fd
Use NewLogFile everywhere
peteski22 Nov 9, 2022
3af776f
Tried to pull out the config aggregation from Agent.Run
peteski22 Nov 9, 2022
7094a07
Add test failure msg.
peteski22 Nov 9, 2022
dbf88a1
Clutching at straws before rolling back a few commits.
peteski22 Nov 9, 2022
3b2fb00
fmt (frustration creeping in)
peteski22 Nov 9, 2022
7cd7db6
Try to clean up after tests nicely
peteski22 Nov 9, 2022
6ddae7e
Typos in `sc` cmd
peteski22 Nov 10, 2022
3fe4a6e
Try to fix mad whitespace auto-adjustments (part 1)
peteski22 Nov 11, 2022
4883a11
Whitespace fixing part 2
peteski22 Nov 11, 2022
5eb50e3
Merge branch 'main' of github.com:hashicorp/vault
peteski22 Nov 11, 2022
d8e3362
Merge branch 'main' into VAULT-8732-log-file-parameter
peteski22 Nov 11, 2022
08be24b
go mod tidy
peteski22 Nov 11, 2022
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,4 @@ website/components/node_modules

.buildcache/
.releaser/
*.log
3 changes: 3 additions & 0 deletions changelog/17841.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
logging: Vault Agent supports logging to a specified file path via environment variable, CLI or config
```
207 changes: 123 additions & 84 deletions command/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ import (
"github.com/hashicorp/vault/command/agent/sink/inmem"
"github.com/hashicorp/vault/command/agent/template"
"github.com/hashicorp/vault/command/agent/winsvc"
"github.com/hashicorp/vault/helper/logging"
"github.com/hashicorp/vault/helper/metricsutil"
"github.com/hashicorp/vault/internalshared/configutil"
"github.com/hashicorp/vault/internalshared/listenerutil"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/helper/useragent"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/version"
Expand All @@ -61,6 +61,12 @@ var (
_ cli.CommandAutocomplete = (*AgentCommand)(nil)
)

const (
// flagNameAgentExitAfterAuth is used as an Agent specific flag to indicate
// that agent should exit after a single successful auth
flagNameAgentExitAfterAuth = "exit-after-auth"
)

type AgentCommand struct {
*BaseCommand

Expand All @@ -80,6 +86,7 @@ type AgentCommand struct {

flagConfigs []string
flagLogLevel string
flagLogFile string
flagExitAfterAuth bool

flagTestVerifyOnly bool
Expand Down Expand Up @@ -124,17 +131,24 @@ func (c *AgentCommand) Flags() *FlagSets {
})

f.StringVar(&StringVar{
Name: "log-level",
Name: flagNameLogLevel,
Target: &c.flagLogLevel,
Default: "info",
EnvVar: "VAULT_LOG_LEVEL",
EnvVar: EnvVaultLogLevel,
Completion: complete.PredictSet("trace", "debug", "info", "warn", "error"),
Usage: "Log verbosity level. Supported values (in order of detail) are " +
"\"trace\", \"debug\", \"info\", \"warn\", and \"error\".",
})

f.StringVar(&StringVar{
Name: flagNameLogFile,
Target: &c.flagLogFile,
EnvVar: EnvVaultLogFile,
Usage: "Path to the log file that Vault should use for logging",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more than this though right? It can be a log dir, or a prefix: https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_log_file

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we add the other log options (like the rotation options) as well as flags? Or alternatively, since unlike consul we have logs of config without associated flags, should we maybe not add the -log-file CLI option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Consul yes, as Consul does rotation of logs etc. so it fiddles with the name a lot more. In Vault I took the simple approach so it's no frills.

})

f.BoolVar(&BoolVar{
Name: "exit-after-auth",
Name: flagNameAgentExitAfterAuth,
Target: &c.flagExitAfterAuth,
Default: false,
Usage: "If set to true, the agent will exit with code 0 after a single " +
Expand Down Expand Up @@ -193,35 +207,14 @@ func (c *AgentCommand) Run(args []string) int {
if c.flagCombineLogs {
c.logWriter = os.Stdout
}
var level log.Level
c.flagLogLevel = strings.ToLower(strings.TrimSpace(c.flagLogLevel))
switch c.flagLogLevel {
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.UI.Error(fmt.Sprintf("Unknown log level: %s", c.flagLogLevel))
return 1
}

if c.logger == nil {
c.logger = logging.NewVaultLoggerWithWriter(c.logWriter, level)
}

// Validation
if len(c.flagConfigs) != 1 {
c.UI.Error("Must specify exactly one config path using -config")
return 1
}

// Load the configuration
// Load the configuration file
config, err := agentConfig.LoadConfig(c.flagConfigs[0])
if err != nil {
c.UI.Error(fmt.Sprintf("Error loading configuration from %s: %s", c.flagConfigs[0], err))
Expand All @@ -235,6 +228,7 @@ func (c *AgentCommand) Run(args []string) int {
"-config flag."))
return 1
}

if config.AutoAuth == nil && config.Cache == nil {
c.UI.Error("No auto_auth or cache block found in config file")
return 1
Expand All @@ -243,62 +237,29 @@ func (c *AgentCommand) Run(args []string) int {
c.UI.Info("No auto_auth block found in config file, not starting automatic authentication feature")
}

exitAfterAuth := config.ExitAfterAuth
f.Visit(func(fl *flag.Flag) {
if fl.Name == "exit-after-auth" {
exitAfterAuth = c.flagExitAfterAuth
}
})
config = c.aggregateConfig(f, config)

c.setStringFlag(f, config.Vault.Address, &StringVar{
Name: flagNameAddress,
Target: &c.flagAddress,
Default: "https://127.0.0.1:8200",
EnvVar: api.EnvVaultAddress,
})
config.Vault.Address = c.flagAddress
c.setStringFlag(f, config.Vault.CACert, &StringVar{
Name: flagNameCACert,
Target: &c.flagCACert,
Default: "",
EnvVar: api.EnvVaultCACert,
})
config.Vault.CACert = c.flagCACert
c.setStringFlag(f, config.Vault.CAPath, &StringVar{
Name: flagNameCAPath,
Target: &c.flagCAPath,
Default: "",
EnvVar: api.EnvVaultCAPath,
})
config.Vault.CAPath = c.flagCAPath
c.setStringFlag(f, config.Vault.ClientCert, &StringVar{
Name: flagNameClientCert,
Target: &c.flagClientCert,
Default: "",
EnvVar: api.EnvVaultClientCert,
})
config.Vault.ClientCert = c.flagClientCert
c.setStringFlag(f, config.Vault.ClientKey, &StringVar{
Name: flagNameClientKey,
Target: &c.flagClientKey,
Default: "",
EnvVar: api.EnvVaultClientKey,
})
config.Vault.ClientKey = c.flagClientKey
c.setBoolFlag(f, config.Vault.TLSSkipVerify, &BoolVar{
Name: flagNameTLSSkipVerify,
Target: &c.flagTLSSkipVerify,
Default: false,
EnvVar: api.EnvVaultSkipVerify,
})
config.Vault.TLSSkipVerify = c.flagTLSSkipVerify
c.setStringFlag(f, config.Vault.TLSServerName, &StringVar{
Name: flagTLSServerName,
Target: &c.flagTLSServerName,
Default: "",
EnvVar: api.EnvVaultTLSServerName,
})
config.Vault.TLSServerName = c.flagTLSServerName
// Build the logger using level, format and path
logLevel, err := logging.ParseLogLevel(config.LogLevel)
if err != nil {
c.UI.Error(err.Error())
return 1
}

logFormat, err := logging.ParseLogFormat(config.LogFormat)
if err != nil {
c.UI.Error(err.Error())
return 1
}

logCfg := logging.NewLogConfig("agent", logLevel, logFormat, config.LogFile)
l, err := logging.Setup(logCfg, c.logWriter)
if err != nil {
c.UI.Error(err.Error())
return 1
}

c.logger = l

infoKeys := make([]string, 0, 10)
info := make(map[string]string)
Expand Down Expand Up @@ -855,16 +816,16 @@ func (c *AgentCommand) Run(args []string) int {
ss := sink.NewSinkServer(&sink.SinkServerConfig{
Logger: c.logger.Named("sink.server"),
Client: ahClient,
ExitAfterAuth: exitAfterAuth,
ExitAfterAuth: config.ExitAfterAuth,
})

ts := template.NewServer(&template.ServerConfig{
Logger: c.logger.Named("template.server"),
LogLevel: level,
LogLevel: logLevel,
LogWriter: c.logWriter,
AgentConfig: config,
Namespace: templateNamespace,
ExitAfterAuth: exitAfterAuth,
ExitAfterAuth: config.ExitAfterAuth,
})

g.Add(func() error {
Expand Down Expand Up @@ -963,6 +924,84 @@ func (c *AgentCommand) Run(args []string) int {
return 0
}

// aggregateConfig ensures that the config object accurately reflects the desired
// settings as configured by the user. It applies the relevant config setting based
// on the precedence (env var overrides file config, cli overrides env var).
// It mutates the config object supplied and returns the updated object.
func (c *AgentCommand) aggregateConfig(f *FlagSets, config *agentConfig.Config) *agentConfig.Config {
f.Visit(func(fl *flag.Flag) {
if fl.Name == flagNameAgentExitAfterAuth {
config.ExitAfterAuth = c.flagExitAfterAuth
}
})

c.setStringFlag(f, config.LogFile, &StringVar{
Name: flagNameLogFile,
EnvVar: EnvVaultLogFile,
Target: &c.flagLogFile,
})
config.LogFile = c.flagLogFile

c.setStringFlag(f, config.LogLevel, &StringVar{
Name: flagNameLogLevel,
EnvVar: EnvVaultLogLevel,
Target: &c.flagLogLevel,
})
config.LogLevel = c.flagLogLevel

c.setStringFlag(f, config.Vault.Address, &StringVar{
Name: flagNameAddress,
Target: &c.flagAddress,
Default: "https://127.0.0.1:8200",
EnvVar: api.EnvVaultAddress,
})
config.Vault.Address = c.flagAddress
c.setStringFlag(f, config.Vault.CACert, &StringVar{
Name: flagNameCACert,
Target: &c.flagCACert,
Default: "",
EnvVar: api.EnvVaultCACert,
})
config.Vault.CACert = c.flagCACert
c.setStringFlag(f, config.Vault.CAPath, &StringVar{
Name: flagNameCAPath,
Target: &c.flagCAPath,
Default: "",
EnvVar: api.EnvVaultCAPath,
})
config.Vault.CAPath = c.flagCAPath
c.setStringFlag(f, config.Vault.ClientCert, &StringVar{
Name: flagNameClientCert,
Target: &c.flagClientCert,
Default: "",
EnvVar: api.EnvVaultClientCert,
})
config.Vault.ClientCert = c.flagClientCert
c.setStringFlag(f, config.Vault.ClientKey, &StringVar{
Name: flagNameClientKey,
Target: &c.flagClientKey,
Default: "",
EnvVar: api.EnvVaultClientKey,
})
config.Vault.ClientKey = c.flagClientKey
c.setBoolFlag(f, config.Vault.TLSSkipVerify, &BoolVar{
Name: flagNameTLSSkipVerify,
Target: &c.flagTLSSkipVerify,
Default: false,
EnvVar: api.EnvVaultSkipVerify,
})
config.Vault.TLSSkipVerify = c.flagTLSSkipVerify
c.setStringFlag(f, config.Vault.TLSServerName, &StringVar{
Name: flagTLSServerName,
Target: &c.flagTLSServerName,
Default: "",
EnvVar: api.EnvVaultTLSServerName,
})
config.Vault.TLSServerName = c.flagTLSServerName

return config
}

// verifyRequestHeader wraps an http.Handler inside a Handler that checks for
// the request header that is used for SSRF protection.
func verifyRequestHeader(handler http.Handler) http.Handler {
Expand Down
4 changes: 2 additions & 2 deletions command/agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"net"
"os"
"strings"
Expand Down Expand Up @@ -38,6 +37,7 @@ type Config struct {
DisableKeepAlivesCaching bool `hcl:"-"`
DisableKeepAlivesTemplating bool `hcl:"-"`
DisableKeepAlivesAutoAuth bool `hcl:"-"`
LogFile string `hcl:"log_file"`
}

const (
Expand Down Expand Up @@ -173,7 +173,7 @@ func LoadConfig(path string) (*Config, error) {
}

// Read the file
d, err := ioutil.ReadFile(path)
d, err := os.ReadFile(path)
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions command/agent/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ func TestLoadConfigFile(t *testing.T) {
NumRetries: 12,
},
},
LogFile: "/var/log/vault/vault-agent.log",
}

config.Prune()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pid_file = "./pidfile"
log_file = "/var/log/vault/vault-agent.log"

auto_auth {
method "aws" {
Expand Down
1 change: 1 addition & 0 deletions command/agent/config/test-fixtures/config.hcl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pid_file = "./pidfile"
log_file = "/var/log/vault/vault-agent.log"

auto_auth {
method {
Expand Down
Loading