@bedrock/kms-http 14.5.0 → 15.0.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/README.md +3 -3
- package/lib/BedrockKeystoreConfigStorage.js +1 -3
- package/lib/helpers.js +14 -11
- package/lib/http.js +8 -10
- package/lib/metering.js +3 -3
- package/lib/middleware.js +13 -15
- package/package.json +21 -16
- package/schemas/bedrock-kms-http.js +1 -1
- package/.eslintrc.cjs +0 -12
- package/.github/workflows/main.yml +0 -77
- package/CHANGELOG.md +0 -386
- package/test/mocha/.eslintrc +0 -9
- package/test/mocha/10-keystore.js +0 -670
- package/test/mocha/11-keystore-kms-client.js +0 -242
- package/test/mocha/20-revocation.js +0 -545
- package/test/mocha/21-revocation-ip-allow-list.js +0 -143
- package/test/mocha/30-operations-generate-key.js +0 -180
- package/test/mocha/31-operations-hmac.js +0 -176
- package/test/mocha/helpers.js +0 -163
- package/test/mocha/mock.data.js +0 -40
- package/test/package.json +0 -64
- package/test/test.config.js +0 -36
- package/test/test.js +0 -31
- package/test/web/.eslintrc +0 -9
- package/test/web/10-api.js +0 -108
- package/test/web/helpers.js +0 -84
|
@@ -1,545 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import * as helpers from './helpers.js';
|
|
5
|
-
import {httpsAgent} from '@bedrock/https-agent';
|
|
6
|
-
import {createRequire} from 'node:module';
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
8
|
-
const {CapabilityAgent, KmsClient, KeystoreAgent} =
|
|
9
|
-
require('@digitalbazaar/webkms-client');
|
|
10
|
-
|
|
11
|
-
const ZCAP_ROOT_PREFIX = 'urn:zcap:root:';
|
|
12
|
-
|
|
13
|
-
describe('revocations API', () => {
|
|
14
|
-
let aliceCapabilityAgent;
|
|
15
|
-
let aliceKeystoreAgent;
|
|
16
|
-
let bobCapabilityAgent;
|
|
17
|
-
let carolCapabilityAgent;
|
|
18
|
-
let diegoCapabilityAgent;
|
|
19
|
-
|
|
20
|
-
before(async () => {
|
|
21
|
-
const secret = '40762a17-1696-428f-a2b2-ddf9fe9b4987';
|
|
22
|
-
const handle = 'alice';
|
|
23
|
-
aliceCapabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
24
|
-
|
|
25
|
-
const {id: keystoreId} = await helpers.createKeystore(
|
|
26
|
-
{capabilityAgent: aliceCapabilityAgent});
|
|
27
|
-
const kmsClient = new KmsClient({httpsAgent});
|
|
28
|
-
aliceKeystoreAgent = new KeystoreAgent(
|
|
29
|
-
{capabilityAgent: aliceCapabilityAgent, keystoreId, kmsClient});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// generate a capability agent for Bob
|
|
33
|
-
before(async () => {
|
|
34
|
-
const secret = '34f2afd1-34ef-4d46-a998-cdc5462dc0d2';
|
|
35
|
-
const handle = 'bob';
|
|
36
|
-
bobCapabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// generate a capability agent for Carol
|
|
40
|
-
before(async () => {
|
|
41
|
-
const secret = 'ae806cd9-2765-4232-b955-01e1024ac032';
|
|
42
|
-
const handle = 'carol';
|
|
43
|
-
carolCapabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// generate a capability agent for Diego
|
|
47
|
-
before(async () => {
|
|
48
|
-
const secret = 'b9cec27e-59fd-11ec-9567-10bf48838a41';
|
|
49
|
-
const handle = 'diego';
|
|
50
|
-
diegoCapabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('successfully revokes a delegation', async () => {
|
|
54
|
-
// first generate a new key for alice; use a did:key ID for its public ID
|
|
55
|
-
const aliceKey = await aliceKeystoreAgent.generateKey({
|
|
56
|
-
type: 'asymmetric',
|
|
57
|
-
publicAliasTemplate: 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// next, delegate authority to bob to use alice's key
|
|
61
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
62
|
-
encodeURIComponent(aliceKeystoreAgent.keystoreId);
|
|
63
|
-
const bobZcap = await helpers.delegate({
|
|
64
|
-
parentCapability: rootCapability,
|
|
65
|
-
controller: bobCapabilityAgent.id,
|
|
66
|
-
invocationTarget: aliceKey.kmsId,
|
|
67
|
-
allowedAction: 'sign',
|
|
68
|
-
delegator: aliceCapabilityAgent
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Bob now uses his delegated authority to sign a document with Alice's key
|
|
72
|
-
const bobSignedDocument = await helpers.signWithDelegatedKey({
|
|
73
|
-
capability: bobZcap,
|
|
74
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
bobSignedDocument.should.have.property('@context');
|
|
78
|
-
bobSignedDocument.should.have.property('example:foo');
|
|
79
|
-
bobSignedDocument.should.have.property('proof');
|
|
80
|
-
bobSignedDocument.proof.should.have.property('verificationMethod');
|
|
81
|
-
// the document was ultimately signed with alice's key
|
|
82
|
-
bobSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
83
|
-
|
|
84
|
-
// Bob has successfully used alice's key to sign a document!
|
|
85
|
-
|
|
86
|
-
// Bob now delegates the use of Alice's key to Carol
|
|
87
|
-
const carolZcap = await helpers.delegate({
|
|
88
|
-
parentCapability: bobZcap,
|
|
89
|
-
controller: carolCapabilityAgent.id,
|
|
90
|
-
delegator: bobCapabilityAgent
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Bob would then store record of the delegation to Carol in an EDV
|
|
94
|
-
|
|
95
|
-
// demonstrate that Carol can also sign with Alice's key
|
|
96
|
-
const carolSignedDocument = await helpers.signWithDelegatedKey({
|
|
97
|
-
capability: carolZcap,
|
|
98
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
99
|
-
});
|
|
100
|
-
carolSignedDocument.should.have.property('@context');
|
|
101
|
-
carolSignedDocument.should.have.property('example:foo');
|
|
102
|
-
carolSignedDocument.should.have.property('proof');
|
|
103
|
-
carolSignedDocument.proof.should.have.property('verificationMethod');
|
|
104
|
-
// the document was ultimately signed with alice's key
|
|
105
|
-
carolSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
106
|
-
|
|
107
|
-
// Bob now submits a revocation to revoke the capability he gave to Carol.
|
|
108
|
-
|
|
109
|
-
// in practice bob is going to locate the capability he gave to carol
|
|
110
|
-
// by way of bedrock-web-zcap-storage
|
|
111
|
-
|
|
112
|
-
// this adds a revocation for Carol's `sign` capability on Alice's
|
|
113
|
-
// kms system
|
|
114
|
-
await helpers.revokeDelegatedCapability({
|
|
115
|
-
// the `sign` capability that Bob gave to Carol
|
|
116
|
-
capabilityToRevoke: carolZcap,
|
|
117
|
-
// bob is doing the revocation
|
|
118
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// an attempt to revoke the capability again should produce an error
|
|
122
|
-
// that a capability in the chain has already been revoked
|
|
123
|
-
let err;
|
|
124
|
-
try {
|
|
125
|
-
await helpers.revokeDelegatedCapability({
|
|
126
|
-
// the `sign` capability that Bob gave to Carol
|
|
127
|
-
capabilityToRevoke: carolZcap,
|
|
128
|
-
// bob is doing the revocation
|
|
129
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
130
|
-
});
|
|
131
|
-
} catch(e) {
|
|
132
|
-
err = e;
|
|
133
|
-
}
|
|
134
|
-
should.exist(err);
|
|
135
|
-
err.status.should.equal(403);
|
|
136
|
-
should.exist(err.data);
|
|
137
|
-
const {data} = err;
|
|
138
|
-
data.type.should.equal('NotAllowedError');
|
|
139
|
-
|
|
140
|
-
// Bob would then update his delegation record in an EDV to indicate that
|
|
141
|
-
// the delegation is now revoked. This is just a housekeeping measure,
|
|
142
|
-
// Carol's capability is revoked on Alice's system and is no longer valid.
|
|
143
|
-
|
|
144
|
-
// demonstrate that Carol can no longer use Alice's key for signing.
|
|
145
|
-
let result;
|
|
146
|
-
err = null;
|
|
147
|
-
try {
|
|
148
|
-
result = await helpers.signWithDelegatedKey({
|
|
149
|
-
capability: carolZcap,
|
|
150
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
151
|
-
});
|
|
152
|
-
} catch(e) {
|
|
153
|
-
err = e;
|
|
154
|
-
}
|
|
155
|
-
should.not.exist(result);
|
|
156
|
-
should.exist(err);
|
|
157
|
-
should.exist(err.data);
|
|
158
|
-
err.data.type.should.equal('NotAllowedError');
|
|
159
|
-
});
|
|
160
|
-
it('successfully demonstrates self-revocation of a delegation', async () => {
|
|
161
|
-
// first generate a new key for alice; use a did:key ID for its public ID
|
|
162
|
-
const aliceKey = await aliceKeystoreAgent.generateKey({
|
|
163
|
-
type: 'asymmetric',
|
|
164
|
-
publicAliasTemplate: 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// next, delegate authority to bob to use alice's key
|
|
168
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
169
|
-
encodeURIComponent(aliceKeystoreAgent.keystoreId);
|
|
170
|
-
const bobZcap = await helpers.delegate({
|
|
171
|
-
parentCapability: rootCapability,
|
|
172
|
-
controller: bobCapabilityAgent.id,
|
|
173
|
-
invocationTarget: aliceKey.kmsId,
|
|
174
|
-
allowedAction: 'sign',
|
|
175
|
-
delegator: aliceCapabilityAgent
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// Bob now uses his delegated authority to sign a document with Alice's key
|
|
179
|
-
const bobSignedDocument = await helpers.signWithDelegatedKey({
|
|
180
|
-
capability: bobZcap,
|
|
181
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
bobSignedDocument.should.have.property('@context');
|
|
185
|
-
bobSignedDocument.should.have.property('example:foo');
|
|
186
|
-
bobSignedDocument.should.have.property('proof');
|
|
187
|
-
bobSignedDocument.proof.should.have.property('verificationMethod');
|
|
188
|
-
// the document was ultimately signed with alice's key
|
|
189
|
-
bobSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
190
|
-
|
|
191
|
-
// Bob has successfully used alice's key to sign a document!
|
|
192
|
-
|
|
193
|
-
// Bob now delegates the use of Alice's key to Carol
|
|
194
|
-
const carolZcap = await helpers.delegate({
|
|
195
|
-
parentCapability: bobZcap,
|
|
196
|
-
controller: carolCapabilityAgent.id,
|
|
197
|
-
delegator: bobCapabilityAgent
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// Bob would then store record of the delegation to Carol in an EDV
|
|
201
|
-
|
|
202
|
-
// demonstrate that Carol can also sign with Alice's key
|
|
203
|
-
const carolSignedDocument = await helpers.signWithDelegatedKey({
|
|
204
|
-
capability: carolZcap,
|
|
205
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
206
|
-
});
|
|
207
|
-
carolSignedDocument.should.have.property('@context');
|
|
208
|
-
carolSignedDocument.should.have.property('example:foo');
|
|
209
|
-
carolSignedDocument.should.have.property('proof');
|
|
210
|
-
carolSignedDocument.proof.should.have.property('verificationMethod');
|
|
211
|
-
// the document was ultimately signed with alice's key
|
|
212
|
-
carolSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
213
|
-
|
|
214
|
-
// Carol now submits a revocation to revoke her own capability.
|
|
215
|
-
|
|
216
|
-
// this adds a revocation for Carol's `sign` capability on Alice's
|
|
217
|
-
// kms system
|
|
218
|
-
await helpers.revokeDelegatedCapability({
|
|
219
|
-
// the `sign` capability that Bob gave to Carol
|
|
220
|
-
capabilityToRevoke: carolZcap,
|
|
221
|
-
// carol is doing the revocation
|
|
222
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
// an attempt to revoke the capability again should produce an error
|
|
226
|
-
// that a capability in the chain has already been revoked
|
|
227
|
-
let err;
|
|
228
|
-
try {
|
|
229
|
-
await helpers.revokeDelegatedCapability({
|
|
230
|
-
// the `sign` capability that Bob gave to Carol
|
|
231
|
-
capabilityToRevoke: carolZcap,
|
|
232
|
-
// carol is doing the revocation
|
|
233
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
234
|
-
});
|
|
235
|
-
} catch(e) {
|
|
236
|
-
err = e;
|
|
237
|
-
}
|
|
238
|
-
should.exist(err);
|
|
239
|
-
err.status.should.equal(403);
|
|
240
|
-
should.exist(err.data);
|
|
241
|
-
const {data} = err;
|
|
242
|
-
data.type.should.equal('NotAllowedError');
|
|
243
|
-
|
|
244
|
-
// demonstrate that Carol can no longer use Alice's key for signing.
|
|
245
|
-
let result;
|
|
246
|
-
err = null;
|
|
247
|
-
try {
|
|
248
|
-
result = await helpers.signWithDelegatedKey({
|
|
249
|
-
capability: carolZcap,
|
|
250
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
251
|
-
});
|
|
252
|
-
} catch(e) {
|
|
253
|
-
err = e;
|
|
254
|
-
}
|
|
255
|
-
should.not.exist(result);
|
|
256
|
-
should.exist(err);
|
|
257
|
-
should.exist(err.data);
|
|
258
|
-
err.data.type.should.equal('NotAllowedError');
|
|
259
|
-
});
|
|
260
|
-
it('stops an unauthorized party from revoking a delegation', async () => {
|
|
261
|
-
// first generate a new key for alice; use a did:key ID for its public ID
|
|
262
|
-
const aliceKey = await aliceKeystoreAgent.generateKey({
|
|
263
|
-
type: 'asymmetric',
|
|
264
|
-
publicAliasTemplate: 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
// next, delegate authority to bob to use alice's key
|
|
268
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
269
|
-
encodeURIComponent(aliceKeystoreAgent.keystoreId);
|
|
270
|
-
const bobZcap = await helpers.delegate({
|
|
271
|
-
parentCapability: rootCapability,
|
|
272
|
-
controller: bobCapabilityAgent.id,
|
|
273
|
-
invocationTarget: aliceKey.kmsId,
|
|
274
|
-
allowedAction: 'sign',
|
|
275
|
-
delegator: aliceCapabilityAgent
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
// Bob now uses his delegated authority to sign a document with Alice's key
|
|
279
|
-
const bobSignedDocument = await helpers.signWithDelegatedKey({
|
|
280
|
-
capability: bobZcap,
|
|
281
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
bobSignedDocument.should.have.property('@context');
|
|
285
|
-
bobSignedDocument.should.have.property('example:foo');
|
|
286
|
-
bobSignedDocument.should.have.property('proof');
|
|
287
|
-
bobSignedDocument.proof.should.have.property('verificationMethod');
|
|
288
|
-
// the document was ultimately signed with alice's key
|
|
289
|
-
bobSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
290
|
-
|
|
291
|
-
// Bob has successfully used alice's key to sign a document!
|
|
292
|
-
|
|
293
|
-
// Bob now delegates the use of Alice's key to Carol
|
|
294
|
-
const carolZcap = await helpers.delegate({
|
|
295
|
-
parentCapability: bobZcap,
|
|
296
|
-
controller: carolCapabilityAgent.id,
|
|
297
|
-
delegator: bobCapabilityAgent
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// Bob would then store record of the delegation to Carol in an EDV
|
|
301
|
-
|
|
302
|
-
// demonstrate that Carol can also sign with Alice's key
|
|
303
|
-
const carolSignedDocument = await helpers.signWithDelegatedKey({
|
|
304
|
-
capability: carolZcap,
|
|
305
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
306
|
-
});
|
|
307
|
-
carolSignedDocument.should.have.property('@context');
|
|
308
|
-
carolSignedDocument.should.have.property('example:foo');
|
|
309
|
-
carolSignedDocument.should.have.property('proof');
|
|
310
|
-
carolSignedDocument.proof.should.have.property('verificationMethod');
|
|
311
|
-
// the document was ultimately signed with alice's key
|
|
312
|
-
carolSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
313
|
-
|
|
314
|
-
// Diego now erroneously trys to revoke Carol's zcap
|
|
315
|
-
let err;
|
|
316
|
-
try {
|
|
317
|
-
await helpers.revokeDelegatedCapability({
|
|
318
|
-
// the `sign` capability that Bob gave to Carol
|
|
319
|
-
capabilityToRevoke: carolZcap,
|
|
320
|
-
// diego is doing the revocation
|
|
321
|
-
invocationSigner: diegoCapabilityAgent.getSigner()
|
|
322
|
-
});
|
|
323
|
-
} catch(e) {
|
|
324
|
-
err = e;
|
|
325
|
-
}
|
|
326
|
-
should.exist(err);
|
|
327
|
-
err.status.should.equal(403);
|
|
328
|
-
should.exist(err.data);
|
|
329
|
-
const {data} = err;
|
|
330
|
-
data.type.should.equal('NotAllowedError');
|
|
331
|
-
});
|
|
332
|
-
it('successfully revokes a delegation with a deeper chain', async () => {
|
|
333
|
-
// first generate a new key for alice; use a did:key ID for its public ID
|
|
334
|
-
const aliceKey = await aliceKeystoreAgent.generateKey({
|
|
335
|
-
type: 'asymmetric',
|
|
336
|
-
publicAliasTemplate: 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
// next, delegate authority to bob to use alice's key
|
|
340
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
341
|
-
encodeURIComponent(aliceKeystoreAgent.keystoreId);
|
|
342
|
-
const bobZcap = await helpers.delegate({
|
|
343
|
-
parentCapability: rootCapability,
|
|
344
|
-
controller: bobCapabilityAgent.id,
|
|
345
|
-
invocationTarget: aliceKey.kmsId,
|
|
346
|
-
allowedAction: 'sign',
|
|
347
|
-
delegator: aliceCapabilityAgent
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
// Bob now uses his delegated authority to sign a document with Alice's key
|
|
351
|
-
const bobSignedDocument = await helpers.signWithDelegatedKey({
|
|
352
|
-
capability: bobZcap,
|
|
353
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
bobSignedDocument.should.have.property('@context');
|
|
357
|
-
bobSignedDocument.should.have.property('example:foo');
|
|
358
|
-
bobSignedDocument.should.have.property('proof');
|
|
359
|
-
bobSignedDocument.proof.should.have.property('verificationMethod');
|
|
360
|
-
// the document was ultimately signed with alice's key
|
|
361
|
-
bobSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
362
|
-
|
|
363
|
-
// Bob has successfully used alice's key to sign a document!
|
|
364
|
-
|
|
365
|
-
// Bob now delegates the use of Alice's key to Carol
|
|
366
|
-
const carolZcap = await helpers.delegate({
|
|
367
|
-
parentCapability: bobZcap,
|
|
368
|
-
controller: carolCapabilityAgent.id,
|
|
369
|
-
delegator: bobCapabilityAgent
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
// Bob would then store record of the delegation to Carol in an EDV
|
|
373
|
-
|
|
374
|
-
// demonstrate that Carol can also sign with Alice's key
|
|
375
|
-
const carolSignedDocument = await helpers.signWithDelegatedKey({
|
|
376
|
-
capability: carolZcap,
|
|
377
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
378
|
-
});
|
|
379
|
-
carolSignedDocument.should.have.property('@context');
|
|
380
|
-
carolSignedDocument.should.have.property('example:foo');
|
|
381
|
-
carolSignedDocument.should.have.property('proof');
|
|
382
|
-
carolSignedDocument.proof.should.have.property('verificationMethod');
|
|
383
|
-
// the document was ultimately signed with alice's key
|
|
384
|
-
carolSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
385
|
-
|
|
386
|
-
// Carol now delegates the use of Alice's key to Diego
|
|
387
|
-
const diegoZcap = await helpers.delegate({
|
|
388
|
-
parentCapability: carolZcap,
|
|
389
|
-
controller: diegoCapabilityAgent.id,
|
|
390
|
-
delegator: carolCapabilityAgent
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
// Carol now submits a revocation to revoke the capability she gave to
|
|
394
|
-
// Diego.
|
|
395
|
-
|
|
396
|
-
// in practice carol is going to locate the capability she gave to diego
|
|
397
|
-
// by way of bedrock-web-zcap-storage
|
|
398
|
-
|
|
399
|
-
// this adds a revocation for Diego's `sign` capability on Alice's
|
|
400
|
-
// kms system
|
|
401
|
-
await helpers.revokeDelegatedCapability({
|
|
402
|
-
// the `sign` capability that Carol gave to Diego
|
|
403
|
-
capabilityToRevoke: diegoZcap,
|
|
404
|
-
// carol is doing the revocation
|
|
405
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
// an attempt to revoke the capability again should produce an error
|
|
409
|
-
// that a capability in the chain has already been revoked
|
|
410
|
-
let err;
|
|
411
|
-
try {
|
|
412
|
-
await helpers.revokeDelegatedCapability({
|
|
413
|
-
// the `sign` capability that Carol gave to Diego
|
|
414
|
-
capabilityToRevoke: diegoZcap,
|
|
415
|
-
// carol is doing the revocation
|
|
416
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
417
|
-
});
|
|
418
|
-
} catch(e) {
|
|
419
|
-
err = e;
|
|
420
|
-
}
|
|
421
|
-
should.exist(err);
|
|
422
|
-
err.status.should.equal(403);
|
|
423
|
-
should.exist(err.data);
|
|
424
|
-
const {data} = err;
|
|
425
|
-
data.type.should.equal('NotAllowedError');
|
|
426
|
-
|
|
427
|
-
// Carol would then update her delegation record in an EDV to indicate that
|
|
428
|
-
// the delegation is now revoked. This is just a housekeeping measure,
|
|
429
|
-
// Diego's capability is revoked on Alice's system and is no longer valid.
|
|
430
|
-
|
|
431
|
-
// demonstrate that Diego can no longer use Alice's key for signing.
|
|
432
|
-
let result;
|
|
433
|
-
err = null;
|
|
434
|
-
try {
|
|
435
|
-
result = await helpers.signWithDelegatedKey({
|
|
436
|
-
capability: diegoZcap,
|
|
437
|
-
invocationSigner: diegoCapabilityAgent.getSigner()
|
|
438
|
-
});
|
|
439
|
-
} catch(e) {
|
|
440
|
-
err = e;
|
|
441
|
-
}
|
|
442
|
-
should.not.exist(result);
|
|
443
|
-
should.exist(err);
|
|
444
|
-
should.exist(err.data);
|
|
445
|
-
err.data.type.should.equal('NotAllowedError');
|
|
446
|
-
});
|
|
447
|
-
it('throws error on zcap that was not properly delegated', async () => {
|
|
448
|
-
// first generate a new key for alice; use a did:key ID for its public ID
|
|
449
|
-
const aliceKey = await aliceKeystoreAgent.generateKey({
|
|
450
|
-
type: 'asymmetric',
|
|
451
|
-
publicAliasTemplate: 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
// next, delegate authority to bob to use alice's key
|
|
455
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
456
|
-
encodeURIComponent(aliceKeystoreAgent.keystoreId);
|
|
457
|
-
const bobZcap = await helpers.delegate({
|
|
458
|
-
parentCapability: rootCapability,
|
|
459
|
-
controller: bobCapabilityAgent.id,
|
|
460
|
-
invocationTarget: aliceKey.kmsId,
|
|
461
|
-
allowedAction: 'sign',
|
|
462
|
-
delegator: aliceCapabilityAgent
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
// Alice now DOES NOT sign the capability delegation; Bob is NOT
|
|
466
|
-
// allowed to `sign` with her key.
|
|
467
|
-
// this is simulated by deleting the proof on bob's zcap
|
|
468
|
-
delete bobZcap.proof;
|
|
469
|
-
|
|
470
|
-
// Bob now delegates the use of Alice's key to Carol
|
|
471
|
-
const carolZcap = await helpers.delegate({
|
|
472
|
-
parentCapability: bobZcap,
|
|
473
|
-
controller: carolCapabilityAgent.id,
|
|
474
|
-
delegator: bobCapabilityAgent,
|
|
475
|
-
purposeOptions: {
|
|
476
|
-
// since `bobZcap` is intentionally not signed, we must disable local
|
|
477
|
-
// validation to allow bad zcap to be created so it can be tested by
|
|
478
|
-
// the verifier and manually specify the capability chain
|
|
479
|
-
_skipLocalValidationForTesting: true,
|
|
480
|
-
_capabilityChain: [
|
|
481
|
-
bobZcap.parentCapability,
|
|
482
|
-
bobZcap
|
|
483
|
-
]
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
let err;
|
|
488
|
-
try {
|
|
489
|
-
await helpers.revokeDelegatedCapability({
|
|
490
|
-
// the `sign` capability that Bob gave to Carol
|
|
491
|
-
capabilityToRevoke: carolZcap,
|
|
492
|
-
// bob is doing the revocation
|
|
493
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
494
|
-
});
|
|
495
|
-
} catch(e) {
|
|
496
|
-
err = e;
|
|
497
|
-
}
|
|
498
|
-
should.exist(err);
|
|
499
|
-
err.data.type.should.equal('NotAllowedError');
|
|
500
|
-
});
|
|
501
|
-
it('throws error on zcap validator', async () => {
|
|
502
|
-
// first generate a new key for alice; use a did:key ID for its public ID
|
|
503
|
-
const aliceKey = await aliceKeystoreAgent.generateKey({
|
|
504
|
-
type: 'asymmetric',
|
|
505
|
-
publicAliasTemplate: 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
// next, delegate authority to bob to use alice's key
|
|
509
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
510
|
-
encodeURIComponent(aliceKeystoreAgent.keystoreId);
|
|
511
|
-
const bobZcap = await helpers.delegate({
|
|
512
|
-
parentCapability: rootCapability,
|
|
513
|
-
controller: bobCapabilityAgent.id,
|
|
514
|
-
invocationTarget: aliceKey.kmsId,
|
|
515
|
-
allowedAction: 'sign',
|
|
516
|
-
delegator: aliceCapabilityAgent
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
// Bob now delegates the use of Alice's key to Carol
|
|
520
|
-
const carolZcap = await helpers.delegate({
|
|
521
|
-
parentCapability: bobZcap,
|
|
522
|
-
controller: carolCapabilityAgent.id,
|
|
523
|
-
delegator: bobCapabilityAgent
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
// now remove `proof` from carol's zcap to create a validation error
|
|
527
|
-
delete carolZcap.proof;
|
|
528
|
-
|
|
529
|
-
let err;
|
|
530
|
-
try {
|
|
531
|
-
await helpers.revokeDelegatedCapability({
|
|
532
|
-
// the `sign` capability that Bob gave to Carol
|
|
533
|
-
capabilityToRevoke: carolZcap,
|
|
534
|
-
// bob is doing the revocation
|
|
535
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
536
|
-
});
|
|
537
|
-
} catch(e) {
|
|
538
|
-
err = e;
|
|
539
|
-
}
|
|
540
|
-
should.exist(err);
|
|
541
|
-
err.data.type.should.equal('ValidationError');
|
|
542
|
-
err.data.message.should.equal(
|
|
543
|
-
'A validation error occured in the \'delegatedZcap\' validator.');
|
|
544
|
-
});
|
|
545
|
-
});
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import * as helpers from './helpers.js';
|
|
5
|
-
import {httpsAgent} from '@bedrock/https-agent';
|
|
6
|
-
import {createRequire} from 'node:module';
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
8
|
-
const {CapabilityAgent, KmsClient, KeystoreAgent} =
|
|
9
|
-
require('@digitalbazaar/webkms-client');
|
|
10
|
-
|
|
11
|
-
const ZCAP_ROOT_PREFIX = 'urn:zcap:root:';
|
|
12
|
-
|
|
13
|
-
describe('revocations API with ipAllowList', () => {
|
|
14
|
-
let aliceCapabilityAgent;
|
|
15
|
-
let aliceKeystoreConfig;
|
|
16
|
-
let aliceKeystoreAgent;
|
|
17
|
-
let bobCapabilityAgent;
|
|
18
|
-
let carolCapabilityAgent;
|
|
19
|
-
|
|
20
|
-
before(async () => {
|
|
21
|
-
const secret = '40762a17-1696-428f-a2b2-ddf9fe9b4987';
|
|
22
|
-
const handle = 'alice';
|
|
23
|
-
aliceCapabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
24
|
-
|
|
25
|
-
aliceKeystoreConfig = await helpers.createKeystore(
|
|
26
|
-
{capabilityAgent: aliceCapabilityAgent});
|
|
27
|
-
const kmsClient = new KmsClient({httpsAgent});
|
|
28
|
-
aliceKeystoreAgent = new KeystoreAgent({
|
|
29
|
-
capabilityAgent: aliceCapabilityAgent,
|
|
30
|
-
keystoreId: aliceKeystoreConfig.id,
|
|
31
|
-
kmsClient,
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// generate a capability agent for Bob
|
|
36
|
-
before(async () => {
|
|
37
|
-
const secret = '34f2afd1-34ef-4d46-a998-cdc5462dc0d2';
|
|
38
|
-
const handle = 'bob';
|
|
39
|
-
bobCapabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
// generate a capability agent for Carol
|
|
43
|
-
before(async () => {
|
|
44
|
-
const secret = 'ae806cd9-2765-4232-b955-01e1024ac032';
|
|
45
|
-
const handle = 'carol';
|
|
46
|
-
carolCapabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('returns NotAllowedError for invalid source IP', async () => {
|
|
50
|
-
// first generate a new key for alice; use a did:key ID for its public ID
|
|
51
|
-
const aliceKey = await aliceKeystoreAgent.generateKey({
|
|
52
|
-
type: 'asymmetric',
|
|
53
|
-
publicAliasTemplate: 'did:key:{publicKeyMultibase}#${publicKeyMultibase}'
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// next, delegate authority to bob to use alice's key
|
|
57
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
58
|
-
encodeURIComponent(aliceKeystoreAgent.keystoreId);
|
|
59
|
-
const bobZcap = await helpers.delegate({
|
|
60
|
-
parentCapability: rootCapability,
|
|
61
|
-
controller: bobCapabilityAgent.id,
|
|
62
|
-
invocationTarget: aliceKey.kmsId,
|
|
63
|
-
allowedAction: 'sign',
|
|
64
|
-
delegator: aliceCapabilityAgent
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// Bob now uses his delegated authority to sign a document with Alice's key
|
|
68
|
-
const bobSignedDocument = await helpers.signWithDelegatedKey({
|
|
69
|
-
capability: bobZcap,
|
|
70
|
-
// bob signs the invocation to use alice's key (and alice's key will
|
|
71
|
-
// sign the document)
|
|
72
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
bobSignedDocument.should.have.property('@context');
|
|
76
|
-
bobSignedDocument.should.have.property('example:foo');
|
|
77
|
-
bobSignedDocument.should.have.property('proof');
|
|
78
|
-
bobSignedDocument.proof.should.have.property('verificationMethod');
|
|
79
|
-
// the document was ultimately signed with alice's key
|
|
80
|
-
bobSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
81
|
-
|
|
82
|
-
// Bob has successfully used alice's key to sign a document!
|
|
83
|
-
|
|
84
|
-
// Bob now delegates the use of Alice's key to Carol
|
|
85
|
-
const carolZcap = await helpers.delegate({
|
|
86
|
-
parentCapability: bobZcap,
|
|
87
|
-
controller: carolCapabilityAgent.id,
|
|
88
|
-
delegator: bobCapabilityAgent
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// Bob would then store record of the delegation to Carol in an EDV
|
|
92
|
-
|
|
93
|
-
// demonstrate that Carol can also sign with Alice's key
|
|
94
|
-
const carolSignedDocument = await helpers.signWithDelegatedKey({
|
|
95
|
-
capability: carolZcap,
|
|
96
|
-
// carol signs the invocation to use alice's key (and alice's key
|
|
97
|
-
// will sign the document)
|
|
98
|
-
invocationSigner: carolCapabilityAgent.getSigner()
|
|
99
|
-
});
|
|
100
|
-
carolSignedDocument.should.have.property('@context');
|
|
101
|
-
carolSignedDocument.should.have.property('example:foo');
|
|
102
|
-
carolSignedDocument.should.have.property('proof');
|
|
103
|
-
carolSignedDocument.proof.should.have.property('verificationMethod');
|
|
104
|
-
// the document was ultimately signed with alice's key
|
|
105
|
-
carolSignedDocument.proof.verificationMethod.should.equal(aliceKey.id);
|
|
106
|
-
|
|
107
|
-
// update Alice's keystore config to include ipAllowList
|
|
108
|
-
aliceKeystoreConfig.sequence++;
|
|
109
|
-
aliceKeystoreConfig.ipAllowList = ['8.8.8.8/32'];
|
|
110
|
-
|
|
111
|
-
const {config} = await aliceKeystoreAgent.updateConfig(
|
|
112
|
-
{config: aliceKeystoreConfig});
|
|
113
|
-
config.should.eql(aliceKeystoreConfig);
|
|
114
|
-
|
|
115
|
-
// Bob now submits a revocation to revoke the capability he gave to Carol.
|
|
116
|
-
|
|
117
|
-
// in practice bob is going to locate the capability he gave to carol
|
|
118
|
-
// by way of bedrock-web-zcap-storage
|
|
119
|
-
|
|
120
|
-
// this adds a revocation for Carol's `sign` capability on Alice's
|
|
121
|
-
// kms system
|
|
122
|
-
|
|
123
|
-
// this request should fails because the request does not originate from
|
|
124
|
-
// an IP in the `ipAllowList` on Alice's keystore.
|
|
125
|
-
let err;
|
|
126
|
-
let result;
|
|
127
|
-
try {
|
|
128
|
-
result = await helpers.revokeDelegatedCapability({
|
|
129
|
-
// the `sign` capability that Bob gave to Carol
|
|
130
|
-
capabilityToRevoke: carolZcap,
|
|
131
|
-
// bob is revoking the capability he gave to carol
|
|
132
|
-
invocationSigner: bobCapabilityAgent.getSigner()
|
|
133
|
-
});
|
|
134
|
-
} catch(e) {
|
|
135
|
-
err = e;
|
|
136
|
-
}
|
|
137
|
-
should.not.exist(result);
|
|
138
|
-
should.exist(err);
|
|
139
|
-
err.status.should.equal(403);
|
|
140
|
-
err.data.type.should.equal('NotAllowedError');
|
|
141
|
-
err.data.message.should.contain('Source IP');
|
|
142
|
-
});
|
|
143
|
-
});
|