@axinom/mosaic-message-bus 0.32.0-rc.7 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/broker.js +5 -2
- package/dist/broker.js.map +1 -1
- package/dist/common/constants.d.ts +27 -0
- package/dist/common/constants.d.ts.map +1 -1
- package/dist/common/constants.js +28 -1
- package/dist/common/constants.js.map +1 -1
- package/dist/generated/key-service.d.ts +438 -0
- package/dist/generated/key-service.d.ts.map +1 -0
- package/dist/generated/key-service.js +162 -0
- package/dist/generated/key-service.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +1 -0
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/validate-signed-event-middleware.d.ts +36 -0
- package/dist/middleware/validate-signed-event-middleware.d.ts.map +1 -0
- package/dist/middleware/validate-signed-event-middleware.js +57 -0
- package/dist/middleware/validate-signed-event-middleware.js.map +1 -0
- package/dist/publication.d.ts.map +1 -1
- package/dist/publication.js +3 -2
- package/dist/publication.js.map +1 -1
- package/dist/rascal-config-builder.d.ts +9 -1
- package/dist/rascal-config-builder.d.ts.map +1 -1
- package/dist/rascal-config-builder.js +1 -0
- package/dist/rascal-config-builder.js.map +1 -1
- package/dist/signing/cache-public-signing-keys.d.ts +37 -0
- package/dist/signing/cache-public-signing-keys.d.ts.map +1 -0
- package/dist/signing/cache-public-signing-keys.js +81 -0
- package/dist/signing/cache-public-signing-keys.js.map +1 -0
- package/dist/signing/event-signing-errors.d.ts +30 -0
- package/dist/signing/event-signing-errors.d.ts.map +1 -0
- package/dist/signing/event-signing-errors.js +33 -0
- package/dist/signing/event-signing-errors.js.map +1 -0
- package/dist/signing/index.d.ts +4 -0
- package/dist/signing/index.d.ts.map +1 -0
- package/dist/signing/index.js +20 -0
- package/dist/signing/index.js.map +1 -0
- package/dist/signing/register-public-signing-key.d.ts +16 -0
- package/dist/signing/register-public-signing-key.d.ts.map +1 -0
- package/dist/signing/register-public-signing-key.js +44 -0
- package/dist/signing/register-public-signing-key.js.map +1 -0
- package/dist/signing/signing-cache.d.ts +25 -0
- package/dist/signing/signing-cache.d.ts.map +1 -0
- package/dist/signing/signing-cache.js +46 -0
- package/dist/signing/signing-cache.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/signing.d.ts +30 -0
- package/dist/types/signing.d.ts.map +1 -0
- package/dist/types/{signing-details.js → signing.js} +1 -1
- package/dist/types/signing.js.map +1 -0
- package/package.json +16 -5
- package/src/common/constants.ts +32 -0
- package/src/generated/key-service.ts +459 -0
- package/src/index.ts +1 -0
- package/src/middleware/index.ts +1 -0
- package/src/middleware/validate-signed-event-middleware.spec.ts +679 -0
- package/src/middleware/validate-signed-event-middleware.ts +136 -0
- package/src/publication.ts +9 -5
- package/src/rascal-config-builder.spec.ts +1 -33
- package/src/rascal-config-builder.ts +11 -1
- package/src/signing/cache-public-signing-keys.graphql +10 -0
- package/src/signing/cache-public-signing-keys.ts +115 -0
- package/src/signing/event-signing-errors.ts +35 -0
- package/src/signing/index.ts +3 -0
- package/src/signing/register-public-signing-key.graphql +10 -0
- package/src/signing/register-public-signing-key.spec.ts +95 -0
- package/src/signing/register-public-signing-key.ts +59 -0
- package/src/signing/signing-cache.ts +49 -0
- package/src/tests/utils/create-builder.ts +34 -0
- package/src/tests/utils/index.ts +1 -0
- package/src/types/index.ts +1 -1
- package/src/types/signing.ts +50 -0
- package/dist/types/signing-details.d.ts +0 -3
- package/dist/types/signing-details.d.ts.map +0 -1
- package/dist/types/signing-details.js.map +0 -1
- package/src/types/signing-details.ts +0 -8
|
@@ -0,0 +1,679 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { generateSignature, rejectionOf } from '@axinom/mosaic-service-common';
|
|
3
|
+
import { stub } from 'jest-auto-stub';
|
|
4
|
+
import 'jest-extended';
|
|
5
|
+
import {
|
|
6
|
+
MOSAIC_SIGNING_SIGNATURE,
|
|
7
|
+
MOSAIC_SIGNING_SIGNATURE_KEY_VERSION,
|
|
8
|
+
} from '../common';
|
|
9
|
+
import * as keyService from '../generated/key-service';
|
|
10
|
+
import { EventSigningErrors, registerPublicSigningKey } from '../signing';
|
|
11
|
+
import {
|
|
12
|
+
exportedForTesting,
|
|
13
|
+
setCachedSigningPublicKeys,
|
|
14
|
+
} from '../signing/signing-cache';
|
|
15
|
+
import { createBuilder } from '../tests/utils';
|
|
16
|
+
import {
|
|
17
|
+
GetEventSigningTokenFunc,
|
|
18
|
+
MessageEnvelope,
|
|
19
|
+
MessageInfo,
|
|
20
|
+
} from '../types';
|
|
21
|
+
import { validateSignedEventMiddleware } from './validate-signed-event-middleware';
|
|
22
|
+
|
|
23
|
+
describe('validateSignedEventMiddleware', () => {
|
|
24
|
+
const keyServiceBaseUrl = 'http://localhost:12100/graphiql';
|
|
25
|
+
const managedServiceId = 'ax-test-service';
|
|
26
|
+
const customizableServiceId = 'test-service';
|
|
27
|
+
const validPrivateKey =
|
|
28
|
+
'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCvqGMSzGnmch+BBNd89xhJMwACFgUuTKDIJAcjhoiJMvV911az2cgGiaIixONqmCBAapGfsZ2bO1FJFpi4dLmWXp+ivqPlRs/lLoUo/3BFmiYT3nZR636ogw6Jy8WCT9gHw4AfI5xnx1lJioylHQExEfEuOmP4VLcU92IilvkOPXSVdxQ/QjyNq1umn2KoIUNBpjuHFIUTanlcko9igDT/2ctmJFfkskXlCw7HV4BnBPSqBLhDlKQafNhPj9Xn93h4sGh85TcPBk90GeZ/XQ3LJ5Omf1p7pBda/uSi5gg6FyZlrFYKjiWgmkB3gi/7MvsnCKMmpw1wsevRKVpGZpQ1AgMBAAECggEAJmv/l7oMo/Jsf60OcXAe6Mv2AX7NjU4HkR+ITDX+IXx7BBaZCWfmf7+VLmPAlq1FyLFGvxZ7sdussP73Usl9Wq3B3zgx41G04Z1mVQxig2bvU0NCwDJxluxrvqpKvnE2gKQ7nxQL/ws0tYhPsUIB47jX91OgUE4/aZ+e4JADVCCyV+mSRwsswliHUU1MauZ0UB0dQGIhHNYXql6qvayyrtFmqBHNCy8hMCCe8TWO9j4WV5x4txZJH1q49u6UlV0dXqOFZOmRM5TkwwxIsJtdr71RFM5bzsLYlVbh7046vsTP31yi0GWfQnpRlKmnLzpuykJltikF0YahoDZSFTODdQKBgQDY0MVEYN/uW6BbNQTzBP9f/3pbaw6amXKa4CeTbQbfPYYGdzmPGpS//DiXzmdxj6Rm+L/eyX1WzZ4+0Ww3Dyp/VIyHxRK83Yh+5YWaTLUSSwjTaiq2sgWhEvy2Wnc8pI0XIMXJpkyLO58gIIhUfCPDM4dWE7MoPs91+i6iYilNEwKBgQDPZ2dkh16vCD/MEXFUwb5yy0fMpx2EDydPUy1MoxFJH74yYQGWZLZZOSJ8p4e+e2xmqM6xTa1cvIFNOckNKL1+p6a5wtv+ageITY5bASJFfGM9tN3sk4Omg3Nl6JDnY8INVltkh/caoj4l1yjKv02LRB1P/iuYkpRqnBDEpqcqlwKBgA887QBXRqW77tM6MLTbvw8CJ5lRNt+KtVFJO77SxM7fxhGiQ3tZROcRVPDmYsLKc6WBCgsgYhy9qseDdHWSLUxxpsbMBPsdHsC8ZN1pUriMaXxiU8ovTNH7QaOXTBYJApmDhiMb+vk2IYLihnJZnzHS50oXbFoBwBbslGZ5O6ndAoGAOSHN3GZh0atfD5K6elOIZ8zRcXGTct5NwM8zykmdKFyDIxOPwWLqzDct5dKsVO9g1AKqNTMlj0cqAyDo3iQb1vjNt5wSx8ljW8upbC4qx6NVHxlkjJeyCztonWjsCaF0QgJI2K+PhRmuLvRO+1KpRLS1smRclAHEun1VLSaPI+8CgYBkQKP0kNuhuC2UfBf4gS6vsT7ldBwCOrsgzIo+sPfnL/hn7INOYqVafg5UqLGO3Runm1WNNfKNmrBJm1+DZci7EQoKrHN9E9FKfn71kk4xyrJ3DabMNtRF5IQkRKoRzbQhAOJiV0oWkWFbtt/8DY5sOV28VsGQTHdB9rpwyigRwg==';
|
|
29
|
+
const validPublicKey =
|
|
30
|
+
'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr6hjEsxp5nIfgQTXfPcYSTMAAhYFLkygyCQHI4aIiTL1fddWs9nIBomiIsTjapggQGqRn7GdmztRSRaYuHS5ll6for6j5UbP5S6FKP9wRZomE952Uet+qIMOicvFgk/YB8OAHyOcZ8dZSYqMpR0BMRHxLjpj+FS3FPdiIpb5Dj10lXcUP0I8jatbpp9iqCFDQaY7hxSFE2p5XJKPYoA0/9nLZiRX5LJF5QsOx1eAZwT0qgS4Q5SkGnzYT4/V5/d4eLBofOU3DwZPdBnmf10NyyeTpn9ae6QXWv7kouYIOhcmZaxWCo4loJpAd4Iv+zL7JwijJqcNcLHr0SlaRmaUNQIDAQAB';
|
|
31
|
+
|
|
32
|
+
const messageType = 'TestMessage';
|
|
33
|
+
const ackOrNack = jest.fn();
|
|
34
|
+
const next = jest.fn();
|
|
35
|
+
const handler = jest.fn();
|
|
36
|
+
const getTokenCallback: GetEventSigningTokenFunc = async () => ({
|
|
37
|
+
accessToken: 'SGVsbG8gVGhlcmUh',
|
|
38
|
+
expiresInSeconds: 86400,
|
|
39
|
+
tokenType: 'ManagedServiceAccount',
|
|
40
|
+
});
|
|
41
|
+
const getEnvelope = (messageType: string, stringifiedPayload?: string) =>
|
|
42
|
+
stub<MessageEnvelope>({
|
|
43
|
+
message_type: messageType,
|
|
44
|
+
payload: stringifiedPayload
|
|
45
|
+
? JSON.parse(stringifiedPayload)
|
|
46
|
+
: { test: 'test message' },
|
|
47
|
+
});
|
|
48
|
+
const getMessageInfo = (
|
|
49
|
+
messageType: string,
|
|
50
|
+
headers = {},
|
|
51
|
+
stringifiedPayload?: string,
|
|
52
|
+
routingKey?: string,
|
|
53
|
+
) =>
|
|
54
|
+
stub<MessageInfo>({
|
|
55
|
+
unparsedEnvelope: stringifiedPayload
|
|
56
|
+
? Buffer.from(stringifiedPayload)
|
|
57
|
+
: {},
|
|
58
|
+
envelope: getEnvelope(messageType, stringifiedPayload),
|
|
59
|
+
fields: { routingKey },
|
|
60
|
+
properties: { headers },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
let keyServiceSpy: jest.SpyInstance;
|
|
64
|
+
let getRegisteredPublicKeys = () => ({});
|
|
65
|
+
let getRegistrationResponse = () => ({});
|
|
66
|
+
|
|
67
|
+
beforeAll(() => {
|
|
68
|
+
keyServiceSpy = jest.spyOn(keyService, 'getSdk').mockImplementation(() =>
|
|
69
|
+
stub<keyService.Sdk>({
|
|
70
|
+
GetPublicSigningKeys: () => ({ data: getRegisteredPublicKeys() }),
|
|
71
|
+
RegisterPublicSigningKey: () => ({ data: getRegistrationResponse() }),
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
afterEach(() => {
|
|
77
|
+
jest.clearAllMocks();
|
|
78
|
+
getRegisteredPublicKeys = () => ({});
|
|
79
|
+
getRegistrationResponse = () => ({});
|
|
80
|
+
exportedForTesting.clearSigningCache();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('event with empty builders -> unexpected message error thrown', async () => {
|
|
84
|
+
// Arrange
|
|
85
|
+
const builders = [];
|
|
86
|
+
const message = getMessageInfo(messageType);
|
|
87
|
+
|
|
88
|
+
// Act
|
|
89
|
+
const middleware = validateSignedEventMiddleware({
|
|
90
|
+
builders,
|
|
91
|
+
keyServiceBaseUrl,
|
|
92
|
+
getTokenCallback,
|
|
93
|
+
});
|
|
94
|
+
const error = await rejectionOf(
|
|
95
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// Assert
|
|
99
|
+
expect(error).toMatchObject(EventSigningErrors.UnexpectedMessageType);
|
|
100
|
+
expect(next).not.toHaveBeenCalled();
|
|
101
|
+
expect(keyServiceSpy).not.toHaveBeenCalled();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('event with not matching messageType -> unexpected message error thrown', async () => {
|
|
105
|
+
// Arrange
|
|
106
|
+
const builders = [createBuilder().subscribeForEvent(handler)];
|
|
107
|
+
const message = getMessageInfo(messageType);
|
|
108
|
+
|
|
109
|
+
// Act
|
|
110
|
+
const middleware = validateSignedEventMiddleware({
|
|
111
|
+
builders,
|
|
112
|
+
keyServiceBaseUrl,
|
|
113
|
+
getTokenCallback,
|
|
114
|
+
});
|
|
115
|
+
const error = await rejectionOf(
|
|
116
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Assert
|
|
120
|
+
expect(error).toMatchObject(EventSigningErrors.UnexpectedMessageType);
|
|
121
|
+
expect(next).not.toHaveBeenCalled();
|
|
122
|
+
expect(keyServiceSpy).not.toHaveBeenCalled();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('event with matching messageType, but no serviceId -> service ID not found error thrown', async () => {
|
|
126
|
+
// Arrange
|
|
127
|
+
const builders = [
|
|
128
|
+
createBuilder({ messageType }).subscribeForEvent(handler),
|
|
129
|
+
];
|
|
130
|
+
const message = getMessageInfo(messageType);
|
|
131
|
+
|
|
132
|
+
// Act
|
|
133
|
+
const middleware = validateSignedEventMiddleware({
|
|
134
|
+
builders,
|
|
135
|
+
keyServiceBaseUrl,
|
|
136
|
+
getTokenCallback,
|
|
137
|
+
});
|
|
138
|
+
const error = await rejectionOf(
|
|
139
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// Assert
|
|
143
|
+
expect(error).toMatchObject(EventSigningErrors.ServiceIdNotFound);
|
|
144
|
+
expect(next).not.toHaveBeenCalled();
|
|
145
|
+
expect(keyServiceSpy).not.toHaveBeenCalled();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('event with matching messageType, routing key serviceId, but no headers -> headers missing error thrown, fallback serviceId used', async () => {
|
|
149
|
+
// Arrange
|
|
150
|
+
const builders = [
|
|
151
|
+
createBuilder({ messageType }).subscribeForEvent(handler),
|
|
152
|
+
];
|
|
153
|
+
const message = getMessageInfo(
|
|
154
|
+
messageType,
|
|
155
|
+
{},
|
|
156
|
+
undefined,
|
|
157
|
+
`${managedServiceId}.test.event`,
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Act
|
|
161
|
+
const middleware = validateSignedEventMiddleware({
|
|
162
|
+
builders,
|
|
163
|
+
keyServiceBaseUrl,
|
|
164
|
+
getTokenCallback,
|
|
165
|
+
});
|
|
166
|
+
const error = await rejectionOf(
|
|
167
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
// Assert
|
|
171
|
+
expect(error).toMatchObject(EventSigningErrors.SigningHeadersMissing);
|
|
172
|
+
expect(next).not.toHaveBeenCalled();
|
|
173
|
+
expect(keyServiceSpy).not.toHaveBeenCalled();
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('event with matching messageType, builder serviceId, but no headers -> headers missing error thrown, builder info serviceId used', async () => {
|
|
177
|
+
// Arrange
|
|
178
|
+
const builders = [
|
|
179
|
+
createBuilder({
|
|
180
|
+
messageType,
|
|
181
|
+
serviceId: managedServiceId,
|
|
182
|
+
}).subscribeForEvent(handler),
|
|
183
|
+
];
|
|
184
|
+
const message = getMessageInfo(messageType);
|
|
185
|
+
|
|
186
|
+
// Act
|
|
187
|
+
const middleware = validateSignedEventMiddleware({
|
|
188
|
+
builders,
|
|
189
|
+
keyServiceBaseUrl,
|
|
190
|
+
getTokenCallback,
|
|
191
|
+
});
|
|
192
|
+
const error = await rejectionOf(
|
|
193
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Assert
|
|
197
|
+
expect(error).toMatchObject(EventSigningErrors.SigningHeadersMissing);
|
|
198
|
+
expect(next).not.toHaveBeenCalled();
|
|
199
|
+
expect(keyServiceSpy).not.toHaveBeenCalled();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('event with matching messageType, builder serviceId, existing headers, but no registered keys -> key not found error thrown', async () => {
|
|
203
|
+
// Arrange
|
|
204
|
+
const builders = [
|
|
205
|
+
createBuilder({
|
|
206
|
+
messageType,
|
|
207
|
+
serviceId: managedServiceId,
|
|
208
|
+
}).subscribeForEvent(handler),
|
|
209
|
+
];
|
|
210
|
+
const message = getMessageInfo(messageType, {
|
|
211
|
+
[MOSAIC_SIGNING_SIGNATURE]: 'test',
|
|
212
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Act
|
|
216
|
+
const middleware = validateSignedEventMiddleware({
|
|
217
|
+
builders,
|
|
218
|
+
keyServiceBaseUrl,
|
|
219
|
+
getTokenCallback,
|
|
220
|
+
});
|
|
221
|
+
const error = await rejectionOf(
|
|
222
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
// Assert
|
|
226
|
+
expect(error).toMatchObject({
|
|
227
|
+
message:
|
|
228
|
+
"Unable to find the public signing key for service with ID 'ax-test-service' and version 1. Please contact Axinom Support.",
|
|
229
|
+
code: EventSigningErrors.SigningPublicKeyNotFound.code,
|
|
230
|
+
});
|
|
231
|
+
expect(next).not.toHaveBeenCalled();
|
|
232
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(1);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('event with matching messageType, builder serviceId, existing headers, but other registered keys -> key not found error thrown', async () => {
|
|
236
|
+
// Arrange
|
|
237
|
+
const builders = [
|
|
238
|
+
createBuilder({
|
|
239
|
+
messageType,
|
|
240
|
+
serviceId: managedServiceId,
|
|
241
|
+
}).subscribeForEvent(handler),
|
|
242
|
+
];
|
|
243
|
+
const message = getMessageInfo(messageType, {
|
|
244
|
+
[MOSAIC_SIGNING_SIGNATURE]: 'test',
|
|
245
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
246
|
+
});
|
|
247
|
+
getRegisteredPublicKeys = () => ({
|
|
248
|
+
publicKeys: {
|
|
249
|
+
nodes: [
|
|
250
|
+
{
|
|
251
|
+
version: 1,
|
|
252
|
+
key: 'R2VuZXJhbCBLZW5vYmkh',
|
|
253
|
+
serviceId: 'ax-other-service',
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// Act
|
|
260
|
+
const middleware = validateSignedEventMiddleware({
|
|
261
|
+
builders,
|
|
262
|
+
keyServiceBaseUrl,
|
|
263
|
+
getTokenCallback,
|
|
264
|
+
});
|
|
265
|
+
const error = await rejectionOf(
|
|
266
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// Assert
|
|
270
|
+
expect(error).toMatchObject({
|
|
271
|
+
message:
|
|
272
|
+
"Unable to find the public signing key for service with ID 'ax-test-service' and version 1. Please contact Axinom Support.",
|
|
273
|
+
code: EventSigningErrors.SigningPublicKeyNotFound.code,
|
|
274
|
+
});
|
|
275
|
+
expect(next).not.toHaveBeenCalled();
|
|
276
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(1);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('event with matching messageType, builder serviceId, existing headers, matching registered key, but invalid signing data -> signature validation error thrown', async () => {
|
|
280
|
+
// Arrange
|
|
281
|
+
const builders = [
|
|
282
|
+
createBuilder({
|
|
283
|
+
messageType,
|
|
284
|
+
serviceId: managedServiceId,
|
|
285
|
+
}).subscribeForEvent(handler),
|
|
286
|
+
];
|
|
287
|
+
const message = getMessageInfo(messageType, {
|
|
288
|
+
[MOSAIC_SIGNING_SIGNATURE]: 'test',
|
|
289
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
290
|
+
});
|
|
291
|
+
getRegisteredPublicKeys = () => ({
|
|
292
|
+
publicKeys: {
|
|
293
|
+
nodes: [
|
|
294
|
+
{
|
|
295
|
+
version: 1,
|
|
296
|
+
key: 'R2VuZXJhbCBLZW5vYmkh',
|
|
297
|
+
serviceId: managedServiceId,
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Act
|
|
304
|
+
const middleware = validateSignedEventMiddleware({
|
|
305
|
+
builders,
|
|
306
|
+
keyServiceBaseUrl,
|
|
307
|
+
getTokenCallback,
|
|
308
|
+
});
|
|
309
|
+
const error = await rejectionOf(
|
|
310
|
+
middleware(message.envelope, message, ackOrNack, next),
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
// Assert
|
|
314
|
+
expect(error).toMatchObject(EventSigningErrors.SignatureValidationFailed);
|
|
315
|
+
expect(next).not.toHaveBeenCalled();
|
|
316
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(1);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('valid signed event -> no errors, validation passed', async () => {
|
|
320
|
+
// Arrange
|
|
321
|
+
const builders = [
|
|
322
|
+
createBuilder({
|
|
323
|
+
messageType,
|
|
324
|
+
serviceId: managedServiceId,
|
|
325
|
+
}).subscribeForEvent(handler),
|
|
326
|
+
];
|
|
327
|
+
const data = { test: 'test message' };
|
|
328
|
+
const { signature, stringifiedValue } = generateSignature(
|
|
329
|
+
data,
|
|
330
|
+
validPrivateKey,
|
|
331
|
+
);
|
|
332
|
+
const message = getMessageInfo(
|
|
333
|
+
messageType,
|
|
334
|
+
{
|
|
335
|
+
[MOSAIC_SIGNING_SIGNATURE]: signature,
|
|
336
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
337
|
+
},
|
|
338
|
+
stringifiedValue,
|
|
339
|
+
);
|
|
340
|
+
getRegisteredPublicKeys = () => ({
|
|
341
|
+
publicKeys: {
|
|
342
|
+
nodes: [
|
|
343
|
+
{
|
|
344
|
+
version: 1,
|
|
345
|
+
key: validPublicKey,
|
|
346
|
+
serviceId: managedServiceId,
|
|
347
|
+
},
|
|
348
|
+
],
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// Act
|
|
353
|
+
const middleware = validateSignedEventMiddleware({
|
|
354
|
+
builders,
|
|
355
|
+
keyServiceBaseUrl,
|
|
356
|
+
getTokenCallback,
|
|
357
|
+
});
|
|
358
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
359
|
+
|
|
360
|
+
// Assert
|
|
361
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
362
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(1);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('command -> no errors, validation skipped', async () => {
|
|
366
|
+
// Arrange
|
|
367
|
+
const builders = [
|
|
368
|
+
createBuilder({
|
|
369
|
+
messageType,
|
|
370
|
+
action: 'command',
|
|
371
|
+
serviceId: managedServiceId,
|
|
372
|
+
}).subscribeForEvent(handler),
|
|
373
|
+
];
|
|
374
|
+
const message = getMessageInfo(messageType, {});
|
|
375
|
+
getRegisteredPublicKeys = () => ({
|
|
376
|
+
publicKeys: {
|
|
377
|
+
nodes: [
|
|
378
|
+
{
|
|
379
|
+
version: 1,
|
|
380
|
+
key: validPublicKey,
|
|
381
|
+
serviceId: managedServiceId,
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// Act
|
|
388
|
+
const middleware = validateSignedEventMiddleware({
|
|
389
|
+
builders,
|
|
390
|
+
keyServiceBaseUrl,
|
|
391
|
+
getTokenCallback,
|
|
392
|
+
});
|
|
393
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
394
|
+
|
|
395
|
+
// Assert
|
|
396
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
397
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(0);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('valid signed event with own key cached during regitration -> no errors, validation passed', async () => {
|
|
401
|
+
// Arrange
|
|
402
|
+
const builders = [
|
|
403
|
+
createBuilder({
|
|
404
|
+
messageType,
|
|
405
|
+
serviceId: managedServiceId,
|
|
406
|
+
}).subscribeForEvent(handler),
|
|
407
|
+
];
|
|
408
|
+
const data = { test: 'test message' };
|
|
409
|
+
const { signature, stringifiedValue } = generateSignature(
|
|
410
|
+
data,
|
|
411
|
+
validPrivateKey,
|
|
412
|
+
);
|
|
413
|
+
const message = getMessageInfo(
|
|
414
|
+
messageType,
|
|
415
|
+
{
|
|
416
|
+
[MOSAIC_SIGNING_SIGNATURE]: signature,
|
|
417
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
418
|
+
},
|
|
419
|
+
stringifiedValue,
|
|
420
|
+
);
|
|
421
|
+
getRegisteredPublicKeys = () => ({
|
|
422
|
+
publicKeys: {
|
|
423
|
+
nodes: [],
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
const config = {
|
|
427
|
+
rmqEventSigningKeyVersion: 1,
|
|
428
|
+
serviceId: managedServiceId,
|
|
429
|
+
rmqEventSigningPublicKey: validPublicKey,
|
|
430
|
+
rmqEventSigningKeyVersionsToRevoke: [],
|
|
431
|
+
};
|
|
432
|
+
getRegistrationResponse = () => ({
|
|
433
|
+
registerPublicKey: {
|
|
434
|
+
publicKey: {
|
|
435
|
+
version: config.rmqEventSigningKeyVersion,
|
|
436
|
+
serviceId: config.serviceId,
|
|
437
|
+
key: config.rmqEventSigningPublicKey,
|
|
438
|
+
isActive: true,
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// Act
|
|
444
|
+
await registerPublicSigningKey(config, keyServiceBaseUrl, getTokenCallback);
|
|
445
|
+
const middleware = validateSignedEventMiddleware({
|
|
446
|
+
builders,
|
|
447
|
+
keyServiceBaseUrl,
|
|
448
|
+
getTokenCallback,
|
|
449
|
+
});
|
|
450
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
451
|
+
|
|
452
|
+
// Assert
|
|
453
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
454
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(1);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it('valid signed event with extraTrustedPublicKeys instead of key service keys -> no errors, validation passed', async () => {
|
|
458
|
+
// Arrange
|
|
459
|
+
const builders = [
|
|
460
|
+
createBuilder({
|
|
461
|
+
messageType,
|
|
462
|
+
serviceId: managedServiceId,
|
|
463
|
+
}).subscribeForEvent(handler),
|
|
464
|
+
];
|
|
465
|
+
const data = { test: 'test message' };
|
|
466
|
+
const { signature, stringifiedValue } = generateSignature(
|
|
467
|
+
data,
|
|
468
|
+
validPrivateKey,
|
|
469
|
+
);
|
|
470
|
+
const message = getMessageInfo(
|
|
471
|
+
messageType,
|
|
472
|
+
{
|
|
473
|
+
[MOSAIC_SIGNING_SIGNATURE]: signature,
|
|
474
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
475
|
+
},
|
|
476
|
+
stringifiedValue,
|
|
477
|
+
);
|
|
478
|
+
getRegisteredPublicKeys = () => ({
|
|
479
|
+
publicKeys: {
|
|
480
|
+
nodes: [],
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// Act
|
|
485
|
+
const middleware = validateSignedEventMiddleware({
|
|
486
|
+
builders,
|
|
487
|
+
keyServiceBaseUrl,
|
|
488
|
+
getTokenCallback,
|
|
489
|
+
extraTrustedPublicKeys: [
|
|
490
|
+
{
|
|
491
|
+
key: validPublicKey,
|
|
492
|
+
serviceId: managedServiceId,
|
|
493
|
+
version: 1,
|
|
494
|
+
isActive: true,
|
|
495
|
+
},
|
|
496
|
+
],
|
|
497
|
+
});
|
|
498
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
499
|
+
|
|
500
|
+
// Assert
|
|
501
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
502
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(0);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it('valid signed customizable service event -> no errors, validation passed', async () => {
|
|
506
|
+
// Arrange
|
|
507
|
+
const builders = [
|
|
508
|
+
createBuilder({
|
|
509
|
+
messageType,
|
|
510
|
+
serviceId: customizableServiceId,
|
|
511
|
+
}).subscribeForEvent(handler),
|
|
512
|
+
];
|
|
513
|
+
const data = { test: 'test message' };
|
|
514
|
+
const { signature, stringifiedValue } = generateSignature(
|
|
515
|
+
data,
|
|
516
|
+
validPrivateKey,
|
|
517
|
+
);
|
|
518
|
+
const message = getMessageInfo(
|
|
519
|
+
messageType,
|
|
520
|
+
{
|
|
521
|
+
[MOSAIC_SIGNING_SIGNATURE]: signature,
|
|
522
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
523
|
+
},
|
|
524
|
+
stringifiedValue,
|
|
525
|
+
);
|
|
526
|
+
getRegisteredPublicKeys = () => ({
|
|
527
|
+
publicKeys: {
|
|
528
|
+
nodes: [],
|
|
529
|
+
},
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// Act
|
|
533
|
+
const middleware = validateSignedEventMiddleware({
|
|
534
|
+
builders,
|
|
535
|
+
keyServiceBaseUrl,
|
|
536
|
+
getTokenCallback,
|
|
537
|
+
extraTrustedPublicKeys: [
|
|
538
|
+
{
|
|
539
|
+
key: validPublicKey,
|
|
540
|
+
serviceId: customizableServiceId,
|
|
541
|
+
version: 1,
|
|
542
|
+
isActive: true,
|
|
543
|
+
},
|
|
544
|
+
],
|
|
545
|
+
});
|
|
546
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
547
|
+
|
|
548
|
+
// Assert
|
|
549
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
550
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(0);
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it('valid unsigned customizable service event -> no errors, validation skipped', async () => {
|
|
554
|
+
// Arrange
|
|
555
|
+
const builders = [
|
|
556
|
+
createBuilder({
|
|
557
|
+
messageType,
|
|
558
|
+
serviceId: customizableServiceId,
|
|
559
|
+
}).subscribeForEvent(handler),
|
|
560
|
+
];
|
|
561
|
+
const data = { test: 'test message' };
|
|
562
|
+
const { signature, stringifiedValue } = generateSignature(
|
|
563
|
+
data,
|
|
564
|
+
validPrivateKey,
|
|
565
|
+
);
|
|
566
|
+
const message = getMessageInfo(
|
|
567
|
+
messageType,
|
|
568
|
+
{
|
|
569
|
+
[MOSAIC_SIGNING_SIGNATURE]: signature,
|
|
570
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
571
|
+
},
|
|
572
|
+
stringifiedValue,
|
|
573
|
+
);
|
|
574
|
+
getRegisteredPublicKeys = () => ({
|
|
575
|
+
publicKeys: {
|
|
576
|
+
nodes: [],
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
// Act
|
|
581
|
+
const middleware = validateSignedEventMiddleware({
|
|
582
|
+
builders,
|
|
583
|
+
keyServiceBaseUrl,
|
|
584
|
+
getTokenCallback,
|
|
585
|
+
});
|
|
586
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
587
|
+
|
|
588
|
+
// Assert
|
|
589
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
590
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(0);
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
it('valid signed event with already cached key -> no errors, validation passed', async () => {
|
|
594
|
+
// Arrange
|
|
595
|
+
const builders = [
|
|
596
|
+
createBuilder({
|
|
597
|
+
messageType,
|
|
598
|
+
serviceId: managedServiceId,
|
|
599
|
+
}).subscribeForEvent(handler),
|
|
600
|
+
];
|
|
601
|
+
const data = { test: 'test message' };
|
|
602
|
+
const { signature, stringifiedValue } = generateSignature(
|
|
603
|
+
data,
|
|
604
|
+
validPrivateKey,
|
|
605
|
+
);
|
|
606
|
+
const message = getMessageInfo(
|
|
607
|
+
messageType,
|
|
608
|
+
{
|
|
609
|
+
[MOSAIC_SIGNING_SIGNATURE]: signature,
|
|
610
|
+
[MOSAIC_SIGNING_SIGNATURE_KEY_VERSION]: 1,
|
|
611
|
+
},
|
|
612
|
+
stringifiedValue,
|
|
613
|
+
);
|
|
614
|
+
getRegisteredPublicKeys = () => ({
|
|
615
|
+
publicKeys: {
|
|
616
|
+
nodes: [],
|
|
617
|
+
},
|
|
618
|
+
});
|
|
619
|
+
setCachedSigningPublicKeys(
|
|
620
|
+
[
|
|
621
|
+
{
|
|
622
|
+
version: 1,
|
|
623
|
+
key: validPublicKey,
|
|
624
|
+
serviceId: managedServiceId,
|
|
625
|
+
isActive: true,
|
|
626
|
+
},
|
|
627
|
+
],
|
|
628
|
+
100000,
|
|
629
|
+
);
|
|
630
|
+
|
|
631
|
+
// Act
|
|
632
|
+
const middleware = validateSignedEventMiddleware({
|
|
633
|
+
builders,
|
|
634
|
+
keyServiceBaseUrl,
|
|
635
|
+
getTokenCallback,
|
|
636
|
+
});
|
|
637
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
638
|
+
|
|
639
|
+
// Assert
|
|
640
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
641
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(0);
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
it('valid unsigned customizable event with managed extraTrustedPublicKeys event -> no errors, validation skipped', async () => {
|
|
645
|
+
// Arrange
|
|
646
|
+
const builders = [
|
|
647
|
+
createBuilder({
|
|
648
|
+
messageType,
|
|
649
|
+
serviceId: customizableServiceId,
|
|
650
|
+
}).subscribeForEvent(handler),
|
|
651
|
+
];
|
|
652
|
+
const message = getMessageInfo(messageType, {});
|
|
653
|
+
getRegisteredPublicKeys = () => ({
|
|
654
|
+
publicKeys: {
|
|
655
|
+
nodes: [{}],
|
|
656
|
+
},
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
// Act
|
|
660
|
+
const middleware = validateSignedEventMiddleware({
|
|
661
|
+
builders,
|
|
662
|
+
keyServiceBaseUrl,
|
|
663
|
+
getTokenCallback,
|
|
664
|
+
extraTrustedPublicKeys: [
|
|
665
|
+
{
|
|
666
|
+
key: validPublicKey,
|
|
667
|
+
serviceId: managedServiceId,
|
|
668
|
+
version: 1,
|
|
669
|
+
isActive: true,
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
});
|
|
673
|
+
await middleware(message.envelope, message, ackOrNack, next);
|
|
674
|
+
|
|
675
|
+
// Assert
|
|
676
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
677
|
+
expect(keyServiceSpy).toHaveBeenCalledTimes(0);
|
|
678
|
+
});
|
|
679
|
+
});
|