diff --git a/docs/pages/reference/cli/tbot.mdx b/docs/pages/reference/cli/tbot.mdx index 4cd2f9782cb92..995bc95e984da 100644 --- a/docs/pages/reference/cli/tbot.mdx +++ b/docs/pages/reference/cli/tbot.mdx @@ -35,8 +35,9 @@ Starts the Machine ID client `tbot`, fetching and writing certificates to disk a | `--destination-dir` | Directory to write short-lived machine certificates. | | `--certificate-ttl` | TTL of short-lived machine certificates. | | `--renewal-interval` | Interval at which short-lived certificates are renewed; must be less than the certificate TTL. | -| `--join-method` | Method to use to join the cluster. Can be `token` or `iam`. | +| `--join-method` | Method to use to join the cluster. Can be `token`, `azure`, `circleci`, `gcp`, `github`, `gitlab` or `iam`. | | `--oneshot` | If set, quit after the first renewal. | +| `--log-format` | Controls the format of output logs. Can be `json` or `text`. Defaults to `text`. | ### Examples @@ -85,6 +86,7 @@ configuring either file or POSIX ACL permissions. | `--reader-user` | Enables POSIX ACLs and defines the Linux user that will read short-lived certificates from `--destination-dir`. | | `--init-dir` | If using a config file and multiple destinations are configured, controls which destination dir to configure. | | `--clean` | If set, remove unexpected files and directories from the destination. | +| `--log-format` | Controls the format of output logs. Can be `json` or `text`. Defaults to `text`. | ### Examples diff --git a/lib/tbot/config/config.go b/lib/tbot/config/config.go index f27a98464e75c..3eb4062e41c02 100644 --- a/lib/tbot/config/config.go +++ b/lib/tbot/config/config.go @@ -79,12 +79,21 @@ func RemainingArgs(s kingpin.Settings) (target *[]string) { return } +const ( + LogFormatJSON = "json" + LogFormatText = "text" +) + // CLIConf is configuration from the CLI. type CLIConf struct { ConfigPath string Debug bool + // LogFormat controls the format of logging. Can be either `json` or `text`. + // By default, this is `text`. + LogFormat string + // AuthServer is a Teleport auth server address. It may either point // directly to an auth server, or to a Teleport proxy server in which case // a tunneled auth connection will be established. diff --git a/tool/tbot/main.go b/tool/tbot/main.go index 8486b20487a56..5bc8ac2e10c6c 100644 --- a/tool/tbot/main.go +++ b/tool/tbot/main.go @@ -61,7 +61,6 @@ Find out more at https://goteleport.com/docs/machine-id/introduction/` func Run(args []string, stdout io.Writer) error { var cf config.CLIConf - utils.InitLogger(utils.LoggingForDaemon, logrus.InfoLevel) app := utils.InitCLIParser("tbot", appHelp).Interspersed(false) app.Flag("debug", "Verbose logging to stdout.").Short('d').BoolVar(&cf.Debug) @@ -87,6 +86,9 @@ func Run(args []string, stdout io.Writer) error { startCmd.Flag("join-method", "Method to use to join the cluster. "+joinMethodList).Default(config.DefaultJoinMethod).EnumVar(&cf.JoinMethod, config.SupportedJoinMethods...) startCmd.Flag("oneshot", "If set, quit after the first renewal.").BoolVar(&cf.Oneshot) startCmd.Flag("diag-addr", "If set and the bot is in debug mode, a diagnostics service will listen on specified address.").StringVar(&cf.DiagAddr) + startCmd.Flag("log-format", "Controls the format of output logs. Can be `json` or `text`. Defaults to `text`."). + Default(config.LogFormatText). + EnumVar(&cf.LogFormat, config.LogFormatJSON, config.LogFormatText) initCmd := app.Command("init", "Initialize a certificate destination directory for writes from a separate bot user.") initCmd.Flag("destination-dir", "Directory to write short-lived machine certificates to.").StringVar(&cf.DestinationDir) @@ -95,6 +97,9 @@ func Run(args []string, stdout io.Writer) error { initCmd.Flag("reader-user", "Enables POSIX ACLs and defines Linux user that will read short-lived certificates from \"--destination-dir\".").StringVar(&cf.ReaderUser) initCmd.Flag("init-dir", "If using a config file and multiple destinations are configured, controls which destination dir to configure.").StringVar(&cf.InitDir) initCmd.Flag("clean", "If set, remove unexpected files and directories from the destination.").BoolVar(&cf.Clean) + initCmd.Flag("log-format", "Controls the format of output logs. Can be `json` or `text`. Defaults to `text`."). + Default(config.LogFormatText). + EnumVar(&cf.LogFormat, config.LogFormatJSON, config.LogFormatText) configureCmd := app.Command("configure", "Creates a config file based on flags provided, and writes it to stdout or a file (-c ).") configureCmd.Flag("auth-server", "Address of the Teleport Auth Server (On-Prem installs) or Proxy Server (Cloud installs).").Short('a').Envar(authServerEnvVar).StringVar(&cf.AuthServer) @@ -106,6 +111,9 @@ func Run(args []string, stdout io.Writer) error { configureCmd.Flag("renewal-interval", "Interval at which short-lived certificates are renewed; must be less than the certificate TTL.").DurationVar(&cf.RenewalInterval) configureCmd.Flag("token", "A bot join token, if attempting to onboard a new bot; used on first connect.").Envar(tokenEnvVar).StringVar(&cf.Token) configureCmd.Flag("output", "Path to write the generated configuration file to rather than write to stdout.").Short('o').StringVar(&cf.ConfigureOutput) + configureCmd.Flag("log-format", "Controls the format of output logs. Can be `json` or `text`. Defaults to `text`."). + Default(config.LogFormatText). + EnumVar(&cf.LogFormat, config.LogFormatJSON, config.LogFormatText) watchCmd := app.Command("watch", "Watch a destination directory for changes.").Hidden() @@ -147,9 +155,8 @@ func Run(args []string, stdout io.Writer) error { cf.RemainingArgs = *proxyRemaining } - // While in debug mode, send logs to stdout. - if cf.Debug { - utils.InitLogger(utils.LoggingForDaemon, logrus.DebugLevel) + if err := setupLogger(cf.Debug, cf.LogFormat); err != nil { + return trace.Wrap(err, "setting up logger") } botConfig, err := config.FromCLIConf(&cf) @@ -298,3 +305,23 @@ func handleSignals(log logrus.FieldLogger, reload chan struct{}, cancel context. } } } + +func setupLogger(debug bool, format string) error { + level := logrus.InfoLevel + if debug { + level = logrus.DebugLevel + } + utils.InitLogger(utils.LoggingForDaemon, level) + + switch format { + case config.LogFormatJSON: + formatter := &utils.JSONFormatter{} + logrus.SetFormatter(formatter) + case config.LogFormatText, "": + // Nothing to do, this is the default set up by utils.InitLogger + default: + return trace.BadParameter("unsupported log format %q", format) + } + + return nil +}