diff --git a/common/crypto/expiration.go b/common/crypto/expiration.go index 985e30371af..565d21c11db 100644 --- a/common/crypto/expiration.go +++ b/common/crypto/expiration.go @@ -39,35 +39,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. @@ -82,6 +82,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 @@ -94,4 +96,5 @@ func trackCertExpiration(rawCert []byte, certRole string, warn WarnFunc, now tim sched(timeLeftUntilOneWeekBeforeExpiration, func() { warn("The %s certificate will expire within one week", certRole) }) + } diff --git a/common/crypto/expiration_test.go b/common/crypto/expiration_test.go index bd2199001b0..b6e4cbc5c93 100644 --- a/common/crypto/expiration_test.go +++ b/common/crypto/expiration_test.go @@ -10,6 +10,7 @@ import ( "fmt" "io/ioutil" "path/filepath" + "strings" "testing" "time" @@ -87,73 +88,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 { @@ -168,15 +186,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 c234940e21b..caa04c341d1 100644 --- a/internal/peer/node/start.go +++ b/internal/peer/node/start.go @@ -314,6 +314,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 79d4cd72d21..953c6145ad9 100644 --- a/orderer/common/server/main.go +++ b/orderer/common/server/main.go @@ -175,6 +175,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)