mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-05 03:33:24 +08:00
client runs with elevated permissions and the command fails (for instance, when the auth server state has not yet been generated), it will leave the file behind possibly making further attempts to properly generate content in data directory by a lower-privilege process impossible.
184 lines
4.9 KiB
Go
184 lines
4.9 KiB
Go
/*
|
|
Copyright 2016 Gravitational, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package utils
|
|
|
|
import (
|
|
"crypto/x509"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log/syslog"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/gravitational/teleport"
|
|
|
|
log "github.com/Sirupsen/logrus"
|
|
logrusSyslog "github.com/Sirupsen/logrus/hooks/syslog"
|
|
"github.com/gravitational/kingpin"
|
|
"github.com/gravitational/trace"
|
|
)
|
|
|
|
// InitLoggerCLI tools by default log into syslog, not stderr
|
|
func InitLoggerCLI() {
|
|
log.SetLevel(log.WarnLevel)
|
|
// clear existing hooks:
|
|
log.StandardLogger().Hooks = make(log.LevelHooks)
|
|
log.SetFormatter(&trace.TextFormatter{})
|
|
|
|
hook, err := logrusSyslog.NewSyslogHook("", "", syslog.LOG_WARNING, "")
|
|
if err != nil {
|
|
// syslog not available
|
|
log.Warn("syslog not available. reverting to stderr")
|
|
} else {
|
|
// ... and disable stderr:
|
|
log.AddHook(hook)
|
|
log.SetOutput(ioutil.Discard)
|
|
}
|
|
}
|
|
|
|
// InitLoggerDebug configures the logger to dump everything to stderr
|
|
func InitLoggerDebug() {
|
|
InitDebugLogger(log.DebugLevel)
|
|
}
|
|
|
|
// InitLoggerVerbose is a less chatty version of debug logger above
|
|
func InitLoggerVerbose() {
|
|
InitDebugLogger(log.InfoLevel)
|
|
}
|
|
|
|
func InitDebugLogger(level log.Level) {
|
|
// clear existing hooks:
|
|
log.StandardLogger().Hooks = make(log.LevelHooks)
|
|
log.SetFormatter(&trace.TextFormatter{})
|
|
log.SetOutput(os.Stderr)
|
|
log.SetLevel(level)
|
|
}
|
|
|
|
// InitLoggerForTests inits logger to discard ouput in tests unless
|
|
// TELEPORT_DEBUG is set to "true"
|
|
func InitLoggerForTests() {
|
|
val, _ := strconv.ParseBool(os.Getenv(teleport.DebugOutputEnvVar))
|
|
if val {
|
|
InitLoggerDebug()
|
|
return
|
|
}
|
|
log.SetLevel(log.WarnLevel)
|
|
log.StandardLogger().Hooks = make(log.LevelHooks)
|
|
log.SetOutput(ioutil.Discard)
|
|
}
|
|
|
|
// FatalError is for CLI front-ends: it detects gravitational/trace debugging
|
|
// information, sends it to the logger, strips it off and prints a clean message to stderr
|
|
func FatalError(err error) {
|
|
fmt.Fprintln(os.Stderr, UserMessageFromError(err))
|
|
os.Exit(1)
|
|
}
|
|
|
|
// UserMessageFromError returns user friendly error message from error
|
|
func UserMessageFromError(err error) string {
|
|
err = trace.Unwrap(err)
|
|
|
|
// untrusted cert?
|
|
switch err.(interface{}).(type) {
|
|
case x509.UnknownAuthorityError, x509.CertificateInvalidError:
|
|
return "WARNING:\n The proxy you are connecting to uses the self-signed HTTPS certificate.\n" +
|
|
" Try --insecure flag if you know what you're doing.\n"
|
|
}
|
|
return err.Error()
|
|
}
|
|
|
|
// Consolef prints the same message to a 'ui console' (if defined) and also to
|
|
// the logger with INFO priority
|
|
func Consolef(w io.Writer, msg string, params ...interface{}) {
|
|
msg = fmt.Sprintf(msg, params...)
|
|
if w != nil {
|
|
fmt.Fprintln(w, msg)
|
|
}
|
|
log.Info(msg)
|
|
}
|
|
|
|
// InitCLIParser configures kingpin command line args parser with
|
|
// some defaults common for all Teleport CLI tools
|
|
func InitCLIParser(appName, appHelp string) (app *kingpin.Application) {
|
|
app = kingpin.New(appName, appHelp)
|
|
|
|
// hide "--help" flag
|
|
app.HelpFlag.Hidden()
|
|
app.HelpFlag.NoEnvar()
|
|
|
|
// set our own help template
|
|
return app.UsageTemplate(defaultUsageTemplate)
|
|
}
|
|
|
|
// Usage template with compactly formatted commands.
|
|
var defaultUsageTemplate = `{{define "FormatCommand"}}\
|
|
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
|
|
{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
|
|
{{end}}\
|
|
|
|
{{define "FormatCommands"}}\
|
|
{{range .FlattenedCommands}}\
|
|
{{if not .Hidden}}\
|
|
{{.FullCommand | printf "%-12s" }}{{if .Default}} (Default){{end}} {{ .Help }}
|
|
{{end}}\
|
|
{{end}}\
|
|
{{end}}\
|
|
|
|
{{define "FormatUsage"}}\
|
|
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
|
|
{{if .Help}}
|
|
{{.Help|Wrap 0}}\
|
|
{{end}}\
|
|
|
|
{{end}}\
|
|
|
|
{{if .Context.SelectedCommand}}\
|
|
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
|
|
{{else}}\
|
|
Usage: {{.App.Name}}{{template "FormatUsage" .App}}
|
|
{{end}}\
|
|
{{if .Context.Flags}}\
|
|
Flags:
|
|
{{.Context.Flags|FlagsToTwoColumnsCompact|FormatTwoColumns}}
|
|
{{end}}\
|
|
{{if .Context.Args}}\
|
|
Args:
|
|
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
|
|
{{end}}\
|
|
{{if .Context.SelectedCommand}}\
|
|
|
|
{{ if .Context.SelectedCommand.Commands}}\
|
|
Commands:
|
|
{{if .Context.SelectedCommand.Commands}}\
|
|
{{template "FormatCommands" .Context.SelectedCommand}}
|
|
{{end}}\
|
|
{{end}}\
|
|
|
|
{{else if .App.Commands}}\
|
|
Commands:
|
|
{{template "FormatCommands" .App}}
|
|
Try '{{.App.Name}} help [command]' to get help for a given command.
|
|
{{end}}\
|
|
|
|
{{ if .Context.SelectedCommand }}\
|
|
{{ range .Context.SelectedCommand.Aliases}}\
|
|
{{ . }}
|
|
{{end}}\
|
|
{{end}}
|
|
`
|