@virtru/dsp-sdk 0.4.1 → 0.6.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/README.md +81 -3
  3. package/dist/src/fips.d.ts +7 -0
  4. package/dist/src/fips.js +12 -0
  5. package/dist/src/lib/dsp.d.ts +17 -1
  6. package/dist/src/lib/dsp.js +28 -5
  7. package/dist/src/lib/fips-crypto/asymmetric.d.ts +35 -0
  8. package/dist/src/lib/fips-crypto/asymmetric.js +116 -0
  9. package/dist/src/lib/fips-crypto/key-format.d.ts +51 -0
  10. package/dist/src/lib/fips-crypto/key-format.js +233 -0
  11. package/dist/src/lib/fips-crypto/keys.d.ts +26 -0
  12. package/dist/src/lib/fips-crypto/keys.js +123 -0
  13. package/dist/src/lib/fips-crypto/primitives.d.ts +41 -0
  14. package/dist/src/lib/fips-crypto/primitives.js +105 -0
  15. package/dist/src/lib/fips-crypto/symmetric.d.ts +61 -0
  16. package/dist/src/lib/fips-crypto/symmetric.js +152 -0
  17. package/dist/src/lib/fips-crypto-service.d.ts +5 -0
  18. package/dist/src/lib/fips-crypto-service.js +44 -0
  19. package/dist/src/lib/utils.d.ts +8 -2
  20. package/dist/src/lib/utils.js +8 -9
  21. package/package.json +31 -5
  22. package/.prettierrc +0 -3
  23. package/.rush/temp/chunked-rush-logs/dsp-sdk._phase_build.chunks.jsonl +0 -12
  24. package/.rush/temp/chunked-rush-logs/dsp-sdk._phase_test.chunks.jsonl +0 -43
  25. package/.rush/temp/package-deps__phase_build.json +0 -68
  26. package/.rush/temp/shrinkwrap-deps.json +0 -1257
  27. package/CHANGELOG.json +0 -278
  28. package/buf.gen.yaml +0 -17
  29. package/buf.yaml +0 -4
  30. package/config/jest.config.json +0 -6
  31. package/config/rig.json +0 -8
  32. package/dist/tests/dsp-client.test.d.ts +0 -1
  33. package/dist/tests/dsp-client.test.js +0 -73
  34. package/dist/tests/dsp.test.d.ts +0 -1
  35. package/dist/tests/dsp.test.js +0 -92
  36. package/dist/tests/mocks/create-export-artifacts.d.ts +0 -2
  37. package/dist/tests/mocks/create-export-artifacts.js +0 -13
  38. package/dist/tests/mocks/tagging-pdp-tag.d.ts +0 -2
  39. package/dist/tests/mocks/tagging-pdp-tag.js +0 -11
  40. package/dist/tests/mocks/well-known-configuration.d.ts +0 -2
  41. package/dist/tests/mocks/well-known-configuration.js +0 -12
  42. package/dist/tests/setup-msw.d.ts +0 -9
  43. package/dist/tests/setup-msw.js +0 -30
  44. package/eslint.config.mjs +0 -28
  45. package/lib-commonjs/src/gen/buf/validate/validate_pb.js +0 -487
  46. package/lib-commonjs/src/gen/config/v1/config_pb.js +0 -142
  47. package/lib-commonjs/src/gen/config/v1/kas_config_pb.js +0 -72
  48. package/lib-commonjs/src/gen/config/v1/meta_pb.js +0 -36
  49. package/lib-commonjs/src/gen/config/v1/outlook_config_pb.js +0 -67
  50. package/lib-commonjs/src/gen/config/v1/secureviewer_config_pb.js +0 -67
  51. package/lib-commonjs/src/gen/config/v1/tagging_pb.js +0 -246
  52. package/lib-commonjs/src/gen/google/api/annotations_pb.js +0 -33
  53. package/lib-commonjs/src/gen/google/api/http_pb.js +0 -44
  54. package/lib-commonjs/src/gen/policyimportexport/v1/policy_import_export_pb.js +0 -93
  55. package/lib-commonjs/src/gen/shared/v1/shared_pb.js +0 -95
  56. package/lib-commonjs/src/gen/tagging/pdp/v2/tagging_pb.js +0 -277
  57. package/lib-commonjs/src/gen/version/v1/version_pb.js +0 -40
  58. package/lib-commonjs/src/gen/virtru/common/common_pb.js +0 -76
  59. package/lib-commonjs/src/gen/virtru/policy/certificates/v1/certificates_pb.js +0 -77
  60. package/lib-commonjs/src/gen/virtru/policy/objects_pb.js +0 -143
  61. package/lib-commonjs/src/index.js +0 -48
  62. package/lib-commonjs/src/lib/client.js +0 -66
  63. package/lib-commonjs/src/lib/consts.js +0 -10
  64. package/lib-commonjs/src/lib/dsp.js +0 -49
  65. package/lib-commonjs/src/lib/utils.js +0 -402
  66. package/lib-commonjs/tests/dsp-client.test.js +0 -75
  67. package/lib-commonjs/tests/dsp.test.js +0 -94
  68. package/lib-commonjs/tests/mocks/create-export-artifacts.js +0 -17
  69. package/lib-commonjs/tests/mocks/tagging-pdp-tag.js +0 -15
  70. package/lib-commonjs/tests/mocks/well-known-configuration.js +0 -16
  71. package/lib-commonjs/tests/setup-msw.js +0 -33
  72. package/src/gen/buf/validate/validate_pb.ts +0 -4879
  73. package/src/gen/config/formatters/testdata/v1/test_pb.ts +0 -287
  74. package/src/gen/config/v1/config_connect.ts +0 -111
  75. package/src/gen/config/v1/config_pb.ts +0 -439
  76. package/src/gen/config/v1/kas_config_pb.ts +0 -183
  77. package/src/gen/config/v1/meta_pb.ts +0 -72
  78. package/src/gen/config/v1/outlook_config_pb.ts +0 -242
  79. package/src/gen/config/v1/secureviewer_config_pb.ts +0 -161
  80. package/src/gen/config/v1/tagging_pb.ts +0 -456
  81. package/src/gen/google/api/annotations_pb.ts +0 -43
  82. package/src/gen/google/api/http_pb.ts +0 -486
  83. package/src/gen/helloworld/v1/helloworld_connect.ts +0 -49
  84. package/src/gen/helloworld/v1/helloworld_pb.ts +0 -104
  85. package/src/gen/kas/nanotdf/v1/nanotdf_rewrap_connect.ts +0 -39
  86. package/src/gen/kas/nanotdf/v1/nanotdf_rewrap_pb.ts +0 -207
  87. package/src/gen/policyimportexport/v1/policy_import_export_connect.ts +0 -56
  88. package/src/gen/policyimportexport/v1/policy_import_export_pb.ts +0 -332
  89. package/src/gen/shared/v1/shared_connect.ts +0 -61
  90. package/src/gen/shared/v1/shared_pb.ts +0 -240
  91. package/src/gen/shared/v2/shared_connect.ts +0 -39
  92. package/src/gen/shared/v2/shared_pb.ts +0 -122
  93. package/src/gen/tagging/pdp/v2/externalprocessors/processor_connect.ts +0 -156
  94. package/src/gen/tagging/pdp/v2/externalprocessors/processor_pb.ts +0 -709
  95. package/src/gen/tagging/pdp/v2/stanag/stanag_pb.ts +0 -953
  96. package/src/gen/tagging/pdp/v2/tagging_connect.ts +0 -73
  97. package/src/gen/tagging/pdp/v2/tagging_pb.ts +0 -1064
  98. package/src/gen/version/v1/version_connect.ts +0 -31
  99. package/src/gen/version/v1/version_pb.ts +0 -143
  100. package/src/gen/virtru/common/common_pb.ts +0 -201
  101. package/src/gen/virtru/policy/certificates/v1/certificates_connect.ts +0 -44
  102. package/src/gen/virtru/policy/certificates/v1/certificates_pb.ts +0 -305
  103. package/src/gen/virtru/policy/objects_pb.ts +0 -253
  104. package/src/gen/web-admin/v1/config_connect.ts +0 -52
  105. package/src/gen/web-admin/v1/config_pb.ts +0 -173
  106. package/src/index.ts +0 -62
  107. package/src/lib/client.ts +0 -90
  108. package/src/lib/consts.ts +0 -8
  109. package/src/lib/dsp.ts +0 -65
  110. package/src/lib/utils.test.ts +0 -412
  111. package/src/lib/utils.ts +0 -524
  112. package/src/vite-env.d.ts +0 -7
  113. package/temp/build/lint/_eslint-5eVG3S6w.json +0 -30
  114. package/temp/test/jest/haste-map-b055a9550e6d9f9b43d8ad29b1607278-49d19aee56a0732eca9c014a51272338-8710993d07b75a801b0956e67ffc46fa +0 -0
  115. package/tests/dsp-client.test.ts +0 -95
  116. package/tests/dsp.test.ts +0 -119
  117. package/tests/mocks/create-export-artifacts.ts +0 -16
  118. package/tests/mocks/tagging-pdp-tag.ts +0 -13
  119. package/tests/mocks/well-known-configuration.ts +0 -15
  120. package/tests/setup-msw.ts +0 -35
  121. package/tsconfig.json +0 -32
  122. package/update-protos.sh +0 -63
  123. package/vitest.config.ts +0 -32
@@ -1,412 +0,0 @@
1
- /*
2
- * Copyright (c) Virtru Corporation. All rights reserved.
3
- *
4
- * Your use of this file is governed by the Virtu Terms of Service <https://www.virtru.com/terms-of-service/>.
5
- */
6
-
7
- import { describe, it, expect, beforeEach, vi } from 'vitest';
8
-
9
- // Mock all @opentdf imports BEFORE importing utils
10
- vi.mock('@opentdf/sdk', () => ({
11
- AuthProviders: {
12
- refreshAuthProvider: vi.fn(),
13
- },
14
- OpenTDF: vi.fn(),
15
- PermissionDeniedError: class PermissionDeniedError extends Error {},
16
- }));
17
-
18
- vi.mock('@opentdf/sdk/platform', () => ({
19
- PlatformClient: vi.fn(),
20
- }));
21
-
22
- vi.mock('@opentdf/sdk/platform/policy/objects_pb.js', () => ({
23
- Certificate: class Certificate {
24
- pem?: string;
25
- constructor(data?: any) {
26
- if (data) Object.assign(this, data);
27
- }
28
- },
29
- }));
30
-
31
- vi.mock('@opentdf/sdk/platform/common/common_pb.js', () => ({
32
- ActiveStateEnum: {
33
- ACTIVE: 1,
34
- },
35
- }));
36
-
37
- // Polyfill atob if needed
38
- if (typeof (globalThis as any).atob === 'undefined') {
39
- (globalThis as any).atob = (b64: string) =>
40
- Buffer.from(b64, 'base64').toString('binary');
41
- }
42
-
43
- // Mock pkijs/asn1js with a way to control them
44
- const mockState = {
45
- asn1Mode: 'ok' as 'ok' | 'bad-der',
46
- verifyResult: { result: true } as { result: boolean; resultMessage?: string },
47
- };
48
-
49
- vi.mock('asn1js', () => ({
50
- fromBER: vi.fn((_: ArrayBuffer) => {
51
- if (mockState.asn1Mode === 'bad-der') return { offset: -1 };
52
- return {
53
- offset: 0,
54
- result: {
55
- subject: { typesAndValues: [] },
56
- issuer: { typesAndValues: [] },
57
- },
58
- };
59
- }),
60
- }));
61
-
62
- vi.mock('pkijs', () => {
63
- return {
64
- Certificate: class Certificate {
65
- public subject: any = { typesAndValues: [] };
66
- public issuer: any = { typesAndValues: [] };
67
- public subjectPublicKeyInfo: any = {};
68
- constructor(_: any) {}
69
- },
70
- CertificateChainValidationEngine: class CertificateChainValidationEngine {
71
- constructor(_: any) {}
72
- async verify() {
73
- return mockState.verifyResult;
74
- }
75
- },
76
- };
77
- });
78
-
79
- // Mock DSPClient
80
- vi.mock('./client', () => ({
81
- DSPClient: vi.fn(),
82
- }));
83
-
84
- // NOW import utils
85
- import { validateJWSCertificateChain, getTrustedCertificates } from './utils';
86
- import { DSPClient } from './client';
87
- import { PlatformClient } from '@opentdf/sdk/platform';
88
- import { AuthProviders } from '@opentdf/sdk';
89
-
90
- describe('validateJWSCertificateChain', () => {
91
- beforeEach(() => {
92
- mockState.asn1Mode = 'ok';
93
- mockState.verifyResult = { result: true };
94
- });
95
-
96
- it('throws error when x5c is empty', async () => {
97
- await expect(
98
- validateJWSCertificateChain([], [{ pem: '---' }] as any)
99
- ).rejects.toThrow(/No certificates provided in x5c array/);
100
- });
101
-
102
- it('throws error when too many certificates in x5c', async () => {
103
- const tooMany = new Array(11).fill('AQI=');
104
- await expect(
105
- validateJWSCertificateChain(tooMany, [{ pem: '---' }] as any)
106
- ).rejects.toThrow(/Too many certificates in x5c/);
107
- });
108
-
109
- it('throws error when no trusted roots provided', async () => {
110
- await expect(
111
- validateJWSCertificateChain(['AQI='], [] as any)
112
- ).rejects.toThrow(/No trusted root certificates provided/);
113
- });
114
-
115
- it('fails on invalid base64 in x5c', async () => {
116
- await expect(
117
- validateJWSCertificateChain(['***not-base64***'], [{ pem: '---' }] as any)
118
- ).rejects.toThrow(/Failed to parse certificate at x5c\[0]/);
119
- });
120
-
121
- it('fails on ASN.1 parse error', async () => {
122
- mockState.asn1Mode = 'bad-der';
123
- await expect(
124
- validateJWSCertificateChain(['AQI='], [{ pem: '---' }] as any)
125
- ).rejects.toThrow(/Invalid DER encoding/);
126
- });
127
-
128
- it('returns valid true on successful verification', async () => {
129
- const pem = '-----BEGIN CERTIFICATE-----\nAQI=\n-----END CERTIFICATE-----';
130
- mockState.verifyResult = { result: true };
131
- const res = await validateJWSCertificateChain(['AQI='], [{ pem }] as any);
132
- expect(res.valid).toBe(true);
133
- expect(res.validationResult.warnings).toEqual([]);
134
- });
135
-
136
- it('returns warnings when some trusted roots fail to parse', async () => {
137
- const pem = '-----BEGIN CERTIFICATE-----\nAQI=\n-----END CERTIFICATE-----';
138
- const res = await validateJWSCertificateChain(['AQI='], [
139
- { pem: '' },
140
- { pem },
141
- ] as any);
142
- expect(res.valid).toBe(true);
143
- expect(res.validationResult.warnings).toHaveLength(1);
144
- expect(res.validationResult.warnings[0]).toMatch(/has no PEM data/);
145
- });
146
- });
147
-
148
- describe('getTrustedCertificates', () => {
149
- const mockOptions = {
150
- oidc: {
151
- clientId: 'test-client-id',
152
- tokenEndpoint: 'https://auth.test.com/token',
153
- userInfoEndpoint: 'https://auth.test.com/userinfo',
154
- },
155
- platformEndpoint: 'https://platform.test.com',
156
- refreshToken: 'test-refresh-token',
157
- };
158
-
159
- let mockAuthProvider: any;
160
- let mockPlatformClient: any;
161
- let mockDSPClient: any;
162
- let mockCertificateService: any;
163
-
164
- beforeEach(() => {
165
- vi.clearAllMocks();
166
-
167
- // Mock crypto.subtle.generateKey for DPoP signing keys
168
- if (!globalThis.crypto) {
169
- (globalThis as any).crypto = {};
170
- }
171
- if (!globalThis.crypto.subtle) {
172
- (globalThis.crypto as any).subtle = {};
173
- }
174
- (globalThis.crypto.subtle as any).generateKey = vi.fn().mockResolvedValue({
175
- publicKey: {},
176
- privateKey: {},
177
- });
178
-
179
- // Mock auth provider
180
- mockAuthProvider = {
181
- updateClientPublicKey: vi.fn().mockResolvedValue(undefined),
182
- };
183
-
184
- (AuthProviders.refreshAuthProvider as any).mockResolvedValue(
185
- mockAuthProvider
186
- );
187
-
188
- // Mock certificate service
189
- mockCertificateService = {
190
- listCertificatesByNamespace: vi.fn(),
191
- };
192
-
193
- // Mock DSP client
194
- mockDSPClient = {
195
- v1: {
196
- certificateService: mockCertificateService,
197
- },
198
- };
199
-
200
- (DSPClient as any).mockImplementation(() => mockDSPClient);
201
-
202
- // Mock platform client
203
- mockPlatformClient = {
204
- v1: {
205
- namespace: {
206
- listNamespaces: vi.fn(),
207
- },
208
- },
209
- };
210
-
211
- (PlatformClient as any).mockImplementation(() => mockPlatformClient);
212
- });
213
-
214
- it('successfully retrieves certificates from a single namespace', async () => {
215
- const mockCertificate1 = { pem: 'cert1-pem-data' };
216
- const mockCertificate2 = { pem: 'cert2-pem-data' };
217
-
218
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
219
- namespaces: [{ id: 'namespace-1' }],
220
- });
221
-
222
- mockCertificateService.listCertificatesByNamespace.mockResolvedValue({
223
- certificates: [mockCertificate1, mockCertificate2],
224
- pagination: { nextOffset: 0 },
225
- });
226
-
227
- const result = await getTrustedCertificates(mockOptions);
228
-
229
- expect(result).toHaveLength(2);
230
- expect(result).toEqual([mockCertificate1, mockCertificate2]);
231
- expect(
232
- mockCertificateService.listCertificatesByNamespace
233
- ).toHaveBeenCalledWith({
234
- namespaceId: 'namespace-1',
235
- pagination: { limit: 100, offset: 0 },
236
- });
237
- });
238
-
239
- it('successfully retrieves certificates from multiple namespaces', async () => {
240
- const mockCert1 = { pem: 'cert1-pem' };
241
- const mockCert2 = { pem: 'cert2-pem' };
242
- const mockCert3 = { pem: 'cert3-pem' };
243
-
244
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
245
- namespaces: [{ id: 'namespace-1' }, { id: 'namespace-2' }],
246
- });
247
-
248
- mockCertificateService.listCertificatesByNamespace
249
- .mockResolvedValueOnce({
250
- certificates: [mockCert1, mockCert2],
251
- pagination: { nextOffset: 0 },
252
- })
253
- .mockResolvedValueOnce({
254
- certificates: [mockCert3],
255
- pagination: { nextOffset: 0 },
256
- });
257
-
258
- const result = await getTrustedCertificates(mockOptions);
259
-
260
- expect(result).toHaveLength(3);
261
- expect(result).toEqual([mockCert1, mockCert2, mockCert3]);
262
- expect(
263
- mockCertificateService.listCertificatesByNamespace
264
- ).toHaveBeenCalledTimes(2);
265
- });
266
-
267
- it('handles pagination correctly (multiple pages)', async () => {
268
- const mockCert1 = { pem: 'cert1' };
269
- const mockCert2 = { pem: 'cert2' };
270
- const mockCert3 = { pem: 'cert3' };
271
-
272
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
273
- namespaces: [{ id: 'namespace-1' }],
274
- });
275
-
276
- // First page
277
- mockCertificateService.listCertificatesByNamespace
278
- .mockResolvedValueOnce({
279
- certificates: [mockCert1, mockCert2],
280
- pagination: { nextOffset: 100 },
281
- })
282
- // Second page
283
- .mockResolvedValueOnce({
284
- certificates: [mockCert3],
285
- pagination: { nextOffset: 0 },
286
- });
287
-
288
- const result = await getTrustedCertificates(mockOptions);
289
-
290
- expect(result).toHaveLength(3);
291
- expect(result).toEqual([mockCert1, mockCert2, mockCert3]);
292
- expect(
293
- mockCertificateService.listCertificatesByNamespace
294
- ).toHaveBeenCalledTimes(2);
295
- expect(
296
- mockCertificateService.listCertificatesByNamespace
297
- ).toHaveBeenNthCalledWith(1, {
298
- namespaceId: 'namespace-1',
299
- pagination: { limit: 100, offset: 0 },
300
- });
301
- expect(
302
- mockCertificateService.listCertificatesByNamespace
303
- ).toHaveBeenNthCalledWith(2, {
304
- namespaceId: 'namespace-1',
305
- pagination: { limit: 100, offset: 100 },
306
- });
307
- });
308
-
309
- it('handles empty certificate list', async () => {
310
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
311
- namespaces: [{ id: 'namespace-1' }],
312
- });
313
-
314
- mockCertificateService.listCertificatesByNamespace.mockResolvedValue({
315
- certificates: [],
316
- pagination: { nextOffset: 0 },
317
- });
318
-
319
- const result = await getTrustedCertificates(mockOptions);
320
-
321
- expect(result).toHaveLength(0);
322
- expect(result).toEqual([]);
323
- });
324
-
325
- it('handles errors from certificate service', async () => {
326
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
327
- namespaces: [{ id: 'namespace-1' }],
328
- });
329
-
330
- mockCertificateService.listCertificatesByNamespace.mockRejectedValue(
331
- new Error('Certificate service error')
332
- );
333
-
334
- await expect(getTrustedCertificates(mockOptions)).rejects.toThrow(
335
- 'Certificate service error'
336
- );
337
- });
338
-
339
- it('handles errors from namespace listing', async () => {
340
- mockPlatformClient.v1.namespace.listNamespaces.mockRejectedValue(
341
- new Error('Namespace listing error')
342
- );
343
-
344
- await expect(getTrustedCertificates(mockOptions)).rejects.toThrow(
345
- 'Namespace listing error'
346
- );
347
- });
348
-
349
- it('initializes auth provider correctly', async () => {
350
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
351
- namespaces: [],
352
- });
353
-
354
- await getTrustedCertificates(mockOptions);
355
-
356
- expect(AuthProviders.refreshAuthProvider).toHaveBeenCalled();
357
- expect(mockAuthProvider.updateClientPublicKey).toHaveBeenCalled();
358
- expect(globalThis.crypto.subtle.generateKey).toHaveBeenCalledWith(
359
- {
360
- name: 'ECDSA',
361
- namedCurve: 'P-256',
362
- },
363
- true,
364
- ['sign', 'verify']
365
- );
366
- });
367
-
368
- it('creates both PlatformClient and DSPClient with correct config', async () => {
369
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
370
- namespaces: [],
371
- });
372
-
373
- await getTrustedCertificates(mockOptions);
374
-
375
- expect(PlatformClient).toHaveBeenCalledWith({
376
- authProvider: mockAuthProvider,
377
- platformUrl: mockOptions.platformEndpoint,
378
- });
379
-
380
- expect(DSPClient).toHaveBeenCalledWith({
381
- platformUrl: mockOptions.platformEndpoint,
382
- authProvider: mockAuthProvider,
383
- });
384
- });
385
-
386
- it('returns same Certificate type compatible with validateJWSCertificateChain', async () => {
387
- const mockCert = {
388
- pem: '-----BEGIN CERTIFICATE-----\nAQI=\n-----END CERTIFICATE-----',
389
- };
390
-
391
- mockPlatformClient.v1.namespace.listNamespaces.mockResolvedValue({
392
- namespaces: [{ id: 'namespace-1' }],
393
- });
394
-
395
- mockCertificateService.listCertificatesByNamespace.mockResolvedValue({
396
- certificates: [mockCert],
397
- pagination: { nextOffset: 0 },
398
- });
399
-
400
- const result = await getTrustedCertificates(mockOptions);
401
-
402
- // Verify the result can be used with validateJWSCertificateChain
403
- expect(result[0].pem).toBeDefined();
404
-
405
- // Integration test: verify compatibility with validateJWSCertificateChain
406
- const validationResult = await validateJWSCertificateChain(
407
- ['AQI='],
408
- result
409
- );
410
- expect(validationResult.valid).toBe(true);
411
- });
412
- });