Skip to content

Commit e3697d1

Browse files
committed
cleaned up code and tests
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
1 parent 35f3bbe commit e3697d1

File tree

18 files changed

+218
-230
lines changed

18 files changed

+218
-230
lines changed

internal/apiserver/route_get_subscription_events_filtered_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,4 @@ func TestGetSubscriptionEventsFilteredNoSequenceIDsProvided(t *testing.T) {
8282

8383
r.ServeHTTP(res, req)
8484
assert.Equal(t, 200, res.Result().StatusCode)
85-
}
85+
}

internal/database/sqlcommon/event_sql_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func TestGetEventsInSequenceRangeE2EWithDB(t *testing.T) {
107107
Type: core.EventTypeMessageConfirmed,
108108
Reference: fftypes.NewUUID(),
109109
Correlator: fftypes.NewUUID(),
110-
Topic: fmt.Sprintf("topic%d", i % 2),
110+
Topic: fmt.Sprintf("topic%d", i%2),
111111
Created: fftypes.Now(),
112112
}
113113
err := s.InsertEvent(ctx, event)
@@ -322,10 +322,9 @@ func TestGetEventsInSequenceRangeBuildQueryFail(t *testing.T) {
322322

323323
func TestGetEventsInSequenceRangeShouldCallGetEventsWhenNoSequencedProvidedAndThrowAnError(t *testing.T) {
324324
s, mock := newMockProvider().init()
325-
mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id", }).AddRow("only one"))
325+
mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow("only one"))
326326
f := database.EventQueryFactory.NewFilter(context.Background()).And()
327327
_, _, err := s.GetEventsInSequenceRange(context.Background(), "ns1", f, -1, -1)
328328
assert.NotNil(t, err)
329329
assert.NoError(t, mock.ExpectationsWereMet())
330330
}
331-

internal/dataexchange/ffdx/ffdx.go

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,17 @@ package ffdx
1818

1919
import (
2020
"context"
21+
"crypto/x509"
2122
"encoding/json"
23+
"encoding/pem"
24+
"errors"
2225
"fmt"
2326
"io"
2427
"strings"
2528
"sync"
29+
"time"
30+
31+
"github.com/hyperledger/firefly/internal/metrics"
2632

2733
"github.com/go-resty/resty/v2"
2834
"github.com/hyperledger/firefly-common/pkg/config"
@@ -54,6 +60,8 @@ type FFDX struct {
5460
retry *retry.Retry
5561
backgroundStart bool
5662
backgroundRetry *retry.Retry
63+
64+
metrics metrics.Manager // optional
5765
}
5866

5967
type dxNode struct {
@@ -168,7 +176,7 @@ func (h *FFDX) Name() string {
168176
return "ffdx"
169177
}
170178

171-
func (h *FFDX) Init(ctx context.Context, cancelCtx context.CancelFunc, config config.Section) (err error) {
179+
func (h *FFDX) Init(ctx context.Context, cancelCtx context.CancelFunc, config config.Section, metrics metrics.Manager) (err error) {
172180
h.ctx = log.WithLogField(ctx, "dx", "https")
173181
h.cancelCtx = cancelCtx
174182
h.ackChannel = make(chan *ack)
@@ -179,6 +187,7 @@ func (h *FFDX) Init(ctx context.Context, cancelCtx context.CancelFunc, config co
179187
}
180188
h.needsInit = config.GetBool(DataExchangeInitEnabled)
181189
h.nodes = make(map[string]*dxNode)
190+
h.metrics = metrics
182191

183192
if config.GetString(ffresty.HTTPConfigURL) == "" {
184193
return i18n.NewError(ctx, coremsgs.MsgMissingPluginConfig, "url", "dataexchange.ffdx")
@@ -456,6 +465,79 @@ func (h *FFDX) TransferBlob(ctx context.Context, nsOpID string, peer, sender fft
456465
return nil
457466
}
458467

468+
func (h *FFDX) CheckNodeIdentityStatus(ctx context.Context, dxPeer fftypes.JSONObject, node *core.Identity) error {
469+
if err := h.checkInitialized(h.ctx); err != nil {
470+
return err
471+
}
472+
473+
if dxPeer.GetString("cert") == "" {
474+
log.L(ctx).Warnf("DX peer does not have a 'cert', DX plugin may be unsupported")
475+
return nil
476+
}
477+
478+
if node.Profile == nil || node.Profile.GetString("cert") == "" {
479+
return i18n.NewError(ctx, coremsgs.MsgDXInfoMissingID) // TODO
480+
}
481+
482+
var mismatchState = metrics.NodeIdentityDXCertMismatchStatusUnknown
483+
defer func() {
484+
if h.metrics != nil && h.metrics.IsMetricsEnabled() {
485+
h.metrics.NodeIdentityDXCertMismatch(node.Namespace, mismatchState)
486+
}
487+
}()
488+
489+
mismatchState = metrics.NodeIdentityDXCertMismatchStatusHealthy
490+
if dxPeer.GetString("cert") != node.Profile.GetString("cert") {
491+
mismatchState = metrics.NodeIdentityDXCertMismatchStatusMismatched
492+
}
493+
494+
if h.metrics != nil && h.metrics.IsMetricsEnabled() {
495+
expiry, err := extractSoonestExpiryFromCertBundle(dxPeer.GetString("cert"))
496+
if err == nil {
497+
if expiry.Before(time.Now()) {
498+
log.L(ctx).Warnf("Certificate for node '%s' has expired", node.Name)
499+
}
500+
501+
h.metrics.NodeIdentityDXCertExpiry(node.Namespace, expiry)
502+
} else {
503+
log.L(ctx).Errorf("Failed to find x509 cert within DX cert bundle node='%s' namespace='%s'", node.Name, node.Namespace)
504+
}
505+
}
506+
507+
return nil
508+
}
509+
510+
// we assume the cert with the soonest expiry is the leaf cert, but even if its the CA,
511+
// thats what will invalidate the leaf anyways, so really we only care about the soonest expiry
512+
func extractSoonestExpiryFromCertBundle(certBundle string) (time.Time, error) {
513+
var leafCert *x509.Certificate
514+
var block *pem.Block
515+
var rest = []byte(certBundle)
516+
517+
for {
518+
block, rest = pem.Decode(rest)
519+
if block == nil {
520+
break
521+
}
522+
if block.Type != "CERTIFICATE" {
523+
continue
524+
}
525+
cert, err := x509.ParseCertificate(block.Bytes)
526+
if err != nil {
527+
return time.Time{}, fmt.Errorf("failed to parse certificate: %v", err)
528+
}
529+
if leafCert == nil || cert.NotAfter.Before(leafCert.NotAfter) {
530+
leafCert = cert
531+
}
532+
}
533+
534+
if leafCert == nil {
535+
return time.Time{}, errors.New("no valid certificate found")
536+
}
537+
538+
return leafCert.NotAfter.UTC(), nil
539+
}
540+
459541
func (h *FFDX) ackLoop() {
460542
for {
461543
select {

internal/dataexchange/ffdx/ffdx_test.go

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"net/url"
2727
"testing"
2828

29+
"github.com/hyperledger/firefly/mocks/metricsmocks"
30+
2931
"github.com/hyperledger/firefly-common/pkg/config"
3032
"github.com/hyperledger/firefly-common/pkg/ffresty"
3133
"github.com/hyperledger/firefly-common/pkg/fftls"
@@ -45,6 +47,55 @@ import (
4547

4648
var utConfig = config.RootSection("ffdx_unit_tests")
4749

50+
const (
51+
testCertBundle = `
52+
-----BEGIN CERTIFICATE-----
53+
MIIDqTCCApGgAwIBAgIUbZT+Ds4f2oDmGpgVi+SaQq9gxvcwDQYJKoZIhvcNAQEL
54+
BQAwZDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
55+
DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCkV4YW1wbGUgQ0ExEzARBgNVBAMMCmV4
56+
YW1wbGUtY2EwHhcNMjUwMjI4MTkzMDM4WhcNMzUwMjI2MTkzMDM4WjBkMQswCQYD
57+
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j
58+
aXNjbzETMBEGA1UECgwKRXhhbXBsZSBDQTETMBEGA1UEAwwKZXhhbXBsZS1jYTCC
59+
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOWBryFqk0YqQ6pzGJvBDjbV
60+
4BnkMzsv+Fq869Xks09OP4eW44oqfFUmpCFyS3fEmRCz+389t4mKvxcCRIJMW0f5
61+
K9jffG1QKUKL4UuNfEPFpM0MXTwhI+dCdvofdelzc+KBGA6CDYlnWYcCKFSuWeSu
62+
xrb/qCEvhcCaSYt3e2WcRHRuK+OLzM3REeJctC4G/pq858OUV5CZU2B6aGV/9uFL
63+
ZW3TCrOaj+Khzzt5FNvjVdLiUw0FS8VESxFA4kH8p+XUshs9S0e7LfIBSID2NU8+
64+
+5D6HliqNqikbsny1Ps6GhLa+nI37LOVj7nFcG7uk+gb6HUN1+0YvjOJ0/zvnLEC
65+
AwEAAaNTMFEwHQYDVR0OBBYEFJfNoXmIn5S6W7Lcj5G/huW5q1YQMB8GA1UdIwQY
66+
MBaAFJfNoXmIn5S6W7Lcj5G/huW5q1YQMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
67+
hvcNAQELBQADggEBALsdRYJHQMkhjLcrO4Yha1KXh2d+irmi8AqQqQgbLIsSzuqG
68+
bKFiYnJ8PKHaISHlev2xRM9kEjDZ/9q8T4aUELg4eBjj7VK+gs+gSBO6peJ+AcEg
69+
TepsE5GHmhoIIiE/3dIP6XnaM6NBb8q0ewsIg1c5vLlrt8W96LY6Og7f+742VvoV
70+
H31srpGjy7c5nYjBTn/Bu84eb5Lxfvy10sJjnenkXDJvzkUcnfbRzDQ9k5ZuPa05
71+
x+BsxonN0iaeZH91F+Y3kgJidLnU5EhIB/1KXYjuEbl9qUxD6GFHRststPRPeOmj
72+
7C+BtJCIjjavysSqVMvQWLQ6rXms3SpRPAimWqM=
73+
-----END CERTIFICATE-----
74+
-----BEGIN CERTIFICATE-----
75+
MIIDqjCCApKgAwIBAgIUWnobAQ4vq8gWBAXZBf7XZG3oSiUwDQYJKoZIhvcNAQEL
76+
BQAwZDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
77+
DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCkV4YW1wbGUgQ0ExEzARBgNVBAMMCmV4
78+
YW1wbGUtY2EwHhcNMjUwMjI4MTkzMDU3WhcNMjgwMjI4MTkzMDU3WjB2MQswCQYD
79+
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j
80+
aXNjbzEcMBoGA1UECgwTSHlwZXJsZWRnZXIgRmlyZWZseTEcMBoGA1UEAwwTaHlw
81+
ZXJsZWRnZXItZmlyZWZseTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
82+
AKlbQ+7cWWS0+QPp03PrdxsnAAtG2tWOk2CEG7HS3AlBU82YImhCidKOw+jQPS68
83+
2f2d0tYBhugqB2Ki6HsfYMGTjHDLbUQ5y+cLk6PFbvhjm39Ayd+WGmhWht5qFtRN
84+
gllTa/SbG8+iGaSPIVFCyvg1IzxsFnBGn+05Gu+KjpL4i0l1RqDmy5ItxKGP77in
85+
RPEUkejiUozg/X3v2TWAGagIVF5+EQ2Cswot9W1faAvyu/QmSGLLfSH22GdEDHXa
86+
U4DV5ArJ2U2eNkOuasSWGKBopa/Wh1SZjKrNsy5Gw84ihAI4k7ARoP+vu1dIPdaX
87+
ElipmGMtUWu0Azn2l9QJZpMCAwEAAaNCMEAwHQYDVR0OBBYEFL798jEmX2+hw70t
88+
SmfJA78PZnnHMB8GA1UdIwQYMBaAFJfNoXmIn5S6W7Lcj5G/huW5q1YQMA0GCSqG
89+
SIb3DQEBCwUAA4IBAQBY1NXTuQJZvjip33dRXyWP6GsSDKbXTSCcSF38P4/m+pcH
90+
r/q/upo+K+8eTtPqUwBsIywH5bypWqoIPtM+rkd3FVBe7uti2FExufpcOruzEGsY
91+
rNTfiFZbc7eHmFRTkKXWW4j6b6ElygrBvV999BhCRNf6NS0/syjqsbALHkFGeIcl
92+
78wdaR+m2XVJBV7SmPmZ/EQzxvhCZONNVyU5zvW2sehI7sRbZt9/FG5U1Ng0LarW
93+
R0gnXX/IZFnLhLh6UpLOBB0KIGENh75EEU7755jMKDKFj16D0uA1Lzrh5YxicTMy
94+
ydFYQLpLycsWl2oV3JB4pO5TIzjY9awkRE0MeMMc
95+
-----END CERTIFICATE-----
96+
`
97+
)
98+
4899
func newTestFFDX(t *testing.T, manifestEnabled bool) (h *FFDX, toServer, fromServer chan string, httpURL string, done func()) {
49100
mockedClient := &http.Client{}
50101
httpmock.ActivateNonDefault(mockedClient)
@@ -64,8 +115,9 @@ func newTestFFDX(t *testing.T, manifestEnabled bool) (h *FFDX, toServer, fromSer
64115
h = &FFDX{initialized: true}
65116
h.InitConfig(utConfig)
66117

118+
mmm := metricsmocks.NewManager(t)
67119
dxCtx, dxCancel := context.WithCancel(context.Background())
68-
err := h.Init(dxCtx, dxCancel, utConfig)
120+
err := h.Init(dxCtx, dxCancel, utConfig, mmm)
69121
assert.NoError(t, err)
70122
assert.Equal(t, "ffdx", h.Name())
71123
assert.NotNil(t, h.Capabilities())
@@ -114,7 +166,7 @@ func TestInitBadURL(t *testing.T) {
114166
h.InitConfig(utConfig)
115167
utConfig.Set(ffresty.HTTPConfigURL, "::::////")
116168
ctx, cancel := context.WithCancel(context.Background())
117-
err := h.Init(ctx, cancel, utConfig)
169+
err := h.Init(ctx, cancel, utConfig, nil)
118170
assert.Regexp(t, "FF00149", err)
119171
}
120172

@@ -127,7 +179,7 @@ func TestInitBadTLS(t *testing.T) {
127179
tlsConfig.Set(fftls.HTTPConfTLSEnabled, true)
128180
tlsConfig.Set(fftls.HTTPConfTLSCAFile, "badCA")
129181
ctx, cancel := context.WithCancel(context.Background())
130-
err := h.Init(ctx, cancel, utConfig)
182+
err := h.Init(ctx, cancel, utConfig, nil)
131183
assert.Regexp(t, "FF00153", err)
132184
}
133185

@@ -136,7 +188,7 @@ func TestInitMissingURL(t *testing.T) {
136188
h := &FFDX{}
137189
h.InitConfig(utConfig)
138190
ctx, cancel := context.WithCancel(context.Background())
139-
err := h.Init(ctx, cancel, utConfig)
191+
err := h.Init(ctx, cancel, utConfig, nil)
140192
assert.Regexp(t, "FF10138", err)
141193
}
142194

@@ -159,7 +211,7 @@ func TestInitWithBackgroundStart(t *testing.T) {
159211

160212
h.InitConfig(utConfig)
161213
ctx, cancel := context.WithCancel(context.Background())
162-
err := h.Init(ctx, cancel, utConfig)
214+
err := h.Init(ctx, cancel, utConfig, nil)
163215
assert.NoError(t, err)
164216

165217
assert.NotNil(t, h.backgroundRetry)
@@ -453,7 +505,7 @@ func TestBackgroundStartWSFail(t *testing.T) {
453505

454506
dxCtx, dxCancel := context.WithCancel(context.Background())
455507
defer dxCancel()
456-
err := h.Init(dxCtx, dxCancel, utConfig)
508+
err := h.Init(dxCtx, dxCancel, utConfig, nil)
457509
assert.NoError(t, err)
458510
assert.Equal(t, "ffdx", h.Name())
459511
assert.NotNil(t, h.Capabilities())
@@ -480,7 +532,7 @@ func TestMessageEventsBackgroundStart(t *testing.T) {
480532
// Starting in background mode and making sure the event loop are started as well
481533
// to listen to messages
482534
utConfig.Set(DataExchangeBackgroundStart, true)
483-
h.Init(h.ctx, h.cancelCtx, utConfig)
535+
h.Init(h.ctx, h.cancelCtx, utConfig, nil)
484536

485537
mcb := &dataexchangemocks.Callbacks{}
486538
h.SetHandler("ns1", "node1", mcb)
@@ -811,7 +863,7 @@ func TestWebsocketWithReinit(t *testing.T) {
811863

812864
h.InitConfig(utConfig)
813865
ctx, cancel := context.WithCancel(context.Background())
814-
err := h.Init(ctx, cancel, utConfig)
866+
err := h.Init(ctx, cancel, utConfig, nil)
815867
assert.NoError(t, err)
816868
h.AddNode(context.Background(), "ns1", "node1", fftypes.JSONObject{})
817869

@@ -859,7 +911,7 @@ func TestWebsocketWithEmptyNodesInit(t *testing.T) {
859911

860912
h.InitConfig(utConfig)
861913
ctx, cancel := context.WithCancel(context.Background())
862-
err := h.Init(ctx, cancel, utConfig)
914+
err := h.Init(ctx, cancel, utConfig, nil)
863915
assert.NoError(t, err)
864916

865917
err = h.Start()
@@ -909,3 +961,14 @@ func TestDeleteBlobFail(t *testing.T) {
909961
err := h.DeleteBlob(context.Background(), fmt.Sprintf("ns1/%s", u))
910962
assert.Regexp(t, "FF10229", err)
911963
}
964+
965+
//
966+
//matchingProfile := fftypes.JSONAnyPtr(fmt.Sprintf(`{"cert": "%s" }`, strings.ReplaceAll(testCertBundle, "\n", `\n`))).JSONObject()
967+
//
968+
//nm.identity.(*identitymanagermocks.Manager).On("GetLocalNode", ctx).Return(&core.Identity{
969+
//IdentityProfile: core.IdentityProfile{
970+
//Profile: matchingProfile,
971+
//},
972+
//}, nil)
973+
//
974+
//expiry := time.Unix(1835379057, 0).UTC()

internal/events/websockets/websockets_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,4 +1219,4 @@ func TestHandleStartWrongNamespace(t *testing.T) {
12191219
err := wc.handleStart(startMessage)
12201220
assert.Error(t, err)
12211221
assert.Regexp(t, "FF10462", err)
1222-
}
1222+
}

internal/namespace/configreload_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ func mockInitConfig(nmm *nmMocks) {
413413
nmm.mdi.On("Init", mock.Anything, mock.Anything).Return(nil)
414414
nmm.mdi.On("SetHandler", database.GlobalHandler, mock.Anything).Return()
415415
nmm.mbi.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
416-
nmm.mdx.On("Init", mock.Anything, mock.Anything, mock.Anything).Return(nil)
416+
nmm.mdx.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
417417
nmm.mps.On("Init", mock.Anything, mock.Anything).Return(nil)
418418
nmm.mti[1].On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
419419
nmm.mei[0].On("Init", mock.Anything, mock.Anything).Return(nil)

internal/namespace/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ func (nm *namespaceManager) initPlugins(pluginsToStart map[string]*plugin) (err
702702
return err
703703
}
704704
case pluginCategoryDataexchange:
705-
if err = p.dataexchange.Init(p.ctx, nm.cancelCtx /* allow plugin to stop whole process */, p.config); err != nil {
705+
if err = p.dataexchange.Init(p.ctx, nm.cancelCtx /* allow plugin to stop whole process */, p.config, nm.metrics); err != nil {
706706
return err
707707
}
708708
case pluginCategorySharedstorage:

internal/namespace/manager_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ func newTestNamespaceManager(t *testing.T, initConfig bool) (*namespaceManager,
273273
nmm.mdi.On("Init", mock.Anything, mock.Anything).Return(nil).Once()
274274
nmm.mdi.On("SetHandler", database.GlobalHandler, mock.Anything).Return().Once()
275275
nmm.mbi.On("Init", mock.Anything, mock.Anything, mock.Anything, nmm.mmi, mock.Anything).Return(nil).Once()
276-
nmm.mdx.On("Init", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
276+
nmm.mdx.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
277277
nmm.mps.On("Init", mock.Anything, mock.Anything).Return(nil).Once()
278278
nmm.mti[0].On("Init", mock.Anything, mock.Anything, "erc721", mock.Anything).Return(nil).Once()
279279
nmm.mti[1].On("Init", mock.Anything, mock.Anything, "erc1155", mock.Anything).Return(nil).Once()
@@ -363,7 +363,7 @@ func TestInitDataExchangeFail(t *testing.T) {
363363
nm, nmm, cleanup := newTestNamespaceManager(t, true)
364364
defer cleanup()
365365

366-
nmm.mdx.On("Init", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop"))
366+
nmm.mdx.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop"))
367367

368368
err := nm.initPlugins(map[string]*plugin{
369369
"ffdx": nm.plugins["ffdx"],

0 commit comments

Comments
 (0)