@opentdf/sdk 0.3.0 → 0.3.2-beta.2277
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/cjs/src/access.js +46 -1
- package/dist/cjs/src/nanotdf/Client.js +12 -6
- package/dist/cjs/src/opentdf.js +37 -6
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/tdf3/src/assertions.js +5 -5
- package/dist/cjs/tdf3/src/client/index.js +20 -11
- package/dist/cjs/tdf3/src/tdf.js +19 -6
- package/dist/types/src/access.d.ts +1 -0
- package/dist/types/src/access.d.ts.map +1 -1
- package/dist/types/src/nanotdf/Client.d.ts +3 -1
- package/dist/types/src/nanotdf/Client.d.ts.map +1 -1
- package/dist/types/src/opentdf.d.ts +5 -1
- package/dist/types/src/opentdf.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tdf3/src/assertions.d.ts +1 -1
- package/dist/types/tdf3/src/assertions.d.ts.map +1 -1
- package/dist/types/tdf3/src/client/index.d.ts +8 -3
- package/dist/types/tdf3/src/client/index.d.ts.map +1 -1
- package/dist/types/tdf3/src/models/manifest.d.ts +1 -1
- package/dist/types/tdf3/src/models/manifest.d.ts.map +1 -1
- package/dist/types/tdf3/src/tdf.d.ts.map +1 -1
- package/dist/web/src/access.js +45 -1
- package/dist/web/src/nanotdf/Client.js +13 -7
- package/dist/web/src/opentdf.js +38 -7
- package/dist/web/src/version.js +1 -1
- package/dist/web/tdf3/src/assertions.js +5 -5
- package/dist/web/tdf3/src/client/index.js +21 -12
- package/dist/web/tdf3/src/tdf.js +19 -6
- package/package.json +1 -1
- package/src/access.ts +48 -0
- package/src/nanotdf/Client.ts +22 -6
- package/src/opentdf.ts +58 -8
- package/src/version.ts +1 -1
- package/tdf3/src/assertions.ts +4 -4
- package/tdf3/src/client/index.ts +30 -11
- package/tdf3/src/models/manifest.ts +2 -1
- package/tdf3/src/tdf.ts +27 -10
package/tdf3/src/client/index.ts
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
EncryptParamsBuilder,
|
|
40
40
|
} from './builders.js';
|
|
41
41
|
import {
|
|
42
|
+
fetchKeyAccessServers,
|
|
42
43
|
type KasPublicKeyInfo,
|
|
43
44
|
keyAlgorithmToPublicKeyAlgorithm,
|
|
44
45
|
OriginAllowList,
|
|
@@ -125,7 +126,7 @@ export interface ClientConfig {
|
|
|
125
126
|
clientId?: string;
|
|
126
127
|
dpopEnabled?: boolean;
|
|
127
128
|
dpopKeys?: Promise<CryptoKeyPair>;
|
|
128
|
-
kasEndpoint
|
|
129
|
+
kasEndpoint: string;
|
|
129
130
|
/**
|
|
130
131
|
* Service to use to look up ABAC. Used during autoconfigure. Defaults to
|
|
131
132
|
* kasEndpoint without the trailing `/kas` path segment, if present.
|
|
@@ -133,9 +134,11 @@ export interface ClientConfig {
|
|
|
133
134
|
policyEndpoint?: string;
|
|
134
135
|
/**
|
|
135
136
|
* List of allowed KASes to connect to for rewrap requests.
|
|
136
|
-
* Defaults to `[
|
|
137
|
+
* Defaults to `[]`.
|
|
137
138
|
*/
|
|
138
139
|
allowedKases?: string[];
|
|
140
|
+
// Platform URL to use to lookup allowed KASes when allowedKases is empty
|
|
141
|
+
platformUrl?: string;
|
|
139
142
|
ignoreAllowList?: boolean;
|
|
140
143
|
easEndpoint?: string;
|
|
141
144
|
// DEPRECATED Ignored
|
|
@@ -237,7 +240,12 @@ export class Client {
|
|
|
237
240
|
* List of allowed KASes to connect to for rewrap requests.
|
|
238
241
|
* Defaults to `[this.kasEndpoint]`.
|
|
239
242
|
*/
|
|
240
|
-
readonly allowedKases
|
|
243
|
+
readonly allowedKases?: OriginAllowList;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* URL of the platform, required to fetch list of allowed KASes when allowedKases is empty
|
|
247
|
+
*/
|
|
248
|
+
readonly platformUrl?: string;
|
|
241
249
|
|
|
242
250
|
readonly kasKeys: Record<string, Promise<KasPublicKeyInfo>[]> = {};
|
|
243
251
|
|
|
@@ -287,6 +295,14 @@ export class Client {
|
|
|
287
295
|
this.kasEndpoint = clientConfig.keyRewrapEndpoint.replace(/\/rewrap$/, '');
|
|
288
296
|
}
|
|
289
297
|
this.kasEndpoint = rstrip(this.kasEndpoint, '/');
|
|
298
|
+
|
|
299
|
+
if (!validateSecureUrl(this.kasEndpoint)) {
|
|
300
|
+
throw new ConfigurationError(`Invalid KAS endpoint [${this.kasEndpoint}]`);
|
|
301
|
+
}
|
|
302
|
+
if (config.platformUrl) {
|
|
303
|
+
this.platformUrl = config.platformUrl;
|
|
304
|
+
}
|
|
305
|
+
|
|
290
306
|
if (clientConfig.policyEndpoint) {
|
|
291
307
|
this.policyEndpoint = rstrip(clientConfig.policyEndpoint, '/');
|
|
292
308
|
} else if (this.kasEndpoint.endsWith('/kas')) {
|
|
@@ -299,16 +315,12 @@ export class Client {
|
|
|
299
315
|
clientConfig.allowedKases,
|
|
300
316
|
!!clientConfig.ignoreAllowList
|
|
301
317
|
);
|
|
302
|
-
if (!
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
} else {
|
|
306
|
-
if (!validateSecureUrl(this.kasEndpoint)) {
|
|
318
|
+
if (!this.allowedKases.allows(kasOrigin)) {
|
|
319
|
+
// TODO PR: ask if in this cases it makes more sense to add defaultKASEndpoint to the allow list if the allowList is not empty but doesn't have the defaultKas
|
|
307
320
|
throw new ConfigurationError(
|
|
308
|
-
`Invalid KAS endpoint [${this.kasEndpoint}]
|
|
321
|
+
`Invalid KAS endpoint [${this.kasEndpoint}]. When allowedKases is set, defaultKASEndpoint needs to be in the allow list`
|
|
309
322
|
);
|
|
310
323
|
}
|
|
311
|
-
this.allowedKases = new OriginAllowList([kasOrigin], !!clientConfig.ignoreAllowList);
|
|
312
324
|
}
|
|
313
325
|
|
|
314
326
|
this.authProvider = config.authProvider;
|
|
@@ -381,6 +393,7 @@ export class Client {
|
|
|
381
393
|
windowSize = DEFAULT_SEGMENT_SIZE,
|
|
382
394
|
keyMiddleware = defaultKeyMiddleware,
|
|
383
395
|
streamMiddleware = async (stream: DecoratedReadableStream) => stream,
|
|
396
|
+
tdfSpecVersion,
|
|
384
397
|
wrappingKeyAlgorithm = 'rsa:2048',
|
|
385
398
|
} = opts;
|
|
386
399
|
const scope = opts.scope ?? { attributes: [], dissem: [] };
|
|
@@ -444,6 +457,7 @@ export class Client {
|
|
|
444
457
|
? maxByteLimit
|
|
445
458
|
: opts.byteLimit;
|
|
446
459
|
const encryptionInformation = new SplitKey(new AesGcmCipher(this.cryptoService));
|
|
460
|
+
// TODO KAS: check here
|
|
447
461
|
const splits: SplitStep[] = splitPlan?.length
|
|
448
462
|
? splitPlan
|
|
449
463
|
: [{ kas: opts.defaultKASEndpoint ?? this.kasEndpoint }];
|
|
@@ -498,6 +512,7 @@ export class Client {
|
|
|
498
512
|
keyForEncryption,
|
|
499
513
|
keyForManifest,
|
|
500
514
|
assertionConfigs: opts.assertionConfigs,
|
|
515
|
+
tdfSpecVersion,
|
|
501
516
|
};
|
|
502
517
|
|
|
503
518
|
return (streamMiddleware as EncryptStreamMiddleware)(await writeStream(ecfg));
|
|
@@ -529,8 +544,12 @@ export class Client {
|
|
|
529
544
|
throw new ConfigurationError('AuthProvider missing');
|
|
530
545
|
}
|
|
531
546
|
const chunker = await makeChunkable(source);
|
|
532
|
-
if (!allowList) {
|
|
547
|
+
if (!allowList && this.allowedKases) {
|
|
533
548
|
allowList = this.allowedKases;
|
|
549
|
+
} else if (this.platformUrl) {
|
|
550
|
+
allowList = await fetchKeyAccessServers(this.platformUrl, this.authProvider);
|
|
551
|
+
} else {
|
|
552
|
+
throw new ConfigurationError('platformUrl is required when allowedKases is empty');
|
|
534
553
|
}
|
|
535
554
|
|
|
536
555
|
// Await in order to catch any errors from this call.
|
|
@@ -6,7 +6,8 @@ export type Manifest = {
|
|
|
6
6
|
payload: Payload;
|
|
7
7
|
encryptionInformation: EncryptionInformation;
|
|
8
8
|
assertions: Assertion[];
|
|
9
|
-
|
|
9
|
+
// Required in later versions, optional prior to 4.3.0
|
|
10
|
+
schemaVersion?: string;
|
|
10
11
|
// Deprecated
|
|
11
12
|
tdf_spec_version?: string;
|
|
12
13
|
};
|
package/tdf3/src/tdf.ts
CHANGED
|
@@ -287,8 +287,8 @@ async function _generateManifest(
|
|
|
287
287
|
keyInfo: KeyInfo,
|
|
288
288
|
encryptionInformation: SplitKey,
|
|
289
289
|
policy: Policy,
|
|
290
|
-
mimeType
|
|
291
|
-
targetSpecVersion
|
|
290
|
+
mimeType?: string,
|
|
291
|
+
targetSpecVersion?: string
|
|
292
292
|
): Promise<Manifest> {
|
|
293
293
|
// (maybe) Fields are quoted to avoid renaming
|
|
294
294
|
const payload: Payload = {
|
|
@@ -301,13 +301,19 @@ async function _generateManifest(
|
|
|
301
301
|
|
|
302
302
|
const encryptionInformationStr = await encryptionInformation.write(policy, keyInfo);
|
|
303
303
|
const assertions: assertions.Assertion[] = [];
|
|
304
|
-
|
|
304
|
+
const partial = {
|
|
305
305
|
payload,
|
|
306
306
|
// generate the manifest first, then insert integrity information into it
|
|
307
307
|
encryptionInformation: encryptionInformationStr,
|
|
308
308
|
assertions: assertions,
|
|
309
|
-
|
|
310
|
-
|
|
309
|
+
};
|
|
310
|
+
const schemaVersion = targetSpecVersion || tdfSpecVersion;
|
|
311
|
+
if (schemaVersion === '4.2.2') {
|
|
312
|
+
return partial;
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
...partial,
|
|
316
|
+
schemaVersion,
|
|
311
317
|
};
|
|
312
318
|
}
|
|
313
319
|
|
|
@@ -401,7 +407,7 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
|
|
|
401
407
|
cfg.encryptionInformation,
|
|
402
408
|
cfg.policy,
|
|
403
409
|
cfg.mimeType,
|
|
404
|
-
cfg.tdfSpecVersion
|
|
410
|
+
cfg.tdfSpecVersion
|
|
405
411
|
);
|
|
406
412
|
|
|
407
413
|
if (!manifest) {
|
|
@@ -531,10 +537,14 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
|
|
|
531
537
|
alg: 'HS256',
|
|
532
538
|
key: new Uint8Array(cfg.keyForEncryption.unwrappedKeyBinary.asArrayBuffer()),
|
|
533
539
|
};
|
|
534
|
-
const assertion = await assertions.CreateAssertion(
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
540
|
+
const assertion = await assertions.CreateAssertion(
|
|
541
|
+
aggregateHash,
|
|
542
|
+
{
|
|
543
|
+
...assertionConfig,
|
|
544
|
+
signingKey,
|
|
545
|
+
},
|
|
546
|
+
cfg.tdfSpecVersion
|
|
547
|
+
);
|
|
538
548
|
|
|
539
549
|
// Add signed assertion to the signedAssertions array
|
|
540
550
|
signedAssertions.push(assertion);
|
|
@@ -981,6 +991,13 @@ export async function readStream(cfg: DecryptConfiguration) {
|
|
|
981
991
|
return decryptStreamFrom(cfg, overview);
|
|
982
992
|
}
|
|
983
993
|
|
|
994
|
+
// TODO: potentially might need fixing here
|
|
995
|
+
// By the time this function is called the allow list will be already set.
|
|
996
|
+
// Verify that this function is not exported in the sdk and only exported for internal use
|
|
997
|
+
// Verify this during tests and PR
|
|
998
|
+
// Remove this comment before merging!
|
|
999
|
+
// https://www.youtube.com/watch?v=NGrLb6W5YOM
|
|
1000
|
+
// Don't leave me here all by myself!
|
|
984
1001
|
export async function decryptStreamFrom(
|
|
985
1002
|
cfg: DecryptConfiguration,
|
|
986
1003
|
{ manifest, zipReader, centralDirectory }: InspectedTDFOverview
|