diff --git a/cmd/client-s3-trace_v2.go b/cmd/client-s3-trace_v2.go index e876d132d1..a719503e7c 100644 --- a/cmd/client-s3-trace_v2.go +++ b/cmd/client-s3-trace_v2.go @@ -87,5 +87,10 @@ func (t traceV2) Response(resp *http.Response) (err error) { if err == nil { console.Debug(string(respTrace)) } + + if globalInsecure && resp.TLS != nil { + dumpTLSCertificates(resp.TLS) + } + return err } diff --git a/cmd/client-s3-trace_v4.go b/cmd/client-s3-trace_v4.go index df5a1cb960..868f535f89 100644 --- a/cmd/client-s3-trace_v4.go +++ b/cmd/client-s3-trace_v4.go @@ -96,5 +96,10 @@ func (t traceV4) Response(resp *http.Response) (err error) { if err == nil { console.Debug(string(respTrace)) } + + if globalInsecure && resp.TLS != nil { + dumpTLSCertificates(resp.TLS) + } + return err } diff --git a/cmd/client-s3.go b/cmd/client-s3.go index ae55a3b19c..ed654c0e18 100644 --- a/cmd/client-s3.go +++ b/cmd/client-s3.go @@ -17,6 +17,7 @@ package cmd import ( + "crypto/tls" "errors" "hash/fnv" "io" @@ -111,17 +112,22 @@ func newFactory() func(config *Config) (Client, *probe.Error) { if e != nil { return nil, probe.NewError(e) } + transport := http.DefaultTransport + if config.Insecure { + transport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + } if config.Debug { - transport := http.DefaultTransport if config.Signature == "S3v4" { - transport = httptracer.GetNewTraceTransport(newTraceV4(), http.DefaultTransport) + transport = httptracer.GetNewTraceTransport(newTraceV4(), transport) } if config.Signature == "S3v2" { - transport = httptracer.GetNewTraceTransport(newTraceV2(), http.DefaultTransport) + transport = httptracer.GetNewTraceTransport(newTraceV2(), transport) } // Set custom transport. - api.SetCustomTransport(transport) } + api.SetCustomTransport(transport) // Cache the new minio client with hash of config as key. clientCache[confSum] = api } diff --git a/cmd/client.go b/cmd/client.go index 2c78301afa..0f45ca66e3 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -76,4 +76,5 @@ type Config struct { AppVersion string AppComments []string Debug bool + Insecure bool } diff --git a/cmd/common-methods.go b/cmd/common-methods.go index d33017122c..5ff1681ed5 100644 --- a/cmd/common-methods.go +++ b/cmd/common-methods.go @@ -159,6 +159,7 @@ func newClientFromAlias(alias string, urlStr string) (Client, *probe.Error) { s3Config.AppComments = []string{os.Args[0], runtime.GOOS, runtime.GOARCH} s3Config.HostURL = urlStr s3Config.Debug = globalDebug + s3Config.Insecure = globalInsecure s3Client, err := s3New(s3Config) if err != nil { return nil, err.Trace(alias, urlStr) diff --git a/cmd/cp-main.go b/cmd/cp-main.go index 83b49858a2..d274ddfb24 100644 --- a/cmd/cp-main.go +++ b/cmd/cp-main.go @@ -221,7 +221,7 @@ func doCopyFake(cpURLs URLs, progressReader *progressBar) URLs { } // doPrepareCopyURLs scans the source URL and prepares a list of objects for copying. -func doPrepareCopyURLs(session *sessionV7, trapCh <-chan bool) { +func doPrepareCopyURLs(session *sessionV8, trapCh <-chan bool) { // Separate source and target. 'cp' can take only one target, // but any number of sources. sourceURLs := session.Header.CommandArgs[:len(session.Header.CommandArgs)-1] @@ -289,7 +289,7 @@ func doPrepareCopyURLs(session *sessionV7, trapCh <-chan bool) { session.Save() } -func doCopySession(session *sessionV7) { +func doCopySession(session *sessionV8) { trapCh := signalTrap(os.Interrupt, syscall.SIGTERM) if !session.HasData() { @@ -410,7 +410,7 @@ func mainCopy(ctx *cli.Context) { // Additional command speific theme customization. console.SetColor("Copy", color.New(color.FgGreen, color.Bold)) - session := newSessionV7() + session := newSessionV8() session.Header.CommandType = "cp" session.Header.CommandBoolFlags["recursive"] = ctx.Bool("recursive") diff --git a/cmd/flags.go b/cmd/flags.go index ab6103bd24..bc0131a2f2 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -47,6 +47,10 @@ var globalFlags = []cli.Flag{ Name: "debug", Usage: "Enable debugging output.", }, + cli.BoolFlag{ + Name: "insecure", + Usage: "Skip SSl certificate verification.", + }, } // registerCmd registers a cli command diff --git a/cmd/globals.go b/cmd/globals.go index eeab262439..0d617e7b94 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -43,19 +43,21 @@ const ( ) var ( - globalQuiet = false // Quiet flag set via command line - globalJSON = false // Json flag set via command line - globalDebug = false // Debug flag set via command line - globalNoColor = false // Debug flag set via command line + globalQuiet = false // Quiet flag set via command line + globalJSON = false // Json flag set via command line + globalDebug = false // Debug flag set via command line + globalNoColor = false // No Color flag set via command line + globalInsecure = false // Insecure flag set via command line // WHEN YOU ADD NEXT GLOBAL FLAG, MAKE SURE TO ALSO UPDATE SESSION CODE AND CODE BELOW. ) // Set global states. NOTE: It is deliberately kept monolithic to ensure we dont miss out any flags. -func setGlobals(quiet, debug, json, noColor bool) { +func setGlobals(quiet, debug, json, noColor, insecure bool) { globalQuiet = quiet globalDebug = debug globalJSON = json globalNoColor = noColor + globalInsecure = insecure // Enable debug messages if requested. if globalDebug { @@ -74,5 +76,6 @@ func setGlobalsFromContext(ctx *cli.Context) { debug := ctx.Bool("debug") || ctx.GlobalBool("debug") json := ctx.Bool("json") || ctx.GlobalBool("json") noColor := ctx.Bool("no-color") || ctx.GlobalBool("no-color") - setGlobals(quiet, debug, json, noColor) + insecure := ctx.Bool("insecure") || ctx.GlobalBool("insecure") + setGlobals(quiet, debug, json, noColor, insecure) } diff --git a/cmd/mirror-main.go b/cmd/mirror-main.go index 98434e8525..fee8c06b1f 100644 --- a/cmd/mirror-main.go +++ b/cmd/mirror-main.go @@ -100,7 +100,7 @@ EXAMPLES: type mirrorSession struct { // embeds the session struct - *sessionV7 + *sessionV8 // the channel to trap SIGKILL signals trapCh <-chan bool @@ -702,7 +702,7 @@ func (ms *mirrorSession) shutdown() { ms.wgStatus.Wait() } -func newMirrorSession(session *sessionV7) *mirrorSession { +func newMirrorSession(session *sessionV8) *mirrorSession { args := session.Header.CommandArgs // we'll define the status to use here, @@ -714,7 +714,7 @@ func newMirrorSession(session *sessionV7) *mirrorSession { ms := mirrorSession{ trapCh: signalTrap(os.Interrupt, syscall.SIGTERM), - sessionV7: session, + sessionV8: session, statusCh: make(chan URLs), harvestCh: make(chan URLs), @@ -754,7 +754,7 @@ func mainMirror(ctx *cli.Context) { // Additional command speific theme customization. console.SetColor("Mirror", color.New(color.FgGreen, color.Bold)) - session := newSessionV7() + session := newSessionV8() session.Header.CommandType = "mirror" if v, err := os.Getwd(); err == nil { diff --git a/cmd/session-main.go b/cmd/session-main.go index 4c19504624..db2356bdfd 100644 --- a/cmd/session-main.go +++ b/cmd/session-main.go @@ -77,7 +77,7 @@ EXAMPLES: } // bySessionWhen is a type for sorting session metadata by time. -type bySessionWhen []*sessionV7 +type bySessionWhen []*sessionV8 func (b bySessionWhen) Len() int { return len(b) } func (b bySessionWhen) Swap(i, j int) { b[i], b[j] = b[j], b[i] } @@ -85,9 +85,9 @@ func (b bySessionWhen) Less(i, j int) bool { return b[i].Header.When.Before(b[j] // listSessions list all current sessions. func listSessions() *probe.Error { - var bySessions []*sessionV7 + var bySessions []*sessionV8 for _, sid := range getSessionIDs() { - session, err := loadSessionV7(sid) + session, err := loadSessionV8(sid) if err != nil { continue // Skip 'broken' session during listing } @@ -133,7 +133,7 @@ func (c clearSessionMessage) JSON() string { func clearSession(sid string) { if sid == "all" { for _, sid := range getSessionIDs() { - session, err := loadSessionV7(sid) + session, err := loadSessionV8(sid) fatalIf(err.Trace(sid), "Unable to load session ‘"+sid+"’.") fatalIf(session.Delete().Trace(sid), "Unable to load session ‘"+sid+"’.") @@ -147,7 +147,7 @@ func clearSession(sid string) { fatalIf(errDummy().Trace(sid), "Session ‘"+sid+"’ not found.") } - session, err := loadSessionV7(sid) + session, err := loadSessionV8(sid) if err != nil { // `mc session clear ` assumes that user is aware that the session is unuseful // and wants the associated session files to be removed @@ -163,7 +163,7 @@ func clearSession(sid string) { } } -func sessionExecute(s *sessionV7) { +func sessionExecute(s *sessionV8) { switch s.Header.CommandType { case "cp": doCopySession(s) @@ -246,7 +246,7 @@ func mainSession(ctx *cli.Context) { } fatalIf(errDummy().Trace(sid), errorMsg) } - s, err := loadSessionV7(sid) + s, err := loadSessionV8(sid) fatalIf(err.Trace(sid), "Unable to load session.") // Restore the state of global variables from this previous session. diff --git a/cmd/session-migrate.go b/cmd/session-migrate.go index ce58c43de6..555ac913e6 100644 --- a/cmd/session-migrate.go +++ b/cmd/session-migrate.go @@ -25,6 +25,58 @@ import ( "github.com/minio/minio/pkg/quick" ) +// Migrates session header version '7' to '8'. The only +// change was the adding of insecure global flag +func migrateSessionV7ToV8() { + for _, sid := range getSessionIDs() { + sV7, err := loadSessionV7(sid) + if err != nil { + if os.IsNotExist(err.ToGoError()) { + continue + } + fatalIf(err.Trace(sid), "Unable to load version ‘7’. Migration failed please report this issue at https://github.com/minio/mc/issues.") + } + + sessionVersion, e := strconv.Atoi(sV7.Header.Version) + fatalIf(probe.NewError(e), "Unable to load version ‘7’. Migration failed please report this issue at https://github.com/minio/mc/issues.") + if sessionVersion > 7 { // It is new format. + continue + } + + sessionFile, err := getSessionFile(sid) + fatalIf(err.Trace(sid), "Unable to get session file.") + + // Initialize v7 header and migrate to new config. + sV8Header := &sessionV8Header{} + sV8Header.Version = "8" + sV8Header.When = sV7.Header.When + sV8Header.RootPath = sV7.Header.RootPath + sV8Header.GlobalBoolFlags = sV7.Header.GlobalBoolFlags + sV8Header.GlobalIntFlags = sV7.Header.GlobalIntFlags + sV8Header.GlobalStringFlags = sV7.Header.GlobalStringFlags + sV8Header.CommandType = sV7.Header.CommandType + sV8Header.CommandArgs = sV7.Header.CommandArgs + sV8Header.CommandBoolFlags = sV7.Header.CommandBoolFlags + sV8Header.CommandIntFlags = sV7.Header.CommandIntFlags + sV8Header.CommandStringFlags = sV7.Header.CommandStringFlags + sV8Header.LastCopied = sV7.Header.LastCopied + sV8Header.LastRemoved = sV7.Header.LastRemoved + sV8Header.TotalBytes = sV7.Header.TotalBytes + sV8Header.TotalObjects = sV7.Header.TotalObjects + + // Add insecure flag to the new V8 header + sV8Header.GlobalBoolFlags["insecure"] = false + + qs, e := quick.New(sV8Header) + fatalIf(probe.NewError(e).Trace(sid), "Unable to initialize quick config for session '8' header.") + + e = qs.Save(sessionFile) + fatalIf(probe.NewError(e).Trace(sid, sessionFile), "Unable to migrate session from '7' to '8'.") + + console.Println("Successfully migrated ‘" + sessionFile + "’ from version ‘" + sV7.Header.Version + "’ to " + "‘" + sV8Header.Version + "’.") + } +} + // Migrates session header version '6' to '7'. Only change is // LastRemoved field which was added in version '7'. func migrateSessionV6ToV7() { @@ -36,7 +88,10 @@ func migrateSessionV6ToV7() { } fatalIf(err.Trace(sid), "Unable to load version ‘6’. Migration failed please report this issue at https://github.com/minio/mc/issues.") } - if sV6Header.Version == "7" { // It is new format. + + sessionVersion, e := strconv.Atoi(sV6Header.Version) + fatalIf(probe.NewError(e), "Unable to load version ‘6’. Migration failed please report this issue at https://github.com/minio/mc/issues.") + if sessionVersion > 6 { // It is new format. continue } @@ -86,7 +141,6 @@ func migrateSessionV5ToV6() { sessionVersion, e := strconv.Atoi(sV6Header.Version) fatalIf(probe.NewError(e), "Unable to load version ‘6’. Migration failed please report this issue at https://github.com/minio/mc/issues.") - if sessionVersion > 5 { // It is new format. continue } diff --git a/cmd/session-old.go b/cmd/session-old.go index de20ac416a..00faab0eb7 100644 --- a/cmd/session-old.go +++ b/cmd/session-old.go @@ -18,6 +18,7 @@ package cmd import ( "os" + "sync" "time" "github.com/minio/minio/pkg/probe" @@ -74,3 +75,75 @@ func loadSessionV6Header(sid string) (*sessionV6Header, *probe.Error) { /////////////////// Session V7 /////////////////// // RESERVED FOR FUTURE + +// sessionV7Header for resumable sessions. +type sessionV7Header struct { + Version string `json:"version"` + When time.Time `json:"time"` + RootPath string `json:"workingFolder"` + GlobalBoolFlags map[string]bool `json:"globalBoolFlags"` + GlobalIntFlags map[string]int `json:"globalIntFlags"` + GlobalStringFlags map[string]string `json:"globalStringFlags"` + CommandType string `json:"commandType"` + CommandArgs []string `json:"cmdArgs"` + CommandBoolFlags map[string]bool `json:"cmdBoolFlags"` + CommandIntFlags map[string]int `json:"cmdIntFlags"` + CommandStringFlags map[string]string `json:"cmdStringFlags"` + LastCopied string `json:"lastCopied"` + LastRemoved string `json:"lastRemoved"` + TotalBytes int64 `json:"totalBytes"` + TotalObjects int `json:"totalObjects"` +} + +// sessionV7 resumable session container. +type sessionV7 struct { + Header *sessionV7Header + SessionID string + mutex *sync.Mutex + DataFP *sessionDataFP + sigCh bool +} + +// loadSessionV7 - reads session file if exists and re-initiates internal variables +func loadSessionV7(sid string) (*sessionV7, *probe.Error) { + if !isSessionDirExists() { + return nil, errInvalidArgument().Trace() + } + sessionFile, err := getSessionFile(sid) + if err != nil { + return nil, err.Trace(sid) + } + + if _, e := os.Stat(sessionFile); e != nil { + return nil, probe.NewError(e) + } + + s := &sessionV7{} + s.Header = &sessionV7Header{} + s.SessionID = sid + s.Header.Version = "7" + qs, e := quick.New(s.Header) + if e != nil { + return nil, probe.NewError(e).Trace(sid, s.Header.Version) + } + e = qs.Load(sessionFile) + if e != nil { + return nil, probe.NewError(e).Trace(sid, s.Header.Version) + } + + s.mutex = new(sync.Mutex) + s.Header = qs.Data().(*sessionV7Header) + + sessionDataFile, err := getSessionDataFile(s.SessionID) + if err != nil { + return nil, err.Trace(sid, s.Header.Version) + } + + dataFile, e := os.Open(sessionDataFile) + if e != nil { + return nil, probe.NewError(e) + } + s.DataFP = &sessionDataFP{false, dataFile} + + return s, nil +} diff --git a/cmd/session-v7.go b/cmd/session-v8.go similarity index 87% rename from cmd/session-v7.go rename to cmd/session-v8.go index 034fc82682..1b16c2c3d3 100644 --- a/cmd/session-v7.go +++ b/cmd/session-v8.go @@ -14,7 +14,7 @@ * limitations under the License. */ -// Package cmd - session V7 - Version 7 stores session header and session data in +// Package cmd - session V8 - Version 8 stores session header and session data in // two separate files. Session data contains fully prepared URL list. package cmd @@ -32,8 +32,8 @@ import ( "github.com/minio/minio/pkg/quick" ) -// sessionV7Header for resumable sessions. -type sessionV7Header struct { +// sessionV8Header for resumable sessions. +type sessionV8Header struct { Version string `json:"version"` When time.Time `json:"time"` RootPath string `json:"workingFolder"` @@ -60,9 +60,9 @@ type sessionMessage struct { CommandArgs []string `json:"commandArgs"` } -// sessionV7 resumable session container. -type sessionV7 struct { - Header *sessionV7Header +// sessionV8 resumable session container. +type sessionV8 struct { + Header *sessionV8Header SessionID string mutex *sync.Mutex DataFP *sessionDataFP @@ -81,7 +81,7 @@ func (file *sessionDataFP) Write(p []byte) (int, error) { } // String colorized session message. -func (s sessionV7) String() string { +func (s sessionV8) String() string { message := console.Colorize("SessionID", fmt.Sprintf("%s -> ", s.SessionID)) message = message + console.Colorize("SessionTime", fmt.Sprintf("[%s]", s.Header.When.Local().Format(printDate))) message = message + console.Colorize("Command", fmt.Sprintf(" %s %s", s.Header.CommandType, strings.Join(s.Header.CommandArgs, " "))) @@ -89,7 +89,7 @@ func (s sessionV7) String() string { } // JSON jsonified session message. -func (s sessionV7) JSON() string { +func (s sessionV8) JSON() string { sessionMsg := sessionMessage{ SessionID: s.SessionID, Time: s.Header.When.Local(), @@ -103,8 +103,8 @@ func (s sessionV7) JSON() string { return string(sessionBytes) } -// loadSessionV7 - reads session file if exists and re-initiates internal variables -func loadSessionV7(sid string) (*sessionV7, *probe.Error) { +// loadSessionV8 - reads session file if exists and re-initiates internal variables +func loadSessionV8(sid string) (*sessionV8, *probe.Error) { if !isSessionDirExists() { return nil, errInvalidArgument().Trace() } @@ -117,10 +117,10 @@ func loadSessionV7(sid string) (*sessionV7, *probe.Error) { return nil, probe.NewError(e) } - s := &sessionV7{} - s.Header = &sessionV7Header{} + s := &sessionV8{} + s.Header = &sessionV8Header{} s.SessionID = sid - s.Header.Version = "7" + s.Header.Version = "8" qs, e := quick.New(s.Header) if e != nil { return nil, probe.NewError(e).Trace(sid, s.Header.Version) @@ -131,7 +131,7 @@ func loadSessionV7(sid string) (*sessionV7, *probe.Error) { } s.mutex = new(sync.Mutex) - s.Header = qs.Data().(*sessionV7Header) + s.Header = qs.Data().(*sessionV8Header) sessionDataFile, err := getSessionDataFile(s.SessionID) if err != nil { @@ -147,11 +147,11 @@ func loadSessionV7(sid string) (*sessionV7, *probe.Error) { return s, nil } -// newSessionV7 provides a new session. -func newSessionV7() *sessionV7 { - s := &sessionV7{} - s.Header = &sessionV7Header{} - s.Header.Version = "7" +// newSessionV8 provides a new session. +func newSessionV8() *sessionV8 { + s := &sessionV8{} + s.Header = &sessionV8Header{} + s.Header.Version = "8" // map of command and files copied. s.Header.GlobalBoolFlags = make(map[string]bool) s.Header.GlobalIntFlags = make(map[string]int) @@ -179,19 +179,19 @@ func newSessionV7() *sessionV7 { } // HasData provides true if this is a session resume, false otherwise. -func (s sessionV7) HasData() bool { +func (s sessionV8) HasData() bool { return s.Header.LastCopied != "" || s.Header.LastRemoved != "" } // NewDataReader provides reader interface to session data file. -func (s *sessionV7) NewDataReader() io.Reader { +func (s *sessionV8) NewDataReader() io.Reader { // DataFP is always intitialized, either via new or load functions. s.DataFP.Seek(0, os.SEEK_SET) return io.Reader(s.DataFP) } // NewDataReader provides writer interface to session data file. -func (s *sessionV7) NewDataWriter() io.Writer { +func (s *sessionV8) NewDataWriter() io.Writer { // DataFP is always intitialized, either via new or load functions. s.DataFP.Seek(0, os.SEEK_SET) // when moving to file position 0 we want to truncate the file as well, @@ -201,7 +201,7 @@ func (s *sessionV7) NewDataWriter() io.Writer { } // Save this session. -func (s *sessionV7) Save() *probe.Error { +func (s *sessionV8) Save() *probe.Error { s.mutex.Lock() defer s.mutex.Unlock() @@ -230,32 +230,34 @@ func (s *sessionV7) Save() *probe.Error { // setGlobals captures the state of global variables into session header. // Used by newSession. -func (s *sessionV7) setGlobals() { +func (s *sessionV8) setGlobals() { s.Header.GlobalBoolFlags["quiet"] = globalQuiet s.Header.GlobalBoolFlags["debug"] = globalDebug s.Header.GlobalBoolFlags["json"] = globalJSON s.Header.GlobalBoolFlags["noColor"] = globalNoColor + s.Header.GlobalBoolFlags["insecure"] = globalInsecure } // RestoreGlobals restores the state of global variables. // Used by resumeSession. -func (s sessionV7) restoreGlobals() { +func (s sessionV8) restoreGlobals() { quiet := s.Header.GlobalBoolFlags["quiet"] debug := s.Header.GlobalBoolFlags["debug"] json := s.Header.GlobalBoolFlags["json"] noColor := s.Header.GlobalBoolFlags["noColor"] - setGlobals(quiet, debug, json, noColor) + insecure := s.Header.GlobalBoolFlags["insecure"] + setGlobals(quiet, debug, json, noColor, insecure) } // IsModified - returns if in memory session header has changed from // its on disk value. -func (s *sessionV7) isModified(sessionFile string) (bool, *probe.Error) { +func (s *sessionV8) isModified(sessionFile string) (bool, *probe.Error) { qs, e := quick.New(s.Header) if e != nil { return false, probe.NewError(e).Trace(s.SessionID) } - var currentHeader = &sessionV7Header{} + var currentHeader = &sessionV8Header{} currentQS, e := quick.Load(sessionFile, currentHeader) if e != nil { // If session does not exist for the first, return modified to @@ -278,7 +280,7 @@ func (s *sessionV7) isModified(sessionFile string) (bool, *probe.Error) { // save - wrapper for quick.Save and saves only if sessionHeader is // modified. -func (s *sessionV7) save() *probe.Error { +func (s *sessionV8) save() *probe.Error { sessionFile, err := getSessionFile(s.SessionID) if err != nil { return err.Trace(s.SessionID) @@ -305,7 +307,7 @@ func (s *sessionV7) save() *probe.Error { } // Close ends this session and removes all associated session files. -func (s *sessionV7) Close() *probe.Error { +func (s *sessionV8) Close() *probe.Error { s.mutex.Lock() defer s.mutex.Unlock() @@ -318,7 +320,7 @@ func (s *sessionV7) Close() *probe.Error { } // Delete removes all the session files. -func (s *sessionV7) Delete() *probe.Error { +func (s *sessionV8) Delete() *probe.Error { s.mutex.Lock() defer s.mutex.Unlock() @@ -353,7 +355,7 @@ func (s *sessionV7) Delete() *probe.Error { } // Close a session and exit. -func (s sessionV7) CloseAndDie() { +func (s sessionV8) CloseAndDie() { s.Close() console.Fatalln("Session safely terminated. To resume session ‘mc session resume " + s.SessionID + "’") } diff --git a/cmd/session.go b/cmd/session.go index 18f379e338..22fed4d914 100644 --- a/cmd/session.go +++ b/cmd/session.go @@ -31,6 +31,9 @@ func migrateSession() { // Migrate V6 to V7. migrateSessionV6ToV7() + + // Migrate V7 to V8 + migrateSessionV7ToV8() } // createSessionDir - create session directory. diff --git a/cmd/session_test.go b/cmd/session_test.go index c3a917fc22..974d251244 100644 --- a/cmd/session_test.go +++ b/cmd/session_test.go @@ -35,7 +35,7 @@ func (s *TestSuite) TestSession(c *C) { c.Assert(err, IsNil) c.Assert(isSessionDirExists(), Equals, true) - session := newSessionV7() + session := newSessionV8() c.Assert(session.Header.CommandArgs, IsNil) c.Assert(len(session.SessionID), Equals, 8) _, e := os.Stat(session.DataFP.Name()) @@ -45,7 +45,7 @@ func (s *TestSuite) TestSession(c *C) { c.Assert(err, IsNil) c.Assert(isSessionExists(session.SessionID), Equals, true) - savedSession, err := loadSessionV7(session.SessionID) + savedSession, err := loadSessionV8(session.SessionID) c.Assert(err, IsNil) c.Assert(session.SessionID, Equals, savedSession.SessionID) diff --git a/cmd/utils.go b/cmd/utils.go index 277b0143fa..1db9bde2d0 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -17,9 +17,12 @@ package cmd import ( + "crypto/tls" "math/rand" "path/filepath" "time" + + "github.com/minio/mc/pkg/console" ) var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") @@ -40,3 +43,18 @@ func isBucketVirtualStyle(host string) bool { googleVirtual, _ := filepath.Match("*.storage.googleapis.com", host) return s3Virtual || googleVirtual } + +// dumpTlsCertificates prints some fields of the certificates received from the server. +// Fields will be inspected by the user, so they must be conscise and useful +func dumpTLSCertificates(t *tls.ConnectionState) { + for _, cert := range t.PeerCertificates { + console.Debugln("TLS Certificate found: ") + if len(cert.Issuer.Country) > 0 { + console.Debugln(" >> Country: " + cert.Issuer.Country[0]) + } + if len(cert.Issuer.Organization) > 0 { + console.Debugln(" >> Organization: " + cert.Issuer.Organization[0]) + } + console.Debugln(" >> Expires: " + cert.NotAfter.String()) + } +}