Skip to content

Commit

Permalink
[v13] Machine ID: Support for JSON log formatting (#30763)
Browse files Browse the repository at this point in the history
* Support for json log output in `tbot`

* Fix spacing in docs

* fix markdown spacing
  • Loading branch information
strideynet committed Aug 23, 2023
1 parent 73f7d4d commit 8268e8d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
4 changes: 3 additions & 1 deletion docs/pages/reference/cli/tbot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
<Tabs>
Expand Down Expand Up @@ -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

Expand Down
9 changes: 9 additions & 0 deletions lib/tbot/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
35 changes: 31 additions & 4 deletions tool/tbot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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 <path>).")
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)
Expand All @@ -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()

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}

0 comments on commit 8268e8d

Please sign in to comment.