@opentdf/ctl 0.1.0-beta.1701
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/README.md +34 -0
- package/bin/opentdf.mjs +4 -0
- package/dist/src/cli.js +511 -0
- package/dist/src/logger.js +64 -0
- package/dist/src/polyfills.js +6 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# OpenTDF command line tool (for node)
|
|
2
|
+
|
|
3
|
+
A sample application using node & ESM to import and test a project
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
opentdf.mjs <auth options> <policy options> [encrypt|decrypt] [input file]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Sample round trip execution:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
echo hello-world >sample.txt
|
|
15
|
+
bin/opentdf.mjs encrypt \
|
|
16
|
+
--kasEndpoint http://localhost:65432/api/kas \
|
|
17
|
+
--oidcEndpoint http://localhost:65432/auth/realms/tdf \
|
|
18
|
+
--auth tdf-client:123-456 \
|
|
19
|
+
--containerType tdf3 \
|
|
20
|
+
--output sample.tdf \
|
|
21
|
+
sample.txt
|
|
22
|
+
bin/opentdf.mjs \
|
|
23
|
+
--kasEndpoint http://localhost:65432/api/kas \
|
|
24
|
+
--oidcEndpoint http://localhost:65432/auth/realms/tdf \
|
|
25
|
+
--auth tdf-client:123-456 \
|
|
26
|
+
--containerType tdf3 \
|
|
27
|
+
--userId alice@somewhere.there \
|
|
28
|
+
decrypt sample.tdf
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### References
|
|
32
|
+
|
|
33
|
+
- [yargs](http://yargs.js.org)
|
|
34
|
+
- [typescript CLI starter](https://github.com/khalidx/typescript-cli-starter)
|
package/bin/opentdf.mjs
ADDED
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import './polyfills.js';
|
|
2
|
+
import { createWriteStream, openAsBlob } from 'node:fs';
|
|
3
|
+
import { readFile, stat, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { Writable } from 'node:stream';
|
|
5
|
+
import yargs from 'yargs';
|
|
6
|
+
import { hideBin } from 'yargs/helpers';
|
|
7
|
+
import { AuthProviders, NanoTDFClient, NanoTDFDatasetClient, TDF3Client, version, EncryptParamsBuilder, DecryptParamsBuilder, } from '@opentdf/sdk';
|
|
8
|
+
import { CLIError, log } from './logger.js';
|
|
9
|
+
import * as assertions from '@opentdf/sdk/assertions';
|
|
10
|
+
import { attributeFQNsAsValues } from '@opentdf/sdk/nano';
|
|
11
|
+
import { base64 } from '@opentdf/sdk/encodings';
|
|
12
|
+
const bindingTypes = ['ecdsa', 'gmac'];
|
|
13
|
+
const containerTypes = ['tdf3', 'nano', 'dataset', 'ztdf'];
|
|
14
|
+
const parseJwt = (jwt, field = 1) => {
|
|
15
|
+
return JSON.parse(base64.decode(jwt.split('.')[field]));
|
|
16
|
+
};
|
|
17
|
+
const parseJwtComplete = (jwt) => {
|
|
18
|
+
return { header: parseJwt(jwt, 0), payload: parseJwt(jwt) };
|
|
19
|
+
};
|
|
20
|
+
async function processAuth({ auth, clientId, clientSecret, oidcEndpoint, userId, }) {
|
|
21
|
+
log('DEBUG', 'Processing auth params');
|
|
22
|
+
if (auth) {
|
|
23
|
+
log('DEBUG', 'Processing an auth string');
|
|
24
|
+
const authParts = auth.split(':');
|
|
25
|
+
if (authParts.length !== 2) {
|
|
26
|
+
throw new CLIError('CRITICAL', `Auth expects <clientId>:<clientSecret>, received ${auth}`);
|
|
27
|
+
}
|
|
28
|
+
[clientId, clientSecret] = authParts;
|
|
29
|
+
}
|
|
30
|
+
else if (!clientId || !clientSecret) {
|
|
31
|
+
throw new CLIError('CRITICAL', 'Auth expects clientId and clientSecret, or combined auth param');
|
|
32
|
+
}
|
|
33
|
+
const actual = await AuthProviders.clientSecretAuthProvider({
|
|
34
|
+
clientId,
|
|
35
|
+
oidcOrigin: oidcEndpoint,
|
|
36
|
+
exchange: 'client',
|
|
37
|
+
clientSecret,
|
|
38
|
+
});
|
|
39
|
+
const requestLog = [];
|
|
40
|
+
return {
|
|
41
|
+
requestLog,
|
|
42
|
+
updateClientPublicKey: async (signingKey) => {
|
|
43
|
+
actual.updateClientPublicKey(signingKey);
|
|
44
|
+
log('DEBUG', `updateClientPublicKey: [${signingKey?.publicKey}]`);
|
|
45
|
+
},
|
|
46
|
+
withCreds: async (httpReq) => {
|
|
47
|
+
const credible = await actual.withCreds(httpReq);
|
|
48
|
+
if (userId) {
|
|
49
|
+
const url = new URL(credible.url);
|
|
50
|
+
url.searchParams.set('userId', userId);
|
|
51
|
+
credible.url = url.href;
|
|
52
|
+
}
|
|
53
|
+
log('DEBUG', `HTTP Requesting: ${JSON.stringify(credible)}`);
|
|
54
|
+
requestLog.push(credible);
|
|
55
|
+
return credible;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const rstrip = (str, suffix = ' ') => {
|
|
60
|
+
while (str && suffix && str.endsWith(suffix)) {
|
|
61
|
+
str = str.slice(0, -suffix.length);
|
|
62
|
+
}
|
|
63
|
+
return str;
|
|
64
|
+
};
|
|
65
|
+
function addParams(client, argv) {
|
|
66
|
+
if (argv.attributes?.length) {
|
|
67
|
+
client.dataAttributes = argv.attributes.split(',');
|
|
68
|
+
}
|
|
69
|
+
if (argv.usersWithAccess?.length) {
|
|
70
|
+
client.dissems = argv.usersWithAccess.split(',');
|
|
71
|
+
}
|
|
72
|
+
log('SILLY', `Built encrypt params dissems: ${client.dissems}, attrs: ${client.dataAttributes}`);
|
|
73
|
+
}
|
|
74
|
+
async function tdf3DecryptParamsFor(argv) {
|
|
75
|
+
const c = new DecryptParamsBuilder();
|
|
76
|
+
if (argv.noVerifyAssertions) {
|
|
77
|
+
c.withNoVerifyAssertions(true);
|
|
78
|
+
}
|
|
79
|
+
c.setFileSource(await openAsBlob(argv.file));
|
|
80
|
+
return c.build();
|
|
81
|
+
}
|
|
82
|
+
function parseAssertionConfig(s) {
|
|
83
|
+
const u = JSON.parse(s);
|
|
84
|
+
// if u is null or empty, return an empty array
|
|
85
|
+
if (!u) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
const a = Array.isArray(u) ? u : [u];
|
|
89
|
+
for (const assertion of a) {
|
|
90
|
+
if (!assertions.isAssertionConfig(assertion)) {
|
|
91
|
+
throw new CLIError('CRITICAL', `invalid assertion config ${JSON.stringify(assertion)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return a;
|
|
95
|
+
}
|
|
96
|
+
async function tdf3EncryptParamsFor(argv) {
|
|
97
|
+
const c = new EncryptParamsBuilder();
|
|
98
|
+
if (argv.assertions?.length) {
|
|
99
|
+
c.withAssertions(parseAssertionConfig(argv.assertions));
|
|
100
|
+
}
|
|
101
|
+
if (argv.attributes?.length) {
|
|
102
|
+
c.setAttributes(argv.attributes.split(','));
|
|
103
|
+
}
|
|
104
|
+
if (argv.usersWithAccess?.length) {
|
|
105
|
+
c.setUsersWithAccess(argv.usersWithAccess.split(','));
|
|
106
|
+
}
|
|
107
|
+
if (argv.mimeType?.length) {
|
|
108
|
+
c.setMimeType(argv.mimeType);
|
|
109
|
+
}
|
|
110
|
+
if (argv.autoconfigure) {
|
|
111
|
+
c.withAutoconfigure();
|
|
112
|
+
}
|
|
113
|
+
// use offline mode, we do not have upsert for v2
|
|
114
|
+
c.setOffline();
|
|
115
|
+
// FIXME TODO must call file.close() after we are done
|
|
116
|
+
const buffer = await processDataIn(argv.file);
|
|
117
|
+
c.setBufferSource(buffer);
|
|
118
|
+
return c.build();
|
|
119
|
+
}
|
|
120
|
+
async function processDataIn(file) {
|
|
121
|
+
if (!file) {
|
|
122
|
+
throw new CLIError('CRITICAL', 'Must specify file or pipe');
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const stats = await stat(file);
|
|
126
|
+
if (!stats?.isFile()) {
|
|
127
|
+
throw new CLIError('CRITICAL', `File does not exist [${file}]`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
throw new CLIError('CRITICAL', `File is not accessable [${file}]`);
|
|
132
|
+
}
|
|
133
|
+
log('DEBUG', `Using input from file [${file}]`);
|
|
134
|
+
return readFile(file);
|
|
135
|
+
}
|
|
136
|
+
export const handleArgs = (args) => {
|
|
137
|
+
return (yargs(args)
|
|
138
|
+
.middleware((argv) => {
|
|
139
|
+
if (argv.silent) {
|
|
140
|
+
log.level = 'CRITICAL';
|
|
141
|
+
}
|
|
142
|
+
else if (argv.logLevel) {
|
|
143
|
+
const ll = argv.logLevel;
|
|
144
|
+
log.level = ll.toUpperCase();
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
.fail((msg, err, yargs) => {
|
|
148
|
+
if (err instanceof CLIError) {
|
|
149
|
+
log(err);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
else if (err) {
|
|
153
|
+
log(err);
|
|
154
|
+
process.exit(2);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.error(`${msg}\n\n${yargs.help()}`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
// AUTH OPTIONS
|
|
162
|
+
.option('kasEndpoint', {
|
|
163
|
+
demandOption: true,
|
|
164
|
+
group: 'Server Endpoints:',
|
|
165
|
+
type: 'string',
|
|
166
|
+
description: 'URL to non-default KAS instance (https://mykas.net)',
|
|
167
|
+
})
|
|
168
|
+
.option('oidcEndpoint', {
|
|
169
|
+
demandOption: true,
|
|
170
|
+
group: 'Server Endpoints:',
|
|
171
|
+
type: 'string',
|
|
172
|
+
description: 'URL to non-default OIDC IdP (https://myidp.net)',
|
|
173
|
+
})
|
|
174
|
+
.option('policyEndpoint', {
|
|
175
|
+
group: 'Server Endpoints:',
|
|
176
|
+
type: 'string',
|
|
177
|
+
description: 'Attribute and key grant service endpoint',
|
|
178
|
+
})
|
|
179
|
+
.option('allowList', {
|
|
180
|
+
group: 'Security:',
|
|
181
|
+
desc: 'allowed KAS origins, comma separated; defaults to [kasEndpoint]',
|
|
182
|
+
type: 'string',
|
|
183
|
+
validate: (uris) => uris.split(','),
|
|
184
|
+
})
|
|
185
|
+
.option('ignoreAllowList', {
|
|
186
|
+
group: 'Security:',
|
|
187
|
+
desc: 'disable KAS allowlist feature for decrypt',
|
|
188
|
+
type: 'boolean',
|
|
189
|
+
})
|
|
190
|
+
.option('noVerifyAssertions', {
|
|
191
|
+
alias: 'no-verify-assertions',
|
|
192
|
+
group: 'Security',
|
|
193
|
+
desc: 'Do not verify assertions',
|
|
194
|
+
type: 'boolean',
|
|
195
|
+
})
|
|
196
|
+
.option('auth', {
|
|
197
|
+
group: 'OAuth and OIDC:',
|
|
198
|
+
type: 'string',
|
|
199
|
+
description: 'Combined OAuth Client Credentials (<clientId>:<clientSecret>)',
|
|
200
|
+
})
|
|
201
|
+
.option('dpop', {
|
|
202
|
+
group: 'Security:',
|
|
203
|
+
desc: 'Use DPoP for token binding',
|
|
204
|
+
type: 'boolean',
|
|
205
|
+
})
|
|
206
|
+
.implies('auth', '--no-clientId')
|
|
207
|
+
.implies('auth', '--no-clientSecret')
|
|
208
|
+
.option('clientId', {
|
|
209
|
+
group: 'OAuth and OIDC:',
|
|
210
|
+
alias: 'cid',
|
|
211
|
+
type: 'string',
|
|
212
|
+
description: 'OAuth Client Credentials: IdP-issued Client ID',
|
|
213
|
+
})
|
|
214
|
+
.implies('clientId', 'clientSecret')
|
|
215
|
+
.option('clientSecret', {
|
|
216
|
+
group: 'OAuth and OIDC:',
|
|
217
|
+
alias: 'cs',
|
|
218
|
+
type: 'string',
|
|
219
|
+
description: 'OAuth Client Credentials: IdP-issued Client Secret',
|
|
220
|
+
})
|
|
221
|
+
.implies('clientSecret', 'clientId')
|
|
222
|
+
.option('exchangeToken', {
|
|
223
|
+
group: 'OAuth and OIDC:',
|
|
224
|
+
alias: 'et',
|
|
225
|
+
type: 'string',
|
|
226
|
+
description: 'OAuth Token Exchange: Token issued by trusted external IdP',
|
|
227
|
+
})
|
|
228
|
+
.implies('exchangeToken', 'clientId')
|
|
229
|
+
// Examples
|
|
230
|
+
.example('$0 --auth ClientID123:Cli3nt$ecret', '# OIDC client credentials')
|
|
231
|
+
.example('$0 --clientId ClientID123 --clientSecret Cli3nt$ecret', '# OIDC client credentials')
|
|
232
|
+
// Policy, encryption, and container options
|
|
233
|
+
.options({
|
|
234
|
+
assertions: {
|
|
235
|
+
group: 'Encrypt Options:',
|
|
236
|
+
desc: 'ZTDF assertion config objects',
|
|
237
|
+
type: 'string',
|
|
238
|
+
default: '',
|
|
239
|
+
validate: parseAssertionConfig,
|
|
240
|
+
},
|
|
241
|
+
attributes: {
|
|
242
|
+
group: 'Encrypt Options:',
|
|
243
|
+
desc: 'Data attributes for the policy',
|
|
244
|
+
type: 'string',
|
|
245
|
+
default: '',
|
|
246
|
+
validate: (attributes) => attributes.split(','),
|
|
247
|
+
},
|
|
248
|
+
autoconfigure: {
|
|
249
|
+
group: 'Encrypt Options:',
|
|
250
|
+
desc: 'Enable automatic configuration from attributes using policy service',
|
|
251
|
+
type: 'boolean',
|
|
252
|
+
default: false,
|
|
253
|
+
},
|
|
254
|
+
containerType: {
|
|
255
|
+
group: 'Encrypt Options:',
|
|
256
|
+
alias: 't',
|
|
257
|
+
choices: containerTypes,
|
|
258
|
+
description: 'Container format',
|
|
259
|
+
default: 'nano',
|
|
260
|
+
},
|
|
261
|
+
policyBinding: {
|
|
262
|
+
group: 'Encrypt Options:',
|
|
263
|
+
choices: bindingTypes,
|
|
264
|
+
description: 'Policy Binding Type (nano only)',
|
|
265
|
+
default: 'gmac',
|
|
266
|
+
},
|
|
267
|
+
mimeType: {
|
|
268
|
+
group: 'Encrypt Options:',
|
|
269
|
+
desc: 'Mime type for the plain text file (only supported for ztdf)',
|
|
270
|
+
type: 'string',
|
|
271
|
+
default: '',
|
|
272
|
+
},
|
|
273
|
+
userId: {
|
|
274
|
+
group: 'Encrypt Options:',
|
|
275
|
+
type: 'string',
|
|
276
|
+
description: 'Owner email address',
|
|
277
|
+
},
|
|
278
|
+
usersWithAccess: {
|
|
279
|
+
alias: 'users-with-access',
|
|
280
|
+
group: 'Encrypt Options:',
|
|
281
|
+
desc: 'Add users to the policy',
|
|
282
|
+
type: 'string',
|
|
283
|
+
default: '',
|
|
284
|
+
validate: (users) => users.split(','),
|
|
285
|
+
},
|
|
286
|
+
})
|
|
287
|
+
// COMMANDS
|
|
288
|
+
.options({
|
|
289
|
+
logLevel: {
|
|
290
|
+
group: 'Verbosity:',
|
|
291
|
+
alias: 'log-level',
|
|
292
|
+
type: 'string',
|
|
293
|
+
default: 'info',
|
|
294
|
+
desc: 'Set logging level',
|
|
295
|
+
},
|
|
296
|
+
silent: {
|
|
297
|
+
group: 'Verbosity:',
|
|
298
|
+
type: 'boolean',
|
|
299
|
+
default: false,
|
|
300
|
+
desc: 'Disable logging',
|
|
301
|
+
},
|
|
302
|
+
})
|
|
303
|
+
.option('output', {
|
|
304
|
+
type: 'string',
|
|
305
|
+
description: 'output file',
|
|
306
|
+
})
|
|
307
|
+
.command('attrs', 'Look up defintions of attributes', (yargs) => {
|
|
308
|
+
yargs.strict();
|
|
309
|
+
}, async (argv) => {
|
|
310
|
+
log('DEBUG', 'attribute value lookup');
|
|
311
|
+
const authProvider = await processAuth(argv);
|
|
312
|
+
const signingKey = await crypto.subtle.generateKey({
|
|
313
|
+
name: 'RSASSA-PKCS1-v1_5',
|
|
314
|
+
hash: 'SHA-256',
|
|
315
|
+
modulusLength: 2048,
|
|
316
|
+
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
317
|
+
}, true, ['sign', 'verify']);
|
|
318
|
+
authProvider.updateClientPublicKey(signingKey);
|
|
319
|
+
log('DEBUG', `Initialized auth provider ${JSON.stringify(authProvider)}`);
|
|
320
|
+
const policyUrl = guessPolicyUrl(argv);
|
|
321
|
+
const defs = await attributeFQNsAsValues(policyUrl, authProvider, ...argv.attributes.split(','));
|
|
322
|
+
console.log(JSON.stringify(defs, null, 2));
|
|
323
|
+
})
|
|
324
|
+
.command('decrypt [file]', 'Decrypt TDF to string',
|
|
325
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
326
|
+
(yargs) => {
|
|
327
|
+
yargs.strict().positional('file', {
|
|
328
|
+
describe: 'path to plain text file',
|
|
329
|
+
type: 'string',
|
|
330
|
+
});
|
|
331
|
+
}, async (argv) => {
|
|
332
|
+
log('DEBUG', 'Running decrypt command');
|
|
333
|
+
const allowedKases = argv.allowList?.split(',');
|
|
334
|
+
const ignoreAllowList = !!argv.ignoreAllowList;
|
|
335
|
+
const authProvider = await processAuth(argv);
|
|
336
|
+
log('DEBUG', `Initialized auth provider ${JSON.stringify(authProvider)}`);
|
|
337
|
+
const kasEndpoint = argv.kasEndpoint;
|
|
338
|
+
if (argv.containerType === 'tdf3' || argv.containerType == 'ztdf') {
|
|
339
|
+
log('DEBUG', `TDF3 Client`);
|
|
340
|
+
const client = new TDF3Client({
|
|
341
|
+
allowedKases,
|
|
342
|
+
ignoreAllowList,
|
|
343
|
+
authProvider,
|
|
344
|
+
kasEndpoint,
|
|
345
|
+
dpopEnabled: argv.dpop,
|
|
346
|
+
});
|
|
347
|
+
log('SILLY', `Initialized client ${JSON.stringify(client)}`);
|
|
348
|
+
log('DEBUG', `About to decrypt [${argv.file}]`);
|
|
349
|
+
const ct = await client.decrypt(await tdf3DecryptParamsFor(argv));
|
|
350
|
+
if (argv.output) {
|
|
351
|
+
const destination = createWriteStream(argv.output);
|
|
352
|
+
await ct.stream.pipeTo(Writable.toWeb(destination));
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
console.log(await ct.toString());
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
const dpopEnabled = !!argv.dpop;
|
|
360
|
+
const client = argv.containerType === 'nano'
|
|
361
|
+
? new NanoTDFClient({
|
|
362
|
+
allowedKases,
|
|
363
|
+
ignoreAllowList,
|
|
364
|
+
authProvider,
|
|
365
|
+
kasEndpoint,
|
|
366
|
+
dpopEnabled,
|
|
367
|
+
})
|
|
368
|
+
: new NanoTDFDatasetClient({
|
|
369
|
+
allowedKases,
|
|
370
|
+
ignoreAllowList,
|
|
371
|
+
authProvider,
|
|
372
|
+
kasEndpoint,
|
|
373
|
+
dpopEnabled,
|
|
374
|
+
});
|
|
375
|
+
const buffer = await processDataIn(argv.file);
|
|
376
|
+
log('DEBUG', 'Decrypt data.');
|
|
377
|
+
const plaintext = await client.decrypt(buffer);
|
|
378
|
+
log('DEBUG', 'Handle output.');
|
|
379
|
+
if (argv.output) {
|
|
380
|
+
await writeFile(argv.output, new Uint8Array(plaintext));
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
console.log(new TextDecoder().decode(plaintext));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
const lastRequest = authProvider.requestLog[authProvider.requestLog.length - 1];
|
|
387
|
+
let accessToken = null;
|
|
388
|
+
let dpopToken = null;
|
|
389
|
+
for (const h of Object.keys(lastRequest.headers)) {
|
|
390
|
+
switch (h.toLowerCase()) {
|
|
391
|
+
case 'dpop':
|
|
392
|
+
console.assert(!dpopToken, 'Multiple dpop headers found');
|
|
393
|
+
dpopToken = parseJwtComplete(lastRequest.headers[h]);
|
|
394
|
+
log('INFO', `dpop: ${JSON.stringify(dpopToken)}`);
|
|
395
|
+
break;
|
|
396
|
+
case 'authorization':
|
|
397
|
+
console.assert(!accessToken, 'Multiple authorization headers found');
|
|
398
|
+
accessToken = parseJwt(lastRequest.headers[h].split(' ')[1]);
|
|
399
|
+
log('INFO', `Access Token: ${JSON.stringify(accessToken)}`);
|
|
400
|
+
if (argv.dpop) {
|
|
401
|
+
console.assert(accessToken.cnf?.jkt, 'Access token must have a cnf.jkt');
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
console.assert(accessToken, 'No access_token found');
|
|
407
|
+
console.assert(!argv.dpop || dpopToken, 'DPoP requested but absent');
|
|
408
|
+
})
|
|
409
|
+
.command('encrypt [file]', 'Encrypt file or pipe to a TDF',
|
|
410
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
411
|
+
(yargs) => {
|
|
412
|
+
yargs.strict().positional('file', {
|
|
413
|
+
describe: 'path to plain text file',
|
|
414
|
+
type: 'string',
|
|
415
|
+
});
|
|
416
|
+
}, async (argv) => {
|
|
417
|
+
log('DEBUG', 'Running encrypt command');
|
|
418
|
+
const authProvider = await processAuth(argv);
|
|
419
|
+
log('DEBUG', `Initialized auth provider ${JSON.stringify(authProvider)}`);
|
|
420
|
+
const kasEndpoint = argv.kasEndpoint;
|
|
421
|
+
const ignoreAllowList = !!argv.ignoreAllowList;
|
|
422
|
+
const allowedKases = argv.allowList?.split(',');
|
|
423
|
+
if ('tdf3' === argv.containerType || 'ztdf' === argv.containerType) {
|
|
424
|
+
log('DEBUG', `TDF3 Client`);
|
|
425
|
+
const policyEndpoint = guessPolicyUrl(argv);
|
|
426
|
+
const client = new TDF3Client({
|
|
427
|
+
allowedKases,
|
|
428
|
+
ignoreAllowList,
|
|
429
|
+
authProvider,
|
|
430
|
+
kasEndpoint,
|
|
431
|
+
policyEndpoint,
|
|
432
|
+
dpopEnabled: argv.dpop,
|
|
433
|
+
});
|
|
434
|
+
log('SILLY', `Initialized client ${JSON.stringify(client)}`);
|
|
435
|
+
const ct = await client.encrypt(await tdf3EncryptParamsFor(argv));
|
|
436
|
+
if (!ct) {
|
|
437
|
+
throw new CLIError('CRITICAL', 'Encrypt configuration error: No output?');
|
|
438
|
+
}
|
|
439
|
+
if (argv.output) {
|
|
440
|
+
const destination = createWriteStream(argv.output);
|
|
441
|
+
await ct.stream.pipeTo(Writable.toWeb(destination));
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
console.log(await ct.toString());
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
const dpopEnabled = !!argv.dpop;
|
|
449
|
+
const ecdsaBinding = argv.policyBinding.toLowerCase() == 'ecdsa';
|
|
450
|
+
const client = argv.containerType === 'nano'
|
|
451
|
+
? new NanoTDFClient({ allowedKases, authProvider, dpopEnabled, kasEndpoint })
|
|
452
|
+
: new NanoTDFDatasetClient({
|
|
453
|
+
allowedKases,
|
|
454
|
+
authProvider,
|
|
455
|
+
dpopEnabled,
|
|
456
|
+
kasEndpoint,
|
|
457
|
+
});
|
|
458
|
+
log('SILLY', `Initialized client ${JSON.stringify(client)}`);
|
|
459
|
+
addParams(client, argv);
|
|
460
|
+
const buffer = await processDataIn(argv.file);
|
|
461
|
+
const cyphertext = await client.encrypt(buffer, { ecdsaBinding });
|
|
462
|
+
log('DEBUG', `Handle cyphertext output ${JSON.stringify(cyphertext)}`);
|
|
463
|
+
if (argv.output) {
|
|
464
|
+
await writeFile(argv.output, new Uint8Array(cyphertext));
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
console.log(base64.encodeArrayBuffer(cyphertext));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
})
|
|
471
|
+
.usage('openTDF CLI\n\nUsage: $0 [options]')
|
|
472
|
+
.alias('help', 'h')
|
|
473
|
+
.demandCommand()
|
|
474
|
+
.recommendCommands()
|
|
475
|
+
.help('help')
|
|
476
|
+
.options({
|
|
477
|
+
env: {
|
|
478
|
+
desc: 'Set the environment',
|
|
479
|
+
},
|
|
480
|
+
})
|
|
481
|
+
.version('version', JSON.stringify({
|
|
482
|
+
'@opentdf/ctl': process.env.npm_package_version || 'UNRELEASED',
|
|
483
|
+
'@opentdf/sdk': version,
|
|
484
|
+
}))
|
|
485
|
+
.alias('version', 'V')
|
|
486
|
+
.strict()
|
|
487
|
+
.parseAsync());
|
|
488
|
+
};
|
|
489
|
+
export const main = async (argsPromise) => {
|
|
490
|
+
argsPromise;
|
|
491
|
+
};
|
|
492
|
+
handleArgs(hideBin(process.argv))
|
|
493
|
+
.then(main)
|
|
494
|
+
.then(() => {
|
|
495
|
+
// Nothing;
|
|
496
|
+
})
|
|
497
|
+
.catch((err) => {
|
|
498
|
+
console.error(err);
|
|
499
|
+
});
|
|
500
|
+
function guessPolicyUrl({ kasEndpoint, policyEndpoint, }) {
|
|
501
|
+
let policyUrl;
|
|
502
|
+
if (policyEndpoint) {
|
|
503
|
+
policyUrl = rstrip(policyEndpoint, '/');
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
const uNoSlash = rstrip(kasEndpoint, '/');
|
|
507
|
+
policyUrl = uNoSlash.endsWith('/kas') ? uNoSlash.slice(0, -4) : uNoSlash;
|
|
508
|
+
}
|
|
509
|
+
return policyUrl;
|
|
510
|
+
}
|
|
511
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxVQUFVLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDeEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4QyxPQUFPLEVBSUwsYUFBYSxFQUNiLGFBQWEsRUFDYixvQkFBb0IsRUFDcEIsVUFBVSxFQUNWLE9BQU8sRUFDUCxvQkFBb0IsRUFFcEIsb0JBQW9CLEdBQ3JCLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxRQUFRLEVBQVMsR0FBRyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRW5ELE9BQU8sS0FBSyxVQUFVLE1BQU0seUJBQXlCLENBQUM7QUFDdEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDMUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBY2hELE1BQU0sWUFBWSxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBRXZDLE1BQU0sY0FBYyxHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFFM0QsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFXLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxFQUFFO0lBQzFDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFD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
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export const Levels = ['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'SILLY'];
|
|
2
|
+
export class CLIError extends Error {
|
|
3
|
+
constructor(prefix, message, cause) {
|
|
4
|
+
super(message, { cause });
|
|
5
|
+
this.prefix = prefix;
|
|
6
|
+
this.message = message;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export const log = Object.assign((thing, message) => {
|
|
10
|
+
let e;
|
|
11
|
+
let m;
|
|
12
|
+
let l;
|
|
13
|
+
if (thing instanceof CLIError) {
|
|
14
|
+
l = thing.prefix;
|
|
15
|
+
m = thing.message;
|
|
16
|
+
e = thing;
|
|
17
|
+
}
|
|
18
|
+
else if (thing instanceof Error) {
|
|
19
|
+
l = 'CRITICAL';
|
|
20
|
+
m = thing.message;
|
|
21
|
+
e = thing;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
l = thing;
|
|
25
|
+
m = message || '';
|
|
26
|
+
e = null;
|
|
27
|
+
}
|
|
28
|
+
const prefixed = `[${l}] ${m}`;
|
|
29
|
+
const i = Levels.indexOf(l);
|
|
30
|
+
if (i <= Levels.indexOf(log.level)) {
|
|
31
|
+
switch (l) {
|
|
32
|
+
case 'CRITICAL':
|
|
33
|
+
case 'ERROR':
|
|
34
|
+
if (e && !(e instanceof CLIError)) {
|
|
35
|
+
console.error(prefixed, e);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
console.error(prefixed);
|
|
39
|
+
}
|
|
40
|
+
break;
|
|
41
|
+
case 'WARNING':
|
|
42
|
+
if (e) {
|
|
43
|
+
console.warn(prefixed, e);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
console.warn(prefixed);
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
case 'INFO':
|
|
50
|
+
console.info(prefixed);
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
console.log(prefixed);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (log.level === 'SILLY') {
|
|
58
|
+
console.error(e);
|
|
59
|
+
}
|
|
60
|
+
if (l === 'CRITICAL') {
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}, { level: 'INFO' });
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xvZ2dlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxNQUFNLENBQUMsTUFBTSxNQUFNLEdBQVksQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBRTFGLE1BQU0sT0FBTyxRQUFTLFNBQVEsS0FBSztJQUVqQyxZQUFZLE1BQWEsRUFBRSxPQUFlLEVBQUUsS0FBYTtRQUN2RCxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztJQUN6QixDQUFDO0NBQ0Y7QUFPRCxNQUFNLENBQUMsTUFBTSxHQUFHLEdBQVcsTUFBTSxDQUFDLE1BQU0sQ0FDdEMsQ0FBQyxLQUErQixFQUFFLE9BQWdCLEVBQUUsRUFBRTtJQUNwRCxJQUFJLENBQWUsQ0FBQztJQUNwQixJQUFJLENBQVMsQ0FBQztJQUNkLElBQUksQ0FBUSxDQUFDO0lBRWIsSUFBSSxLQUFLLFlBQVksUUFBUSxFQUFFLENBQUM7UUFDOUIsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDakIsQ0FBQyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDbEIsQ0FBQyxHQUFHLEtBQWMsQ0FBQztJQUNyQixDQUFDO1NBQU0sSUFBSSxLQUFLLFlBQVksS0FBSyxFQUFFLENBQUM7UUFDbEMsQ0FBQyxHQUFHLFVBQVUsQ0FBQztRQUNmLENBQUMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDO1FBQ2xCLENBQUMsR0FBRyxLQUFjLENBQUM7SUFDckIsQ0FBQztTQUFNLENBQUM7UUFDTixDQUFDLEdBQUcsS0FBYyxDQUFDO1FBQ25CLENBQUMsR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO1FBQ2xCLENBQUMsR0FBRyxJQUFJLENBQUM7SUFDWCxDQUFDO0lBQ0QsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDL0IsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QixJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ25DLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDVixLQUFLLFVBQVUsQ0FBQztZQUNoQixLQUFLLE9BQU87Z0JBQ1YsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsWUFBWSxRQUFRLENBQUMsRUFBRSxDQUFDO29CQUNsQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDN0IsQ0FBQztxQkFBTSxDQUFDO29CQUNOLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQzFCLENBQUM7Z0JBQ0QsTUFBTTtZQUNSLEtBQUssU0FBUztnQkFDWixJQUFJLENBQUMsRUFBRSxDQUFDO29CQUNOLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUM1QixDQUFDO3FCQUFNLENBQUM7b0JBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDekIsQ0FBQztnQkFDRCxNQUFNO1lBQ1IsS0FBSyxNQUFNO2dCQUNULE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ3ZCLE1BQU07WUFDUjtnQkFDRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUN0QixNQUFNO1FBQ1YsQ0FBQztJQUNILENBQUM7SUFDRCxJQUFJLEdBQUcsQ0FBQyxLQUFLLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDMUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsSUFBSSxDQUFDLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDckIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQixDQUFDO0FBQ0gsQ0FBQyxFQUNELEVBQUUsS0FBSyxFQUFFLE1BQWUsRUFBRSxDQUMzQixDQUFDIn0=
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
if (!('document' in globalThis)) {
|
|
2
|
+
// @ts-expect-error // document is either undefined or readonly
|
|
3
|
+
globalThis.document = { documentElement: { style: {} } };
|
|
4
|
+
}
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9seWZpbGxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BvbHlmaWxscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxJQUFJLENBQUMsQ0FBQyxVQUFVLElBQUksVUFBVSxDQUFDLEVBQUUsQ0FBQztJQUNoQywrREFBK0Q7SUFDL0QsVUFBVSxDQUFDLFFBQVEsR0FBRyxFQUFFLGVBQWUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQzNELENBQUMifQ==
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opentdf/ctl",
|
|
3
|
+
"version": "0.1.0-beta.1701",
|
|
4
|
+
"description": "Node based CLI for opentdf",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/opentdf/web-sdk.git",
|
|
8
|
+
"directory": "cli"
|
|
9
|
+
},
|
|
10
|
+
"license": "BSD-3-Clause-Clear",
|
|
11
|
+
"author": "Virtru",
|
|
12
|
+
"main": "dist/src/cli.js",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/src/**",
|
|
16
|
+
"bin/opentdf.mjs"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"build:watch": "tsc --watch",
|
|
21
|
+
"prepack": "npm run build",
|
|
22
|
+
"test": "npm run build && mocha dist/**/*.spec.js",
|
|
23
|
+
"watch": "(trap 'kill 0' SIGINT; npm run build && (npm run build:watch & npm run test -- --watch))",
|
|
24
|
+
"format": "prettier --write \"{src,tests}/**/*.ts\"",
|
|
25
|
+
"license-check": "license-checker-rseidelsohn --production --onlyAllow 'Apache-2.0; BSD; CC-BY-4.0; ISC; MIT'",
|
|
26
|
+
"lint": "eslint ./{src,tests}/**/*.ts"
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"opentdf": "./bin/opentdf.mjs"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@esm-bundle/chai": "4.3.4-fix.0",
|
|
33
|
+
"@types/mocha": "10.0.9",
|
|
34
|
+
"@types/node": "^22.9.0",
|
|
35
|
+
"@types/readable-stream": "^4.0.18",
|
|
36
|
+
"@types/sinon": "^17.0.3",
|
|
37
|
+
"@types/yargs": "^17.0.33",
|
|
38
|
+
"@typescript-eslint/eslint-plugin": "^6.2.1",
|
|
39
|
+
"@typescript-eslint/parser": "^6.2.1",
|
|
40
|
+
"chai": "^5.1.2",
|
|
41
|
+
"eslint": "^8.9.0",
|
|
42
|
+
"eslint-config-prettier": "^8.9.0",
|
|
43
|
+
"license-checker-rseidelsohn": "^4.4.2",
|
|
44
|
+
"mocha": "^10.8.2",
|
|
45
|
+
"prettier": "^3.3.3",
|
|
46
|
+
"sinon": "^19.0.2",
|
|
47
|
+
"ts-node": "^10.9.2",
|
|
48
|
+
"typescript": "^5.1.6"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@opentdf/sdk": "^0.1.0-beta.1701",
|
|
52
|
+
"yargs": "^17.7.2"
|
|
53
|
+
}
|
|
54
|
+
}
|