github.com/hyperledger-labs/bdls@v2.1.1+incompatible/common/crypto/expiration_test.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  	"fmt"
    11  	"io/ioutil"
    12  	"path/filepath"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/golang/protobuf/proto"
    17  	"github.com/hyperledger/fabric-protos-go/msp"
    18  	"github.com/hyperledger/fabric/common/crypto/tlsgen"
    19  	"github.com/hyperledger/fabric/protoutil"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestX509CertExpiresAt(t *testing.T) {
    24  	certBytes, err := ioutil.ReadFile(filepath.Join("testdata", "cert.pem"))
    25  	assert.NoError(t, err)
    26  	sId := &msp.SerializedIdentity{
    27  		IdBytes: certBytes,
    28  	}
    29  	serializedIdentity, err := proto.Marshal(sId)
    30  	assert.NoError(t, err)
    31  	expirationTime := ExpiresAt(serializedIdentity)
    32  	assert.Equal(t, time.Date(2027, 8, 17, 12, 19, 48, 0, time.UTC), expirationTime)
    33  }
    34  
    35  func TestX509InvalidCertExpiresAt(t *testing.T) {
    36  	certBytes, err := ioutil.ReadFile(filepath.Join("testdata", "badCert.pem"))
    37  	assert.NoError(t, err)
    38  	sId := &msp.SerializedIdentity{
    39  		IdBytes: certBytes,
    40  	}
    41  	serializedIdentity, err := proto.Marshal(sId)
    42  	assert.NoError(t, err)
    43  	expirationTime := ExpiresAt(serializedIdentity)
    44  	assert.True(t, expirationTime.IsZero())
    45  }
    46  
    47  func TestIdemixIdentityExpiresAt(t *testing.T) {
    48  	idemixId := &msp.SerializedIdemixIdentity{
    49  		NymX: []byte{1, 2, 3},
    50  		NymY: []byte{1, 2, 3},
    51  		Ou:   []byte("OU1"),
    52  	}
    53  	idemixBytes, err := proto.Marshal(idemixId)
    54  	assert.NoError(t, err)
    55  	sId := &msp.SerializedIdentity{
    56  		IdBytes: idemixBytes,
    57  	}
    58  	serializedIdentity, err := proto.Marshal(sId)
    59  	assert.NoError(t, err)
    60  	expirationTime := ExpiresAt(serializedIdentity)
    61  	assert.True(t, expirationTime.IsZero())
    62  }
    63  
    64  func TestInvalidIdentityExpiresAt(t *testing.T) {
    65  	expirationTime := ExpiresAt([]byte{1, 2, 3})
    66  	assert.True(t, expirationTime.IsZero())
    67  }
    68  
    69  func TestTrackExpiration(t *testing.T) {
    70  	ca, err := tlsgen.NewCA()
    71  	assert.NoError(t, err)
    72  
    73  	now := time.Now()
    74  	expirationTime := certExpirationTime(ca.CertBytes())
    75  
    76  	timeUntilExpiration := expirationTime.Sub(now)
    77  	timeUntilOneMonthBeforeExpiration := timeUntilExpiration - 28*24*time.Hour
    78  	timeUntil2DaysBeforeExpiration := timeUntilExpiration - 2*24*time.Hour - time.Hour*12
    79  
    80  	monthBeforeExpiration := now.Add(timeUntilOneMonthBeforeExpiration)
    81  	twoDaysBeforeExpiration := now.Add(timeUntil2DaysBeforeExpiration)
    82  
    83  	tlsCert, err := ca.NewServerCertKeyPair("127.0.0.1")
    84  	assert.NoError(t, err)
    85  
    86  	signingIdentity := protoutil.MarshalOrPanic(&msp.SerializedIdentity{
    87  		IdBytes: tlsCert.Cert,
    88  	})
    89  
    90  	shouldNotBeInvoked := func(format string, args ...interface{}) {
    91  		t.Fatalf(format, args...)
    92  	}
    93  
    94  	var formattedWarning string
    95  	shouldBeInvoked := func(format string, args ...interface{}) {
    96  		formattedWarning = fmt.Sprintf(format, args...)
    97  	}
    98  
    99  	for _, testCase := range []struct {
   100  		description     string
   101  		tls             bool
   102  		serverCert      []byte
   103  		clientCertChain [][]byte
   104  		sIDBytes        []byte
   105  		warn            WarnFunc
   106  		now             time.Time
   107  		expectedWarn    string
   108  	}{
   109  		{
   110  			description: "No TLS, enrollment cert isn't valid logs a warning",
   111  			warn:        shouldNotBeInvoked,
   112  			sIDBytes:    []byte{1, 2, 3},
   113  		},
   114  		{
   115  			description:  "No TLS, enrollment cert expires soon",
   116  			sIDBytes:     signingIdentity,
   117  			warn:         shouldBeInvoked,
   118  			now:          monthBeforeExpiration,
   119  			expectedWarn: "The enrollment certificate will expire within one week",
   120  		},
   121  		{
   122  			description:  "TLS, server cert expires soon",
   123  			warn:         shouldBeInvoked,
   124  			now:          monthBeforeExpiration,
   125  			tls:          true,
   126  			serverCert:   tlsCert.Cert,
   127  			expectedWarn: "The server TLS certificate will expire within one week",
   128  		},
   129  		{
   130  			description:  "TLS, server cert expires really soon",
   131  			warn:         shouldBeInvoked,
   132  			now:          twoDaysBeforeExpiration,
   133  			tls:          true,
   134  			serverCert:   tlsCert.Cert,
   135  			expectedWarn: "The server TLS certificate expires within 2 days and 12 hours",
   136  		},
   137  		{
   138  			description:  "TLS, server cert has expired",
   139  			warn:         shouldBeInvoked,
   140  			now:          expirationTime.Add(time.Hour),
   141  			tls:          true,
   142  			serverCert:   tlsCert.Cert,
   143  			expectedWarn: "The server TLS certificate has expired",
   144  		},
   145  		{
   146  			description:     "TLS, client cert expires soon",
   147  			warn:            shouldBeInvoked,
   148  			now:             monthBeforeExpiration,
   149  			tls:             true,
   150  			clientCertChain: [][]byte{tlsCert.Cert},
   151  			expectedWarn:    "The client TLS certificate will expire within one week",
   152  		},
   153  	} {
   154  		t.Run(testCase.description, func(t *testing.T) {
   155  			defer func() {
   156  				formattedWarning = ""
   157  			}()
   158  
   159  			fakeTimeAfter := func(duration time.Duration, f func()) *time.Timer {
   160  				assert.NotEmpty(t, testCase.expectedWarn)
   161  				threeWeeks := 3 * 7 * 24 * time.Hour
   162  				assert.Equal(t, threeWeeks, duration)
   163  				f()
   164  				return nil
   165  			}
   166  
   167  			TrackExpiration(testCase.tls,
   168  				testCase.serverCert,
   169  				testCase.clientCertChain,
   170  				testCase.sIDBytes,
   171  				testCase.warn,
   172  				testCase.now,
   173  				fakeTimeAfter)
   174  
   175  			if testCase.expectedWarn != "" {
   176  				assert.Equal(t, testCase.expectedWarn, formattedWarning)
   177  			} else {
   178  				assert.Empty(t, formattedWarning)
   179  			}
   180  		})
   181  	}
   182  }