From bf8f6fc7164f8767bf55bd0fa02b3fb6116130d1 Mon Sep 17 00:00:00 2001 From: denyeart Date: Wed, 26 Aug 2020 09:32:58 -0400 Subject: [PATCH] [FAB-18188] Log orderer and peer cert expiration date upon startup (#1804) FAB-17000 added a warning if expiration is within a week. This change additionally info logs the future enrollment, tls server, and tls client cert expiration dates upon startup, regardless of whether they will expire within a week or not. Signed-off-by: David Enyeart (cherry picked from commit bd7180cd1be1e20b6a48b356e093afaddab082cb) --- common/crypto/expiration.go | 17 +++--- common/crypto/expiration_test.go | 96 ++++++++++++++++++++------------ internal/peer/node/start.go | 1 + orderer/common/server/main.go | 1 + 4 files changed, 73 insertions(+), 42 deletions(-) diff --git a/common/crypto/expiration.go b/common/crypto/expiration.go index 24d22367afa..8b1e0336347 100644 --- a/common/crypto/expiration.go +++ b/common/crypto/expiration.go @@ -41,35 +41,35 @@ func certExpirationTime(pemBytes []byte) time.Time { return cert.NotAfter } -// WarnFunc notifies a warning happened with the given format, and can be replaced with Warnf of a logger. -type WarnFunc func(format string, args ...interface{}) +// MessageFunc notifies a message happened with the given format, and can be replaced with Warnf or Infof of a logger. +type MessageFunc func(format string, args ...interface{}) // Scheduler invokes f after d time, and can be replaced with time.AfterFunc. type Scheduler func(d time.Duration, f func()) *time.Timer // TrackExpiration warns a week before one of the certificates expires -func TrackExpiration(tls bool, serverCert []byte, clientCertChain [][]byte, sIDBytes []byte, warn WarnFunc, now time.Time, s Scheduler) { +func TrackExpiration(tls bool, serverCert []byte, clientCertChain [][]byte, sIDBytes []byte, info MessageFunc, warn MessageFunc, now time.Time, s Scheduler) { sID := &msp.SerializedIdentity{} if err := proto.Unmarshal(sIDBytes, sID); err != nil { return } - trackCertExpiration(sID.IdBytes, "enrollment", warn, now, s) + trackCertExpiration(sID.IdBytes, "enrollment", info, warn, now, s) if !tls { return } - trackCertExpiration(serverCert, "server TLS", warn, now, s) + trackCertExpiration(serverCert, "server TLS", info, warn, now, s) if len(clientCertChain) == 0 || len(clientCertChain[0]) == 0 { return } - trackCertExpiration(clientCertChain[0], "client TLS", warn, now, s) + trackCertExpiration(clientCertChain[0], "client TLS", info, warn, now, s) } -func trackCertExpiration(rawCert []byte, certRole string, warn WarnFunc, now time.Time, sched Scheduler) { +func trackCertExpiration(rawCert []byte, certRole string, info MessageFunc, warn MessageFunc, now time.Time, sched Scheduler) { expirationTime := certExpirationTime(rawCert) if expirationTime.IsZero() { // If the certificate expiration time cannot be classified, return. @@ -84,6 +84,8 @@ func trackCertExpiration(rawCert []byte, certRole string, warn WarnFunc, now tim return } + info("The %s certificate will expire on %s", certRole, expirationTime) + if timeLeftUntilExpiration < oneWeek { days := timeLeftUntilExpiration / (time.Hour * 24) hours := (timeLeftUntilExpiration - (days * time.Hour * 24)) / time.Hour @@ -96,6 +98,7 @@ func trackCertExpiration(rawCert []byte, certRole string, warn WarnFunc, now tim sched(timeLeftUntilOneWeekBeforeExpiration, func() { warn("The %s certificate will expire within one week", certRole) }) + } var ( diff --git a/common/crypto/expiration_test.go b/common/crypto/expiration_test.go index 485a70bbefe..f3f438d000c 100644 --- a/common/crypto/expiration_test.go +++ b/common/crypto/expiration_test.go @@ -13,6 +13,7 @@ import ( "fmt" "io/ioutil" "path/filepath" + "strings" "testing" "time" @@ -91,73 +92,90 @@ func TestTrackExpiration(t *testing.T) { IdBytes: tlsCert.Cert, }) - shouldNotBeInvoked := func(format string, args ...interface{}) { + warnShouldNotBeInvoked := func(format string, args ...interface{}) { t.Fatalf(format, args...) } var formattedWarning string - shouldBeInvoked := func(format string, args ...interface{}) { + warnShouldBeInvoked := func(format string, args ...interface{}) { formattedWarning = fmt.Sprintf(format, args...) } + var formattedInfo string + infoShouldBeInvoked := func(format string, args ...interface{}) { + formattedInfo = fmt.Sprintf(format, args...) + } + for _, testCase := range []struct { - description string - tls bool - serverCert []byte - clientCertChain [][]byte - sIDBytes []byte - warn WarnFunc - now time.Time - expectedWarn string + description string + tls bool + serverCert []byte + clientCertChain [][]byte + sIDBytes []byte + info MessageFunc + warn MessageFunc + now time.Time + expectedInfoPrefix string + expectedWarn string }{ { description: "No TLS, enrollment cert isn't valid logs a warning", - warn: shouldNotBeInvoked, + warn: warnShouldNotBeInvoked, sIDBytes: []byte{1, 2, 3}, }, { - description: "No TLS, enrollment cert expires soon", - sIDBytes: signingIdentity, - warn: shouldBeInvoked, - now: monthBeforeExpiration, - expectedWarn: "The enrollment certificate will expire within one week", + description: "No TLS, enrollment cert expires soon", + sIDBytes: signingIdentity, + info: infoShouldBeInvoked, + warn: warnShouldBeInvoked, + now: monthBeforeExpiration, + expectedInfoPrefix: "The enrollment certificate will expire on", + expectedWarn: "The enrollment certificate will expire within one week", }, { - description: "TLS, server cert expires soon", - warn: shouldBeInvoked, - now: monthBeforeExpiration, - tls: true, - serverCert: tlsCert.Cert, - expectedWarn: "The server TLS certificate will expire within one week", + description: "TLS, server cert expires soon", + info: infoShouldBeInvoked, + warn: warnShouldBeInvoked, + now: monthBeforeExpiration, + tls: true, + serverCert: tlsCert.Cert, + expectedInfoPrefix: "The server TLS certificate will expire on", + expectedWarn: "The server TLS certificate will expire within one week", }, { - description: "TLS, server cert expires really soon", - warn: shouldBeInvoked, - now: twoDaysBeforeExpiration, - tls: true, - serverCert: tlsCert.Cert, - expectedWarn: "The server TLS certificate expires within 2 days and 12 hours", + description: "TLS, server cert expires really soon", + info: infoShouldBeInvoked, + warn: warnShouldBeInvoked, + now: twoDaysBeforeExpiration, + tls: true, + serverCert: tlsCert.Cert, + expectedInfoPrefix: "The server TLS certificate will expire on", + expectedWarn: "The server TLS certificate expires within 2 days and 12 hours", }, { description: "TLS, server cert has expired", - warn: shouldBeInvoked, + info: infoShouldBeInvoked, + warn: warnShouldBeInvoked, now: expirationTime.Add(time.Hour), tls: true, serverCert: tlsCert.Cert, expectedWarn: "The server TLS certificate has expired", }, { - description: "TLS, client cert expires soon", - warn: shouldBeInvoked, - now: monthBeforeExpiration, - tls: true, - clientCertChain: [][]byte{tlsCert.Cert}, - expectedWarn: "The client TLS certificate will expire within one week", + description: "TLS, client cert expires soon", + info: infoShouldBeInvoked, + warn: warnShouldBeInvoked, + now: monthBeforeExpiration, + tls: true, + clientCertChain: [][]byte{tlsCert.Cert}, + expectedInfoPrefix: "The client TLS certificate will expire on", + expectedWarn: "The client TLS certificate will expire within one week", }, } { t.Run(testCase.description, func(t *testing.T) { defer func() { formattedWarning = "" + formattedInfo = "" }() fakeTimeAfter := func(duration time.Duration, f func()) *time.Timer { @@ -172,15 +190,23 @@ func TestTrackExpiration(t *testing.T) { testCase.serverCert, testCase.clientCertChain, testCase.sIDBytes, + testCase.info, testCase.warn, testCase.now, fakeTimeAfter) + if testCase.expectedInfoPrefix != "" { + require.True(t, strings.HasPrefix(formattedInfo, testCase.expectedInfoPrefix)) + } else { + require.Empty(t, formattedInfo) + } + if testCase.expectedWarn != "" { assert.Equal(t, testCase.expectedWarn, formattedWarning) } else { assert.Empty(t, formattedWarning) } + }) } } diff --git a/internal/peer/node/start.go b/internal/peer/node/start.go index 63c0ae91904..430c9731170 100644 --- a/internal/peer/node/start.go +++ b/internal/peer/node/start.go @@ -313,6 +313,7 @@ func serve(args []string) error { serverConfig.SecOpts.Certificate, cs.GetClientCertificate().Certificate, signingIdentityBytes, + expirationLogger.Infof, expirationLogger.Warnf, // This can be used to piggyback a metric event in the future time.Now(), time.AfterFunc, diff --git a/orderer/common/server/main.go b/orderer/common/server/main.go index b4941c0c934..be9fd008d33 100644 --- a/orderer/common/server/main.go +++ b/orderer/common/server/main.go @@ -200,6 +200,7 @@ func Main() { serverConfig.SecOpts.Certificate, [][]byte{clusterClientConfig.SecOpts.Certificate}, identityBytes, + expirationLogger.Infof, expirationLogger.Warnf, // This can be used to piggyback a metric event in the future time.Now(), time.AfterFunc)