From 99b843a64ed9bdbd2afd7c02da5e513961afd85d Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Wed, 19 Dec 2018 01:08:11 +0100 Subject: [PATCH] Add anonymous flag to prevent logging sensitive information (#6899) --- cmd/common-main.go | 25 +++++++++++++++++++++++++ cmd/gateway-main.go | 25 +++---------------------- cmd/gateway-startup-msg.go | 2 +- cmd/globals.go | 10 +++++++++- cmd/logger/logger.go | 37 ++++++++++++++++++++++++++++++++++++- cmd/main.go | 4 ++++ cmd/server-main.go | 25 +++++-------------------- cmd/server-startup-msg.go | 2 +- 8 files changed, 84 insertions(+), 46 deletions(-) diff --git a/cmd/common-main.go b/cmd/common-main.go index 723546148..ed6c6148d 100644 --- a/cmd/common-main.go +++ b/cmd/common-main.go @@ -80,6 +80,31 @@ func loadLoggers() { func handleCommonCmdArgs(ctx *cli.Context) { + // Get "json" flag from command line argument and + // enable json and quite modes if jason flag is turned on. + globalCLIContext.JSON = ctx.IsSet("json") || ctx.GlobalIsSet("json") + if globalCLIContext.JSON { + logger.EnableJSON() + } + + // Get quiet flag from command line argument. + globalCLIContext.Quiet = ctx.IsSet("quiet") || ctx.GlobalIsSet("quiet") + if globalCLIContext.Quiet { + logger.EnableQuiet() + } + + // Get anonymous flag from command line argument. + globalCLIContext.Anonymous = ctx.IsSet("anonymous") || ctx.GlobalIsSet("anonymous") + if globalCLIContext.Anonymous { + logger.EnableAnonymous() + } + + // Fetch address option + globalCLIContext.Addr = ctx.GlobalString("address") + if globalCLIContext.Addr == "" || globalCLIContext.Addr == ":"+globalMinioDefaultPort { + globalCLIContext.Addr = ctx.String("address") + } + var configDir string switch { diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index 29e18ce83..2b1626c54 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -112,30 +112,11 @@ func StartGateway(ctx *cli.Context, gw Gateway) { cli.ShowCommandHelpAndExit(ctx, gatewayName, 1) } - // Get "json" flag from command line argument and - // enable json and quite modes if jason flag is turned on. - jsonFlag := ctx.IsSet("json") || ctx.GlobalIsSet("json") - if jsonFlag { - logger.EnableJSON() - } - - // Get quiet flag from command line argument. - quietFlag := ctx.IsSet("quiet") || ctx.GlobalIsSet("quiet") - if quietFlag { - logger.EnableQuiet() - } - - // Fetch address option - gatewayAddr := ctx.GlobalString("address") - if gatewayAddr == ":"+globalMinioPort { - gatewayAddr = ctx.String("address") - } - // Handle common command args. handleCommonCmdArgs(ctx) // Get port to listen on from gateway address - globalMinioHost, globalMinioPort = mustSplitHostPort(gatewayAddr) + globalMinioHost, globalMinioPort = mustSplitHostPort(globalCLIContext.Addr) // On macOS, if a process already listens on LOCALIPADDR:PORT, net.Listen() falls back // to IPv6 address ie minio will start listening on IPv6 address whereas another @@ -207,7 +188,7 @@ func StartGateway(ctx *cli.Context, gw Gateway) { getCert = globalTLSCerts.GetCertificate } - globalHTTPServer = xhttp.NewServer([]string{gatewayAddr}, criticalErrorHandler{registerHandlers(router, globalHandlers...)}, getCert) + globalHTTPServer = xhttp.NewServer([]string{globalCLIContext.Addr}, criticalErrorHandler{registerHandlers(router, globalHandlers...)}, getCert) globalHTTPServer.UpdateBytesReadFunc = globalConnStats.incInputBytes globalHTTPServer.UpdateBytesWrittenFunc = globalConnStats.incOutputBytes go func() { @@ -294,7 +275,7 @@ func StartGateway(ctx *cli.Context, gw Gateway) { globalObjLayerMutex.Unlock() // Prints the formatted startup message once object layer is initialized. - if !quietFlag { + if !globalCLIContext.Quiet { mode := globalMinioModeGatewayPrefix + gatewayName // Check update mode. checkUpdate(mode) diff --git a/cmd/gateway-startup-msg.go b/cmd/gateway-startup-msg.go index f5c850b43..6068f90b3 100644 --- a/cmd/gateway-startup-msg.go +++ b/cmd/gateway-startup-msg.go @@ -58,7 +58,7 @@ func printGatewayCommonMsg(apiEndpoints []string) { // Colorize the message and print. logger.StartupMessage(colorBlue("Endpoint: ") + colorBold(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 1), apiEndpointStr))) - if isTerminal() { + if isTerminal() && !globalCLIContext.Anonymous { logger.StartupMessage(colorBlue("AccessKey: ") + colorBold(fmt.Sprintf("%s ", cred.AccessKey))) logger.StartupMessage(colorBlue("SecretKey: ") + colorBold(fmt.Sprintf("%s ", cred.SecretKey))) } diff --git a/cmd/globals.go b/cmd/globals.go index 3f6e2c03a..c4ec4a8bd 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -42,6 +42,8 @@ import ( const ( globalMinioCertExpireWarnDays = time.Hour * 24 * 30 // 30 days. + globalMinioDefaultPort = "9000" + globalMinioDefaultRegion = "" // This is a sha256 output of ``arn:aws:iam::minio:user/admin``, // this is kept in present form to be compatible with S3 owner ID @@ -90,6 +92,12 @@ const ( maxLocationConstraintSize = 3 * humanize.MiByte ) +var globalCLIContext = struct { + JSON, Quiet bool + Anonymous bool + Addr string +}{} + var ( // Indicates the total number of erasure coded sets configured. globalXLSetCount int @@ -127,7 +135,7 @@ var ( // Minio local server address (in `host:port` format) globalMinioAddr = "" // Minio default port, can be changed through command line. - globalMinioPort = "9000" + globalMinioPort = globalMinioDefaultPort // Holds the host that was passed using --address globalMinioHost = "" diff --git a/cmd/logger/logger.go b/cmd/logger/logger.go index aee3c3835..87e0920df 100644 --- a/cmd/logger/logger.go +++ b/cmd/logger/logger.go @@ -18,17 +18,28 @@ package logger import ( "context" + "encoding/hex" "fmt" "go/build" + "hash" "path/filepath" + "reflect" "runtime" "strings" "time" + "github.com/minio/highwayhash" "github.com/minio/minio-go/pkg/set" "github.com/minio/minio/cmd/logger/message/log" ) +var ( + // HighwayHash key for logging in anonymous mode + magicHighwayHash256Key = []byte("\x4b\xe7\x34\xfa\x8e\x23\x8a\xcd\x26\x3e\x83\xe6\xbb\x96\x85\x52\x04\x0f\x93\x5d\xa3\x9f\x44\x14\x97\xe0\x9d\x13\x22\xde\x36\xa0") + // HighwayHash hasher for logging in anonymous mode + loggerHighwayHasher hash.Hash +) + // Disable disables all logging, false by default. (used for "go test") var Disable = false @@ -94,7 +105,7 @@ func (level Level) String() string { // quietFlag: Hide startup messages if enabled // jsonFlag: Display in JSON format, if enabled var ( - quietFlag, jsonFlag bool + quietFlag, jsonFlag, anonFlag bool // Custom function to format error errorFmtFunc func(string, error, bool) string ) @@ -110,6 +121,12 @@ func EnableJSON() { quietFlag = true } +// EnableAnonymous - turns anonymous flag +// to avoid printing sensitive information. +func EnableAnonymous() { + anonFlag = true +} + // IsJSON - returns true if jsonFlag is true func IsJSON() bool { return jsonFlag @@ -187,6 +204,8 @@ func Init(goPath string, goRoot string) { // paths like "{GOROOT}/src/github.com/minio/minio" // and "{GOPATH}/src/github.com/minio/minio" trimStrings = append(trimStrings, filepath.Join("github.com", "minio", "minio")+string(filepath.Separator)) + + loggerHighwayHasher, _ = highwayhash.New(magicHighwayHash256Key) // New will never return error since key is 256 bit } func trimTrace(f string) string { @@ -239,6 +258,14 @@ func getTrace(traceLevel int) []string { return trace } +// Return the highway hash of the passed string +func hashString(input string) string { + defer loggerHighwayHasher.Reset() + loggerHighwayHasher.Write([]byte(input)) + checksum := loggerHighwayHasher.Sum(nil) + return hex.EncodeToString(checksum) +} + // LogAlwaysIf prints a detailed error message during // the execution of the server. func LogAlwaysIf(ctx context.Context, err error) { @@ -312,6 +339,14 @@ func logIf(ctx context.Context, err error) { }, } + if anonFlag { + entry.API.Args.Bucket = hashString(entry.API.Args.Bucket) + entry.API.Args.Object = hashString(entry.API.Args.Object) + entry.RemoteHost = hashString(entry.RemoteHost) + entry.Message = reflect.TypeOf(err).String() + entry.Trace.Variables = make(map[string]string) + } + // Iterate over all logger targets to send the log entry for _, t := range Targets { t.Send(entry) diff --git a/cmd/main.go b/cmd/main.go index e2a5a9e07..39546249a 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -44,6 +44,10 @@ var globalFlags = []cli.Flag{ Name: "quiet", Usage: "Disable startup information.", }, + cli.BoolFlag{ + Name: "anonymous", + Usage: "Hide sensitive information from logging.", + }, cli.BoolFlag{ Name: "json", Usage: "Output server logs and startup information in json format.", diff --git a/cmd/server-main.go b/cmd/server-main.go index e151a6876..e7a018d46 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -41,7 +41,7 @@ func init() { var serverFlags = []cli.Flag{ cli.StringFlag{ Name: "address", - Value: ":" + globalMinioPort, + Value: ":" + globalMinioDefaultPort, Usage: "bind to a specific ADDRESS:PORT, ADDRESS can be an IP or hostname", }, } @@ -148,9 +148,7 @@ func serverHandleCmdArgs(ctx *cli.Context) { // Handle common command args. handleCommonCmdArgs(ctx) - // Server address. - serverAddr := ctx.String("address") - logger.FatalIf(CheckLocalServerAddr(serverAddr), "Unable to validate passed arguments") + logger.FatalIf(CheckLocalServerAddr(globalCLIContext.Addr), "Unable to validate passed arguments") var setupType SetupType var err error @@ -163,9 +161,9 @@ func serverHandleCmdArgs(ctx *cli.Context) { endpoints := strings.Fields(os.Getenv("MINIO_ENDPOINTS")) if len(endpoints) > 0 { - globalMinioAddr, globalEndpoints, setupType, globalXLSetCount, globalXLSetDriveCount, err = createServerEndpoints(serverAddr, endpoints...) + globalMinioAddr, globalEndpoints, setupType, globalXLSetCount, globalXLSetDriveCount, err = createServerEndpoints(globalCLIContext.Addr, endpoints...) } else { - globalMinioAddr, globalEndpoints, setupType, globalXLSetCount, globalXLSetDriveCount, err = createServerEndpoints(serverAddr, ctx.Args()...) + globalMinioAddr, globalEndpoints, setupType, globalXLSetCount, globalXLSetDriveCount, err = createServerEndpoints(globalCLIContext.Addr, ctx.Args()...) } logger.FatalIf(err, "Invalid command line arguments") @@ -206,19 +204,6 @@ func serverMain(ctx *cli.Context) { // error during initialization will be shown as a fatal message logger.Disable = true - // Get "json" flag from command line argument and - // enable json and quite modes if jason flag is turned on. - jsonFlag := ctx.IsSet("json") || ctx.GlobalIsSet("json") - if jsonFlag { - logger.EnableJSON() - } - - // Get quiet flag from command line argument. - quietFlag := ctx.IsSet("quiet") || ctx.GlobalIsSet("quiet") - if quietFlag { - logger.EnableQuiet() - } - // Handle all server command args. serverHandleCmdArgs(ctx) @@ -247,7 +232,7 @@ func serverMain(ctx *cli.Context) { } } - if !quietFlag { + if !globalCLIContext.Quiet { // Check for new updates from dl.minio.io. mode := globalMinioModeFS if globalIsDistXL { diff --git a/cmd/server-startup-msg.go b/cmd/server-startup-msg.go index b1c5bb123..4b35704d1 100644 --- a/cmd/server-startup-msg.go +++ b/cmd/server-startup-msg.go @@ -123,7 +123,7 @@ func printServerCommonMsg(apiEndpoints []string) { // Colorize the message and print. logger.StartupMessage(colorBlue("Endpoint: ") + colorBold(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 1), apiEndpointStr))) - if isTerminal() { + if isTerminal() && !globalCLIContext.Anonymous { logger.StartupMessage(colorBlue("AccessKey: ") + colorBold(fmt.Sprintf("%s ", cred.AccessKey))) logger.StartupMessage(colorBlue("SecretKey: ") + colorBold(fmt.Sprintf("%s ", cred.SecretKey))) if region != "" {