github.com/hyperledger-labs/bdls@v2.1.1+incompatible/common/crypto/expiration.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package crypto 8 9 import ( 10 "crypto/x509" 11 "encoding/pem" 12 "time" 13 14 "github.com/golang/protobuf/proto" 15 "github.com/hyperledger/fabric-protos-go/msp" 16 ) 17 18 // ExpiresAt returns when the given identity expires, or a zero time.Time 19 // in case we cannot determine that 20 func ExpiresAt(identityBytes []byte) time.Time { 21 sId := &msp.SerializedIdentity{} 22 // If protobuf parsing failed, we make no decisions about the expiration time 23 if err := proto.Unmarshal(identityBytes, sId); err != nil { 24 return time.Time{} 25 } 26 return certExpirationTime(sId.IdBytes) 27 } 28 29 func certExpirationTime(pemBytes []byte) time.Time { 30 bl, _ := pem.Decode(pemBytes) 31 if bl == nil { 32 // If the identity isn't a PEM block, we make no decisions about the expiration time 33 return time.Time{} 34 } 35 cert, err := x509.ParseCertificate(bl.Bytes) 36 if err != nil { 37 return time.Time{} 38 } 39 return cert.NotAfter 40 } 41 42 // WarnFunc notifies a warning happened with the given format, and can be replaced with Warnf of a logger. 43 type WarnFunc func(format string, args ...interface{}) 44 45 // Scheduler invokes f after d time, and can be replaced with time.AfterFunc. 46 type Scheduler func(d time.Duration, f func()) *time.Timer 47 48 // TrackExpiration warns a week before one of the certificates expires 49 func TrackExpiration(tls bool, serverCert []byte, clientCertChain [][]byte, sIDBytes []byte, warn WarnFunc, now time.Time, s Scheduler) { 50 sID := &msp.SerializedIdentity{} 51 if err := proto.Unmarshal(sIDBytes, sID); err != nil { 52 return 53 } 54 55 trackCertExpiration(sID.IdBytes, "enrollment", warn, now, s) 56 57 if !tls { 58 return 59 } 60 61 trackCertExpiration(serverCert, "server TLS", warn, now, s) 62 63 if len(clientCertChain) == 0 || len(clientCertChain[0]) == 0 { 64 return 65 } 66 67 trackCertExpiration(clientCertChain[0], "client TLS", warn, now, s) 68 } 69 70 func trackCertExpiration(rawCert []byte, certRole string, warn WarnFunc, now time.Time, sched Scheduler) { 71 expirationTime := certExpirationTime(rawCert) 72 if expirationTime.IsZero() { 73 // If the certificate expiration time cannot be classified, return. 74 return 75 } 76 77 timeLeftUntilExpiration := expirationTime.Sub(now) 78 oneWeek := time.Hour * 24 * 7 79 80 if timeLeftUntilExpiration < 0 { 81 warn("The %s certificate has expired", certRole) 82 return 83 } 84 85 if timeLeftUntilExpiration < oneWeek { 86 days := timeLeftUntilExpiration / (time.Hour * 24) 87 hours := (timeLeftUntilExpiration - (days * time.Hour * 24)) / time.Hour 88 warn("The %s certificate expires within %d days and %d hours", certRole, days, hours) 89 return 90 } 91 92 timeLeftUntilOneWeekBeforeExpiration := timeLeftUntilExpiration - oneWeek 93 94 sched(timeLeftUntilOneWeekBeforeExpiration, func() { 95 warn("The %s certificate will expire within one week", certRole) 96 }) 97 }