@bedrock/kms-http 14.5.0 → 16.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 +7 -7
- 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 -8
- 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,180 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import * as helpers from './helpers.js';
|
|
5
|
-
import {httpClient, DEFAULT_HEADERS} from '@digitalbazaar/http-client';
|
|
6
|
-
import {httpsAgent} from '@bedrock/https-agent';
|
|
7
|
-
import {createRequire} from 'node:module';
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
|
-
const {CapabilityAgent, KmsClient, KeystoreAgent} =
|
|
10
|
-
require('@digitalbazaar/webkms-client');
|
|
11
|
-
const {signCapabilityInvocation} = require(
|
|
12
|
-
'@digitalbazaar/http-signature-zcap-invoke');
|
|
13
|
-
|
|
14
|
-
describe('generateKey', () => {
|
|
15
|
-
it('generates a key', async () => {
|
|
16
|
-
const secret = '0628a44e-7599-11ec-989d-10bf48838a41';
|
|
17
|
-
const handle = 'testKey';
|
|
18
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
19
|
-
{handle, secret});
|
|
20
|
-
let err;
|
|
21
|
-
let result;
|
|
22
|
-
try {
|
|
23
|
-
result = await keystoreAgent.generateKey({type: 'hmac'});
|
|
24
|
-
} catch(e) {
|
|
25
|
-
err = e;
|
|
26
|
-
}
|
|
27
|
-
assertNoError(err);
|
|
28
|
-
should.exist(result);
|
|
29
|
-
result.should.include.keys([
|
|
30
|
-
'algorithm', 'capability', 'id', 'type', 'invocationSigner', 'kmsClient'
|
|
31
|
-
]);
|
|
32
|
-
});
|
|
33
|
-
it('generates a key with ipAllowList', async () => {
|
|
34
|
-
// source of requests in the test suite are from 127.0.0.1
|
|
35
|
-
const secret = '22612679-05ce-4ffd-bf58-22b3c4bc1314';
|
|
36
|
-
const handle = 'testKeyAllowList';
|
|
37
|
-
const ipAllowList = ['127.0.0.1/32'];
|
|
38
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
39
|
-
{handle, ipAllowList, secret});
|
|
40
|
-
let err;
|
|
41
|
-
let result;
|
|
42
|
-
try {
|
|
43
|
-
result = await keystoreAgent.generateKey({type: 'hmac'});
|
|
44
|
-
} catch(e) {
|
|
45
|
-
err = e;
|
|
46
|
-
}
|
|
47
|
-
assertNoError(err);
|
|
48
|
-
should.exist(result);
|
|
49
|
-
result.should.include.keys([
|
|
50
|
-
'algorithm', 'capability', 'id', 'type', 'invocationSigner', 'kmsClient'
|
|
51
|
-
]);
|
|
52
|
-
});
|
|
53
|
-
it('generates a key with x-forwarded-for header', async () => {
|
|
54
|
-
// source of requests in the test suite are from 127.0.0.1
|
|
55
|
-
const secret = '22612679-05ce-4ffd-bf58-22b3c4bc1314';
|
|
56
|
-
const handle = 'testKeyAllowList';
|
|
57
|
-
const ipAllowList = ['8.8.8.8/32'];
|
|
58
|
-
const keystoreAgent = await helpers.createKeystoreAgent({
|
|
59
|
-
handle, ipAllowList, secret, kmsClientHeaders: {
|
|
60
|
-
'x-forwarded-for': '8.8.8.8',
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
let err;
|
|
64
|
-
let result;
|
|
65
|
-
try {
|
|
66
|
-
result = await keystoreAgent.generateKey({type: 'hmac'});
|
|
67
|
-
} catch(e) {
|
|
68
|
-
err = e;
|
|
69
|
-
}
|
|
70
|
-
assertNoError(err);
|
|
71
|
-
should.exist(result);
|
|
72
|
-
result.should.include.keys([
|
|
73
|
-
'algorithm', 'capability', 'id', 'type', 'invocationSigner', 'kmsClient'
|
|
74
|
-
]);
|
|
75
|
-
});
|
|
76
|
-
it('generates a key with multiple ipAllowList entries', async () => {
|
|
77
|
-
// source of requests in the test suite are from 127.0.0.1
|
|
78
|
-
const secret = 'efef2772-f7aa-4d25-9eac-6228f2a64b3b';
|
|
79
|
-
const handle = 'testKeyAllowList';
|
|
80
|
-
const ipAllowList = ['8.8.8.8/32', '127.0.0.1/32'];
|
|
81
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
82
|
-
{handle, ipAllowList, secret});
|
|
83
|
-
let err;
|
|
84
|
-
let result;
|
|
85
|
-
try {
|
|
86
|
-
result = await keystoreAgent.generateKey({type: 'hmac'});
|
|
87
|
-
} catch(e) {
|
|
88
|
-
err = e;
|
|
89
|
-
}
|
|
90
|
-
assertNoError(err);
|
|
91
|
-
should.exist(result);
|
|
92
|
-
result.should.include.keys([
|
|
93
|
-
'algorithm', 'capability', 'id', 'type', 'invocationSigner', 'kmsClient'
|
|
94
|
-
]);
|
|
95
|
-
});
|
|
96
|
-
it('returns NotAllowedError for invalid source IP', async () => {
|
|
97
|
-
// source of requests in the test suite are from 127.0.0.1
|
|
98
|
-
const secret = '860a6bc8-74e1-4dfd-b701-7efc2a596e91';
|
|
99
|
-
const handle = 'testKeyAllowList';
|
|
100
|
-
const ipAllowList = ['8.8.8.8/32'];
|
|
101
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
102
|
-
{handle, ipAllowList, secret});
|
|
103
|
-
|
|
104
|
-
let err;
|
|
105
|
-
let result;
|
|
106
|
-
try {
|
|
107
|
-
result = await keystoreAgent.generateKey({type: 'hmac'});
|
|
108
|
-
} catch(e) {
|
|
109
|
-
err = e;
|
|
110
|
-
}
|
|
111
|
-
should.exist(err);
|
|
112
|
-
should.not.exist(result);
|
|
113
|
-
err.status.should.equal(403);
|
|
114
|
-
err.data.type.should.equal('NotAllowedError');
|
|
115
|
-
});
|
|
116
|
-
it('generates a key with "maxCapabilityChainLength=1"', async () => {
|
|
117
|
-
const secret = '0ad59134-7583-11ec-b16e-10bf48838a41';
|
|
118
|
-
const handle = 'testKeyMaxCapabilityChainLength';
|
|
119
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
120
|
-
{handle, secret});
|
|
121
|
-
let err;
|
|
122
|
-
let result;
|
|
123
|
-
try {
|
|
124
|
-
result = await keystoreAgent.generateKey({
|
|
125
|
-
type: 'asymmetric', maxCapabilityChainLength: 1
|
|
126
|
-
});
|
|
127
|
-
} catch(e) {
|
|
128
|
-
err = e;
|
|
129
|
-
}
|
|
130
|
-
assertNoError(err);
|
|
131
|
-
should.exist(result);
|
|
132
|
-
result.should.include.keys([
|
|
133
|
-
'capability', 'id', 'type', 'invocationSigner', 'kmsClient', 'kmsId'
|
|
134
|
-
]);
|
|
135
|
-
});
|
|
136
|
-
}); // generateKey with ipAllowList
|
|
137
|
-
|
|
138
|
-
describe('get public key description', () => {
|
|
139
|
-
it('gets public key description', async () => {
|
|
140
|
-
const secret = '34f2afd1-34ef-4d46-a998-cdc5462dc0d2';
|
|
141
|
-
const handle = 'bobKey';
|
|
142
|
-
const capabilityAgent = await CapabilityAgent.fromSecret(
|
|
143
|
-
{secret, handle});
|
|
144
|
-
const {id: keystoreId} = await helpers.createKeystore(
|
|
145
|
-
{capabilityAgent});
|
|
146
|
-
const kmsClient = new KmsClient({keystoreId, httpsAgent});
|
|
147
|
-
let keystoreAgent;
|
|
148
|
-
try {
|
|
149
|
-
keystoreAgent = new KeystoreAgent(
|
|
150
|
-
{capabilityAgent, keystoreId, kmsClient});
|
|
151
|
-
} catch(e) {
|
|
152
|
-
assertNoError(e);
|
|
153
|
-
}
|
|
154
|
-
const key = await keystoreAgent.generateKey({type: 'asymmetric'});
|
|
155
|
-
|
|
156
|
-
const url = key.id;
|
|
157
|
-
const headers = await signCapabilityInvocation({
|
|
158
|
-
url, method: 'get',
|
|
159
|
-
headers: DEFAULT_HEADERS,
|
|
160
|
-
capability: 'urn:zcap:root:' + encodeURIComponent(url),
|
|
161
|
-
invocationSigner: capabilityAgent.getSigner(),
|
|
162
|
-
capabilityAction: 'read'
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
let err;
|
|
166
|
-
let result;
|
|
167
|
-
try {
|
|
168
|
-
result = await httpClient.get(url, {agent: httpsAgent, headers});
|
|
169
|
-
} catch(e) {
|
|
170
|
-
err = e;
|
|
171
|
-
}
|
|
172
|
-
assertNoError(err);
|
|
173
|
-
should.exist(result);
|
|
174
|
-
result.data.should.include.keys([
|
|
175
|
-
'@context', 'id', 'type', 'publicKeyMultibase', 'controller'
|
|
176
|
-
]);
|
|
177
|
-
result.data.id.should.equal(key.id);
|
|
178
|
-
result.data.type.should.equal(key.type);
|
|
179
|
-
});
|
|
180
|
-
});
|
|
@@ -1,176 +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
|
-
import pMap from 'p-map';
|
|
8
|
-
import uuid from 'uuid-random';
|
|
9
|
-
const require = createRequire(import.meta.url);
|
|
10
|
-
const {CapabilityAgent, Hmac, KmsClient} = require(
|
|
11
|
-
'@digitalbazaar/webkms-client');
|
|
12
|
-
|
|
13
|
-
const ZCAP_ROOT_PREFIX = 'urn:zcap:root:';
|
|
14
|
-
|
|
15
|
-
describe('bedrock-kms-http HMAC operations', () => {
|
|
16
|
-
describe('Sha256HmacKey2019', () => {
|
|
17
|
-
let hmac;
|
|
18
|
-
before(async () => {
|
|
19
|
-
const secret = 'b07e6b31-d910-438e-9a5f-08d945a5f676';
|
|
20
|
-
const handle = 'testKey1';
|
|
21
|
-
const keystoreAgent = await helpers.createKeystoreAgent({handle, secret});
|
|
22
|
-
hmac = await keystoreAgent.generateKey({type: 'hmac'});
|
|
23
|
-
});
|
|
24
|
-
it('successfully signs', async () => {
|
|
25
|
-
const data = new TextEncoder('utf-8').encode('hello');
|
|
26
|
-
let err;
|
|
27
|
-
let result;
|
|
28
|
-
try {
|
|
29
|
-
result = await hmac.sign({data});
|
|
30
|
-
} catch(e) {
|
|
31
|
-
err = e;
|
|
32
|
-
}
|
|
33
|
-
assertNoError(err);
|
|
34
|
-
should.exist(result);
|
|
35
|
-
result.should.be.a('Uint8Array');
|
|
36
|
-
});
|
|
37
|
-
}); // end Sha256HmacKey2019
|
|
38
|
-
|
|
39
|
-
describe('Sha256HmacKey2019 with ipAllowList', () => {
|
|
40
|
-
it('successfully signs', async () => {
|
|
41
|
-
const secret = '22612679-05ce-4ffd-bf58-22b3c4bc1314';
|
|
42
|
-
const handle = 'testKeyAllowList';
|
|
43
|
-
const ipAllowList = ['127.0.0.1/32'];
|
|
44
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
45
|
-
{handle, ipAllowList, secret});
|
|
46
|
-
const hmac = await keystoreAgent.generateKey({type: 'hmac'});
|
|
47
|
-
const data = new TextEncoder('utf-8').encode('hello');
|
|
48
|
-
let err;
|
|
49
|
-
let result;
|
|
50
|
-
try {
|
|
51
|
-
result = await hmac.sign({data});
|
|
52
|
-
} catch(e) {
|
|
53
|
-
err = e;
|
|
54
|
-
}
|
|
55
|
-
assertNoError(err);
|
|
56
|
-
should.exist(result);
|
|
57
|
-
result.should.be.a('Uint8Array');
|
|
58
|
-
});
|
|
59
|
-
it('fails when "maxCapabilityChainLength" is exceeded', async () => {
|
|
60
|
-
const secret = '22612679-05ce-4ffd-bf58-22b3c4bc1314';
|
|
61
|
-
const handle = 'testKeyMaxCapabilityChainLength';
|
|
62
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
63
|
-
{handle, secret});
|
|
64
|
-
const hmac = await keystoreAgent.generateKey({
|
|
65
|
-
type: 'hmac', maxCapabilityChainLength: 1
|
|
66
|
-
});
|
|
67
|
-
const data = new TextEncoder('utf-8').encode('hello');
|
|
68
|
-
|
|
69
|
-
let err;
|
|
70
|
-
let result;
|
|
71
|
-
try {
|
|
72
|
-
result = await hmac.sign({data});
|
|
73
|
-
} catch(e) {
|
|
74
|
-
err = e;
|
|
75
|
-
}
|
|
76
|
-
assertNoError(err);
|
|
77
|
-
should.exist(result);
|
|
78
|
-
result.should.be.a('Uint8Array');
|
|
79
|
-
|
|
80
|
-
// now delegate and try to invoke
|
|
81
|
-
const delegatee = await CapabilityAgent.fromSecret({
|
|
82
|
-
secret: uuid(),
|
|
83
|
-
handle: uuid()
|
|
84
|
-
});
|
|
85
|
-
const rootCapability = ZCAP_ROOT_PREFIX +
|
|
86
|
-
encodeURIComponent(keystoreAgent.keystoreId);
|
|
87
|
-
const delegatedZcap = await helpers.delegate({
|
|
88
|
-
parentCapability: rootCapability,
|
|
89
|
-
controller: delegatee.id,
|
|
90
|
-
invocationTarget: hmac.id,
|
|
91
|
-
allowedAction: 'sign',
|
|
92
|
-
delegator: keystoreAgent.capabilityAgent
|
|
93
|
-
});
|
|
94
|
-
const hmac2 = await Hmac.fromCapability({
|
|
95
|
-
capability: delegatedZcap,
|
|
96
|
-
invocationSigner: delegatee.getSigner(),
|
|
97
|
-
kmsClient: new KmsClient({httpsAgent})
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
let err2;
|
|
101
|
-
let result2;
|
|
102
|
-
try {
|
|
103
|
-
result2 = await hmac2.sign({data});
|
|
104
|
-
} catch(e) {
|
|
105
|
-
err2 = e;
|
|
106
|
-
}
|
|
107
|
-
should.exist(err2);
|
|
108
|
-
should.not.exist(result2);
|
|
109
|
-
should.exist(err2.data);
|
|
110
|
-
err2.data.type.should.equal('NotAllowedError');
|
|
111
|
-
should.exist(err2.data.cause);
|
|
112
|
-
err2.data.cause.message.should.equal(
|
|
113
|
-
'Maximum zcap invocation capability chain length (1) exceeded.');
|
|
114
|
-
});
|
|
115
|
-
it('successfully signs with x-forwarded-for header', async () => {
|
|
116
|
-
const secret = '2726f62d-31bb-4688-b54a-1a0b4e50329f';
|
|
117
|
-
const handle = 'testKeyAllowList';
|
|
118
|
-
const ipAllowList = ['8.8.8.8/32'];
|
|
119
|
-
const keystoreAgent = await helpers.createKeystoreAgent({
|
|
120
|
-
handle, ipAllowList, secret, kmsClientHeaders: {
|
|
121
|
-
'x-forwarded-for': '8.8.8.8',
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
const hmac = await keystoreAgent.generateKey({type: 'hmac'});
|
|
125
|
-
const data = new TextEncoder('utf-8').encode('hello');
|
|
126
|
-
let err;
|
|
127
|
-
let result;
|
|
128
|
-
try {
|
|
129
|
-
result = await hmac.sign({data});
|
|
130
|
-
} catch(e) {
|
|
131
|
-
err = e;
|
|
132
|
-
}
|
|
133
|
-
assertNoError(err);
|
|
134
|
-
should.exist(result);
|
|
135
|
-
result.should.be.a('Uint8Array');
|
|
136
|
-
});
|
|
137
|
-
}); // end Sha256HmacKey2019 with ipAllowList
|
|
138
|
-
|
|
139
|
-
describe('bulk operations', () => {
|
|
140
|
-
const operationCount = 1000;
|
|
141
|
-
const vData = [];
|
|
142
|
-
let hmac;
|
|
143
|
-
|
|
144
|
-
before(async () => {
|
|
145
|
-
const secret = '9b5a0a63-aac2-447c-a60a-8cc79b46418d';
|
|
146
|
-
const handle = 'testKeyBulk';
|
|
147
|
-
const keystoreAgent = await helpers.createKeystoreAgent({handle, secret});
|
|
148
|
-
hmac = await keystoreAgent.generateKey({type: 'hmac'});
|
|
149
|
-
});
|
|
150
|
-
before(async () => {
|
|
151
|
-
for(let i = 0; i < operationCount; ++i) {
|
|
152
|
-
// uuids are 37 chars long, * 30 is ~1KiB
|
|
153
|
-
let v = '';
|
|
154
|
-
for(let n = 0; n < 30; ++n) {
|
|
155
|
-
v += uuid();
|
|
156
|
-
}
|
|
157
|
-
vData.push(new TextEncoder('utf-8').encode(v));
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
it(`performs ${operationCount} signatures`, async function() {
|
|
161
|
-
this.timeout(0);
|
|
162
|
-
let result;
|
|
163
|
-
let err;
|
|
164
|
-
try {
|
|
165
|
-
result = await pMap(
|
|
166
|
-
vData, data => hmac.sign({data}), {concurrency: 30});
|
|
167
|
-
} catch(e) {
|
|
168
|
-
err = e;
|
|
169
|
-
}
|
|
170
|
-
assertNoError(err);
|
|
171
|
-
should.exist(result);
|
|
172
|
-
result.should.be.an('array');
|
|
173
|
-
result.should.have.length(operationCount);
|
|
174
|
-
});
|
|
175
|
-
}); // end bulk operations
|
|
176
|
-
});
|
package/test/mocha/helpers.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import * as bedrock from '@bedrock/core';
|
|
5
|
-
import {createRequire} from 'node:module';
|
|
6
|
-
import {documentLoader} from '@bedrock/jsonld-document-loader';
|
|
7
|
-
import {getAppIdentity} from '@bedrock/app-identity';
|
|
8
|
-
import {httpsAgent} from '@bedrock/https-agent';
|
|
9
|
-
import jsigs from 'jsonld-signatures';
|
|
10
|
-
import uuid from 'uuid-random';
|
|
11
|
-
const require = createRequire(import.meta.url);
|
|
12
|
-
const {AsymmetricKey, CapabilityAgent, KeystoreAgent, KmsClient} =
|
|
13
|
-
require('@digitalbazaar/webkms-client');
|
|
14
|
-
const {
|
|
15
|
-
CapabilityDelegation,
|
|
16
|
-
constants: zcapConstants
|
|
17
|
-
} = require('@digitalbazaar/zcap');
|
|
18
|
-
const {Ed25519Signature2020} = require('@digitalbazaar/ed25519-signature-2020');
|
|
19
|
-
const {ZcapClient} = require('@digitalbazaar/ezcap');
|
|
20
|
-
|
|
21
|
-
const {purposes: {AssertionProofPurpose}} = jsigs;
|
|
22
|
-
const {ZCAP_CONTEXT_URL} = zcapConstants;
|
|
23
|
-
|
|
24
|
-
export async function createMeter({capabilityAgent} = {}) {
|
|
25
|
-
// create signer using the application's capability invocation key
|
|
26
|
-
const {keys: {capabilityInvocationKey}} = getAppIdentity();
|
|
27
|
-
|
|
28
|
-
const zcapClient = new ZcapClient({
|
|
29
|
-
agent: httpsAgent,
|
|
30
|
-
invocationSigner: capabilityInvocationKey.signer(),
|
|
31
|
-
SuiteClass: Ed25519Signature2020
|
|
32
|
-
});
|
|
33
|
-
// create a meter
|
|
34
|
-
const meterService = `${bedrock.config.server.baseUri}/meters`;
|
|
35
|
-
let meter = {
|
|
36
|
-
controller: capabilityAgent.id,
|
|
37
|
-
product: {
|
|
38
|
-
// mock ID for webkms service product
|
|
39
|
-
id: 'urn:uuid:80a82316-e8c2-11eb-9570-10bf48838a41'
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
({data: {meter}} = await zcapClient.write({url: meterService, json: meter}));
|
|
43
|
-
|
|
44
|
-
// return full meter ID
|
|
45
|
-
const {id} = meter;
|
|
46
|
-
return {id: `${meterService}/${id}`};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function createKeystore({
|
|
50
|
-
capabilityAgent, ipAllowList, referenceId, meterId,
|
|
51
|
-
kmsBaseUrl = `${bedrock.config.server.baseUri}/kms`,
|
|
52
|
-
kmsModule = 'ssm-v1',
|
|
53
|
-
}) {
|
|
54
|
-
if(!meterId) {
|
|
55
|
-
// create a meter for the keystore
|
|
56
|
-
({id: meterId} = await createMeter({capabilityAgent}));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// create keystore
|
|
60
|
-
const config = {
|
|
61
|
-
sequence: 0,
|
|
62
|
-
controller: capabilityAgent.id,
|
|
63
|
-
meterId,
|
|
64
|
-
kmsModule
|
|
65
|
-
};
|
|
66
|
-
if(referenceId) {
|
|
67
|
-
config.referenceId = referenceId;
|
|
68
|
-
}
|
|
69
|
-
if(ipAllowList) {
|
|
70
|
-
config.ipAllowList = ipAllowList;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return KmsClient.createKeystore({
|
|
74
|
-
url: `${kmsBaseUrl}/keystores`,
|
|
75
|
-
config,
|
|
76
|
-
invocationSigner: capabilityAgent.getSigner(),
|
|
77
|
-
httpsAgent
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export async function createKeystoreAgent({
|
|
82
|
-
handle, ipAllowList, secret, kmsClientHeaders = {}
|
|
83
|
-
}) {
|
|
84
|
-
const capabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
85
|
-
|
|
86
|
-
let err;
|
|
87
|
-
let keystore;
|
|
88
|
-
try {
|
|
89
|
-
keystore = await createKeystore({capabilityAgent, ipAllowList});
|
|
90
|
-
} catch(e) {
|
|
91
|
-
err = e;
|
|
92
|
-
}
|
|
93
|
-
assertNoError(err);
|
|
94
|
-
|
|
95
|
-
// create kmsClient only required because we need to use httpsAgent
|
|
96
|
-
// that accepts self-signed certs used in test suite
|
|
97
|
-
const kmsClient = new KmsClient(
|
|
98
|
-
{httpsAgent, defaultHeaders: kmsClientHeaders});
|
|
99
|
-
const keystoreAgent = new KeystoreAgent({
|
|
100
|
-
capabilityAgent,
|
|
101
|
-
keystoreId: keystore.id,
|
|
102
|
-
kmsClient
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
return keystoreAgent;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export async function getKeystore({id, capabilityAgent}) {
|
|
109
|
-
const kmsClient = new KmsClient({keystoreId: id, httpsAgent});
|
|
110
|
-
const invocationSigner = capabilityAgent.getSigner();
|
|
111
|
-
return kmsClient.getKeystore({invocationSigner});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export async function delegate({
|
|
115
|
-
parentCapability, controller, invocationTarget, expires, allowedAction,
|
|
116
|
-
delegator, purposeOptions = {}
|
|
117
|
-
}) {
|
|
118
|
-
const newCapability = {
|
|
119
|
-
'@context': ZCAP_CONTEXT_URL,
|
|
120
|
-
id: `urn:zcap:${uuid()}`,
|
|
121
|
-
controller,
|
|
122
|
-
parentCapability: parentCapability.id || parentCapability,
|
|
123
|
-
invocationTarget: invocationTarget || parentCapability.invocationTarget,
|
|
124
|
-
expires: expires || parentCapability.expires ||
|
|
125
|
-
new Date(Date.now() + 5000).toISOString().slice(0, -5) + 'Z',
|
|
126
|
-
allowedAction: allowedAction || parentCapability.allowedAction
|
|
127
|
-
};
|
|
128
|
-
// attach capability delegation proof
|
|
129
|
-
return jsigs.sign(newCapability, {
|
|
130
|
-
documentLoader,
|
|
131
|
-
purpose: new CapabilityDelegation({parentCapability, ...purposeOptions}),
|
|
132
|
-
suite: new Ed25519Signature2020({signer: delegator.getSigner()}),
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export async function revokeDelegatedCapability({
|
|
137
|
-
capabilityToRevoke, invocationSigner
|
|
138
|
-
}) {
|
|
139
|
-
const kmsClient = new KmsClient({httpsAgent});
|
|
140
|
-
await kmsClient.revokeCapability({
|
|
141
|
-
capabilityToRevoke,
|
|
142
|
-
invocationSigner
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export async function signWithDelegatedKey({
|
|
147
|
-
capability, doc, invocationSigner
|
|
148
|
-
}) {
|
|
149
|
-
const delegatedSigningKey = await AsymmetricKey.fromCapability({
|
|
150
|
-
capability,
|
|
151
|
-
invocationSigner,
|
|
152
|
-
kmsClient: new KmsClient({httpsAgent})
|
|
153
|
-
});
|
|
154
|
-
const suite = new Ed25519Signature2020({signer: delegatedSigningKey});
|
|
155
|
-
|
|
156
|
-
doc = doc || {'example:foo': 'test'};
|
|
157
|
-
|
|
158
|
-
return jsigs.sign(doc, {
|
|
159
|
-
documentLoader,
|
|
160
|
-
purpose: new AssertionProofPurpose(),
|
|
161
|
-
suite
|
|
162
|
-
});
|
|
163
|
-
}
|
package/test/mocha/mock.data.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import {createRequire} from 'node:module';
|
|
5
|
-
const require = createRequire(import.meta.url);
|
|
6
|
-
const {constants: zcapConstants} = require('@digitalbazaar/zcap');
|
|
7
|
-
|
|
8
|
-
const {ZCAP_CONTEXT_URL} = zcapConstants;
|
|
9
|
-
|
|
10
|
-
export const mockData = {};
|
|
11
|
-
|
|
12
|
-
const zcaps = mockData.zcaps = {};
|
|
13
|
-
|
|
14
|
-
// Note: This zcap is only used to check JSON schema validators, it does not
|
|
15
|
-
// have valid proofs.
|
|
16
|
-
const zcap0 = {
|
|
17
|
-
'@context': ZCAP_CONTEXT_URL,
|
|
18
|
-
id: 'urn:zcap:z19vWhR8EsNbWqvazp5bg6BTu',
|
|
19
|
-
controller: 'did:key:z6Mkkt1BWYLPAAXwYBwyVHAZkL94tgT8QbQv2SUxeW1U3DaG',
|
|
20
|
-
expires: '2022-01-08T17:27:15Z',
|
|
21
|
-
invocationTarget: 'https://bedrock.localhost:18443/kms' +
|
|
22
|
-
'/keystores/z1AAWWM7Zd4YyyV3NfaCqFuzQ/keys/z19wxodgv1UhrToQMvSxGhQG6',
|
|
23
|
-
parentCapability: 'urn:zcap:root:' + encodeURIComponent(
|
|
24
|
-
'https://bedrock.localhost:18443/kms/keystores/z1AAWWM7Zd4YyyV3NfaCqFuzQ'),
|
|
25
|
-
allowedAction: 'sign',
|
|
26
|
-
proof: {
|
|
27
|
-
type: 'Ed25519Signature2020',
|
|
28
|
-
created: '2020-02-27T21:22:48Z',
|
|
29
|
-
verificationMethod: 'did:key:z6MkkrtV7wnBpXKBtiZjxaSghCo8ttb5kZUJTk8bEwT' +
|
|
30
|
-
'TTYvg#z6MkkrtV7wnBpXKBtiZjxaSghCo8ttb5kZUJTk8bEwTTTYvg',
|
|
31
|
-
proofPurpose: 'capabilityDelegation',
|
|
32
|
-
capabilityChain: [
|
|
33
|
-
'urn:zcap:root:' + encodeURIComponent(
|
|
34
|
-
'https://bedrock.localhost:18443/kms/keystores/z1AAWWM7Zd4YyyV3NfaCqFu')
|
|
35
|
-
],
|
|
36
|
-
proofValue: 'eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19'
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
zcaps.zero = zcap0;
|
package/test/package.json
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "bedrock-kms-http-test",
|
|
3
|
-
"version": "0.0.1-0",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "Bedrock KMS HTTP API test",
|
|
6
|
-
"private": true,
|
|
7
|
-
"scripts": {
|
|
8
|
-
"test": "node --preserve-symlinks test.js test",
|
|
9
|
-
"test:debug": "node --preserve-symlinks test.js test --log-level debug",
|
|
10
|
-
"test-node": "node --preserve-symlinks test.js test --framework mocha",
|
|
11
|
-
"test-karma": "node --preserve-symlinks test.js test --framework karma",
|
|
12
|
-
"coverage": "cross-env NODE_ENV=test c8 --reporter=lcov --reporter=text-summary node --preserve-symlinks test.js test --framework mocha",
|
|
13
|
-
"coverage-ci": "cross-env NODE_ENV=test c8 --reporter=lcovonly node --preserve-symlinks test.js test --framework mocha",
|
|
14
|
-
"coverage-report": "c8 report"
|
|
15
|
-
},
|
|
16
|
-
"dependencies": {
|
|
17
|
-
"@bedrock/app-identity": "^3.0.0",
|
|
18
|
-
"@bedrock/core": "^6.0.0",
|
|
19
|
-
"@bedrock/did-context": "^4.0.0",
|
|
20
|
-
"@bedrock/did-io": "^8.0.0",
|
|
21
|
-
"@bedrock/express": "^8.0.0",
|
|
22
|
-
"@bedrock/https-agent": "^4.0.0",
|
|
23
|
-
"@bedrock/jsonld-document-loader": "^3.0.0",
|
|
24
|
-
"@bedrock/karma": "^4.0.0",
|
|
25
|
-
"@bedrock/kms": "^10.0.0",
|
|
26
|
-
"@bedrock/kms-http": "file:..",
|
|
27
|
-
"@bedrock/ledger-context": "^23.0.0",
|
|
28
|
-
"@bedrock/meter": "^3.0.0",
|
|
29
|
-
"@bedrock/meter-http": "^8.0.0",
|
|
30
|
-
"@bedrock/meter-usage-reporter": "^7.0.0",
|
|
31
|
-
"@bedrock/mongodb": "^10.0.0",
|
|
32
|
-
"@bedrock/package-manager": "^3.0.0",
|
|
33
|
-
"@bedrock/security-context": "^7.0.0",
|
|
34
|
-
"@bedrock/server": "^5.0.0",
|
|
35
|
-
"@bedrock/ssm-mongodb": "^9.0.0",
|
|
36
|
-
"@bedrock/test": "^8.0.0",
|
|
37
|
-
"@bedrock/validation": "^7.0.0",
|
|
38
|
-
"@bedrock/veres-one-context": "^14.0.0",
|
|
39
|
-
"@bedrock/zcap-storage": "^7.0.0",
|
|
40
|
-
"@digitalbazaar/did-method-key": "^2.0.0",
|
|
41
|
-
"@digitalbazaar/ed25519-signature-2020": "^3.0.0",
|
|
42
|
-
"@digitalbazaar/ezcap": "^2.0.0",
|
|
43
|
-
"@digitalbazaar/http-client": "^3.0.1",
|
|
44
|
-
"@digitalbazaar/http-signature-zcap-invoke": "^5.0.1",
|
|
45
|
-
"@digitalbazaar/webkms-client": "^10.0.0",
|
|
46
|
-
"@digitalbazaar/zcap": "^7.0.0",
|
|
47
|
-
"base58-universal": "^1.0.0",
|
|
48
|
-
"c8": "^7.11.0",
|
|
49
|
-
"cross-env": "^7.0.3",
|
|
50
|
-
"jsonld-signatures": "^9.3.0",
|
|
51
|
-
"p-map": "^4.0.0",
|
|
52
|
-
"sinon": "^9.0.2",
|
|
53
|
-
"uuid-random": "^1.3.2"
|
|
54
|
-
},
|
|
55
|
-
"c8": {
|
|
56
|
-
"excludeNodeModules": false,
|
|
57
|
-
"include": [
|
|
58
|
-
"node_modules/@bedrock/kms-http/**"
|
|
59
|
-
],
|
|
60
|
-
"exclude": [
|
|
61
|
-
"node_modules/@bedrock/kms-http/node_modules/**"
|
|
62
|
-
]
|
|
63
|
-
}
|
|
64
|
-
}
|
package/test/test.config.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import {config} from '@bedrock/core';
|
|
5
|
-
import {fileURLToPath} from 'node:url';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
import '@bedrock/https-agent';
|
|
8
|
-
import '@bedrock/kms-http';
|
|
9
|
-
import '@bedrock/mongodb';
|
|
10
|
-
|
|
11
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
|
|
13
|
-
config.mocha.tests.push(path.join(__dirname, 'mocha'));
|
|
14
|
-
|
|
15
|
-
// MongoDB
|
|
16
|
-
config.mongodb.name = 'bedrock_kms_http_test';
|
|
17
|
-
config.mongodb.dropCollections.onInit = true;
|
|
18
|
-
config.mongodb.dropCollections.collections = [];
|
|
19
|
-
|
|
20
|
-
// do not require an authentication session for tests
|
|
21
|
-
config['kms-http'].requireAuthentication = false;
|
|
22
|
-
|
|
23
|
-
// allow self-signed certs in test framework
|
|
24
|
-
config['https-agent'].rejectUnauthorized = false;
|
|
25
|
-
|
|
26
|
-
// configure karma tests
|
|
27
|
-
config.karma.suites['bedrock-web-kms'] = path.join('web', '**', '*.js');
|
|
28
|
-
config.karma.config.proxies = {
|
|
29
|
-
'/': {
|
|
30
|
-
target: 'https://localhost:18443',
|
|
31
|
-
changeOrigin: true
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
config.karma.config.proxyValidateSSL = false;
|
|
35
|
-
config.karma.config.browserNoActivityTimeout = 120000;
|
|
36
|
-
config.karma.config.browserDisconnectTimeout = 120000;
|
package/test/test.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import * as bedrock from '@bedrock/core';
|
|
5
|
-
import '@bedrock/https-agent';
|
|
6
|
-
import '@bedrock/kms';
|
|
7
|
-
import '@bedrock/kms-http';
|
|
8
|
-
import '@bedrock/meter';
|
|
9
|
-
import {handlers} from '@bedrock/meter-http';
|
|
10
|
-
import '@bedrock/meter-usage-reporter';
|
|
11
|
-
import '@bedrock/security-context';
|
|
12
|
-
import '@bedrock/ssm-mongodb';
|
|
13
|
-
import '@bedrock/test';
|
|
14
|
-
import '@bedrock/karma';
|
|
15
|
-
|
|
16
|
-
bedrock.events.on('bedrock.init', async () => {
|
|
17
|
-
/* Handlers need to be added before `bedrock.start` is called. These are
|
|
18
|
-
no-op handlers to enable meter usage without restriction */
|
|
19
|
-
handlers.setCreateHandler({
|
|
20
|
-
handler({meter} = {}) {
|
|
21
|
-
// use configured meter usage reporter as service ID for tests
|
|
22
|
-
meter.serviceId = bedrock.config['app-identity'].seeds.services.webkms.id;
|
|
23
|
-
return {meter};
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
handlers.setUpdateHandler({handler: ({meter} = {}) => ({meter})});
|
|
27
|
-
handlers.setRemoveHandler({handler: ({meter} = {}) => ({meter})});
|
|
28
|
-
handlers.setUseHandler({handler: ({meter} = {}) => ({meter})});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
bedrock.start();
|