@@ -22,10 +22,13 @@ import (
2222 "encoding/json"
2323 "errors"
2424 "fmt"
25+ "github.com/hyperledger/firefly/internal/metrics"
2526 "io/ioutil"
2627 "net/http"
2728 "net/url"
29+ "strings"
2830 "testing"
31+ "time"
2932
3033 "github.com/hyperledger/firefly/mocks/metricsmocks"
3134
@@ -49,6 +52,8 @@ import (
4952var utConfig = config .RootSection ("ffdx_unit_tests" )
5053
5154const (
55+ // NOTE: the CA cert expires on Monday, February 28, 2035 7:30:57 PM,
56+ // and the leaf cert expires on Monday, February 28, 2028 7:30:57 PM
5257 testCertBundle = `
5358-----BEGIN CERTIFICATE-----
5459MIIDqTCCApGgAwIBAgIUbZT+Ds4f2oDmGpgVi+SaQq9gxvcwDQYJKoZIhvcNAQEL
@@ -94,6 +99,30 @@ rNTfiFZbc7eHmFRTkKXWW4j6b6ElygrBvV999BhCRNf6NS0/syjqsbALHkFGeIcl
9499R0gnXX/IZFnLhLh6UpLOBB0KIGENh75EEU7755jMKDKFj16D0uA1Lzrh5YxicTMy
95100ydFYQLpLycsWl2oV3JB4pO5TIzjY9awkRE0MeMMc
96101-----END CERTIFICATE-----
102+ `
103+ testExpiredCert = `
104+ -----BEGIN CERTIFICATE-----
105+ MIIDqjCCApKgAwIBAgIUWnobAQ4vq8gWBAXZBf7XZG3oSicwDQYJKoZIhvcNAQEL
106+ BQAwZDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
107+ DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCkV4YW1wbGUgQ0ExEzARBgNVBAMMCmV4
108+ YW1wbGUtY2EwHhcNMjUwMzAyMTQxNDA1WhcNMjUwMzAyMTQxNDA1WjB2MQswCQYD
109+ VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j
110+ aXNjbzEcMBoGA1UECgwTSHlwZXJsZWRnZXIgRmlyZWZseTEcMBoGA1UEAwwTaHlw
111+ ZXJsZWRnZXItZmlyZWZseTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
112+ AKlbQ+7cWWS0+QPp03PrdxsnAAtG2tWOk2CEG7HS3AlBU82YImhCidKOw+jQPS68
113+ 2f2d0tYBhugqB2Ki6HsfYMGTjHDLbUQ5y+cLk6PFbvhjm39Ayd+WGmhWht5qFtRN
114+ gllTa/SbG8+iGaSPIVFCyvg1IzxsFnBGn+05Gu+KjpL4i0l1RqDmy5ItxKGP77in
115+ RPEUkejiUozg/X3v2TWAGagIVF5+EQ2Cswot9W1faAvyu/QmSGLLfSH22GdEDHXa
116+ U4DV5ArJ2U2eNkOuasSWGKBopa/Wh1SZjKrNsy5Gw84ihAI4k7ARoP+vu1dIPdaX
117+ ElipmGMtUWu0Azn2l9QJZpMCAwEAAaNCMEAwHQYDVR0OBBYEFL798jEmX2+hw70t
118+ SmfJA78PZnnHMB8GA1UdIwQYMBaAFJfNoXmIn5S6W7Lcj5G/huW5q1YQMA0GCSqG
119+ SIb3DQEBCwUAA4IBAQA1dY8UCf1YSLG3Vu/u20ucw5q9tnYYoTi4fHm/g+imTvEQ
120+ KgTQBd5s9EHmj0BSjVFy9eSSTx5XiH6JqzGhCJRSbOIQ8RwrXpUlTuLr7gp0cO9c
121+ Ykxz6wt0k1F+9Iq+K8Eb6jzXoZe/ebMz611zUqY7+9lIl1AIIgx96MoZcDS/LA0e
122+ p/TUQ6q+Mg3W9pSXqLm8jmWNBfDViQF1v9Z3ASFYHUF/yak8jMdBEUpAqDadd/ay
123+ BHm9m8IvFevQjpUw6kyyg77ehEBBn7H/ISTL3HTCpUbkR3qUnFjOyBJ0G02XoozB
124+ I/hI0mpd6y+/JwyvG0smbD2lioiO/JQaUEZGU8pU
125+ -----END CERTIFICATE-----
97126`
98127)
99128
@@ -1047,16 +1076,109 @@ BAYTAkFVMRMwEQYDVQQIDApxdWVlbnNsYW5kMREwDwYDVQQHDAhCcm9va2ZpZWxk
10471076
10481077 _ , err := extractSoonestExpiryFromCertBundle (nonCertPEMBundle )
10491078 assert .ErrorContains (t , err , "failed to parse non-certificate within bundle" )
1079+ }
10501080
1081+ func TestCheckNodeIdentityStatusReturnsErrorWhenNotInitialized (t * testing.T ) {
1082+ h := & FFDX {initialized : false }
1083+ err := h .CheckNodeIdentityStatus (context .Background (), fftypes.JSONObject {}, & core.Identity {})
1084+ assert .Regexp (t , "FF10342" , err )
10511085}
10521086
1053- //
1054- //matchingProfile := fftypes.JSONAnyPtr(fmt.Sprintf(`{"cert": "%s" }`, strings.ReplaceAll(testCertBundle, "\n", `\n`))).JSONObject()
1055- //
1056- //nm.identity.(*identitymanagermocks.Manager).On("GetLocalNode", ctx).Return(&core.Identity{
1057- //IdentityProfile: core.IdentityProfile{
1058- //Profile: matchingProfile,
1059- //},
1060- //}, nil)
1061- //
1062- //expiry := time.Unix(1835379057, 0).UTC()
1087+ func TestCheckNodeIdentityStatusReturnsNilWhenCertIsEmpty (t * testing.T ) {
1088+ mmm := metricsmocks .NewManager (t )
1089+
1090+ h := & FFDX {initialized : true , metrics : mmm }
1091+ dxPeer := fftypes.JSONObject {"cert" : "" }
1092+ node := & core.Identity {
1093+ IdentityBase : core.IdentityBase {
1094+ Namespace : "ns1" ,
1095+ },
1096+ }
1097+
1098+ mmm .On ("IsMetricsEnabled" ).Return (true )
1099+ mmm .On ("NodeIdentityDXCertMismatch" , "ns1" , metrics .NodeIdentityDXCertMismatchStatusUnknown ).Return (true )
1100+
1101+ err := h .CheckNodeIdentityStatus (context .Background (), dxPeer , node )
1102+ assert .NoError (t , err )
1103+ }
1104+
1105+ func TestCheckNodeIdentityStatusReturnsErrorWhenNodeProfileIsNil (t * testing.T ) {
1106+ mmm := metricsmocks .NewManager (t )
1107+
1108+ h := & FFDX {initialized : true , metrics : mmm }
1109+ dxPeer := fftypes.JSONObject {"cert" : "cert" }
1110+ node := & core.Identity {
1111+ IdentityBase : core.IdentityBase {
1112+ Namespace : "ns1" ,
1113+ },
1114+ }
1115+ mmm .On ("IsMetricsEnabled" ).Return (false )
1116+
1117+ err := h .CheckNodeIdentityStatus (context .Background (), dxPeer , node )
1118+ assert .Error (t , err )
1119+ //assert.Equal(t, coremsgs.MsgDXInfoMissingID, err.(*i18n.Error).ID)
1120+ }
1121+
1122+ func TestCheckNodeIdentityStatusSetsMismatchStateWhenCertsDiffer (t * testing.T ) {
1123+
1124+ mmm := & metricsmocks.Manager {}
1125+ h := & FFDX {initialized : true , metrics : mmm }
1126+ dxPeer := fftypes.JSONObject {"cert" : "a-cert" }
1127+ node := & core.Identity {
1128+ IdentityBase : core.IdentityBase {
1129+ Namespace : "ns1" ,
1130+ },
1131+ IdentityProfile : core.IdentityProfile {
1132+ Profile : fftypes.JSONObject {"cert" : "b-cert" },
1133+ },
1134+ }
1135+
1136+ mmm .On ("IsMetricsEnabled" ).Return (true )
1137+ mmm .On ("NodeIdentityDXCertMismatch" , "ns1" , metrics .NodeIdentityDXCertMismatchStatusMismatched ).Return (true )
1138+ err := h .CheckNodeIdentityStatus (context .Background (), dxPeer , node )
1139+ assert .NoError (t , err )
1140+ }
1141+
1142+ func TestCheckNodeIdentityStatusSetsHealthyStateWhenCertsMatch (t * testing.T ) {
1143+ mmm := metricsmocks .NewManager (t )
1144+ h := & FFDX {initialized : true , metrics : mmm }
1145+ dxPeer := fftypes.JSONObject {"cert" : strings .ReplaceAll (testCertBundle , "\n " , `\n` )}
1146+ node := & core.Identity {
1147+ IdentityBase : core.IdentityBase {
1148+ Namespace : "ns1" ,
1149+ },
1150+ IdentityProfile : core.IdentityProfile {
1151+ Profile : fftypes.JSONObject {"cert" : strings .ReplaceAll (testCertBundle , "\n " , `\n` )},
1152+ },
1153+ }
1154+
1155+ mmm .On ("IsMetricsEnabled" ).Return (true )
1156+ mmm .On ("NodeIdentityDXCertMismatch" , "ns1" , metrics .NodeIdentityDXCertMismatchStatusHealthy ).Return (true )
1157+ expiry := time .Unix (1835379057 , 0 ).UTC ()
1158+ mmm .On ("NodeIdentityDXCertExpiry" , "ns1" , expiry ).Return (true )
1159+
1160+ err := h .CheckNodeIdentityStatus (context .Background (), dxPeer , node )
1161+ assert .NoError (t , err )
1162+ }
1163+
1164+ func TestCheckNodeIdentityStatusSetsHealthyStateWhenCertsExpire (t * testing.T ) {
1165+ mmm := metricsmocks .NewManager (t )
1166+ h := & FFDX {initialized : true , metrics : mmm }
1167+ dxPeer := fftypes.JSONObject {"cert" : strings .ReplaceAll (testExpiredCert , "\n " , `\n` )}
1168+ node := & core.Identity {
1169+ IdentityBase : core.IdentityBase {
1170+ Namespace : "ns1" ,
1171+ },
1172+ IdentityProfile : core.IdentityProfile {
1173+ Profile : fftypes.JSONObject {"cert" : strings .ReplaceAll (testExpiredCert , "\n " , `\n` )},
1174+ },
1175+ }
1176+
1177+ mmm .On ("IsMetricsEnabled" ).Return (true )
1178+ mmm .On ("NodeIdentityDXCertMismatch" , "ns1" , metrics .NodeIdentityDXCertMismatchStatusHealthy ).Return (true )
1179+ expiry := time .Unix (1740924845 , 0 ).UTC ()
1180+ mmm .On ("NodeIdentityDXCertExpiry" , "ns1" , expiry ).Return (true )
1181+
1182+ err := h .CheckNodeIdentityStatus (context .Background (), dxPeer , node )
1183+ assert .NoError (t , err )
1184+ }
0 commit comments