@ratelkey/burrow-sdk 0.1.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 +108 -0
- package/dist/cjs/Burrow.js +30 -0
- package/dist/cjs/Burrow.js.map +1 -0
- package/dist/cjs/BurrowClient.js +110 -0
- package/dist/cjs/BurrowClient.js.map +1 -0
- package/dist/cjs/Errors.js +80 -0
- package/dist/cjs/Errors.js.map +1 -0
- package/dist/cjs/Identity.js +274 -0
- package/dist/cjs/Identity.js.map +1 -0
- package/dist/cjs/Model.js +143 -0
- package/dist/cjs/Model.js.map +1 -0
- package/dist/cjs/Signer.js +42 -0
- package/dist/cjs/Signer.js.map +1 -0
- package/dist/cjs/Tls.js +85 -0
- package/dist/cjs/Tls.js.map +1 -0
- package/dist/cjs/Transport.js +198 -0
- package/dist/cjs/Transport.js.map +1 -0
- package/dist/cjs/index.js +28 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/esm/Burrow.d.ts +59 -0
- package/dist/esm/Burrow.d.ts.map +1 -0
- package/dist/esm/Burrow.js +27 -0
- package/dist/esm/Burrow.js.map +1 -0
- package/dist/esm/BurrowClient.d.ts +40 -0
- package/dist/esm/BurrowClient.d.ts.map +1 -0
- package/dist/esm/BurrowClient.js +106 -0
- package/dist/esm/BurrowClient.js.map +1 -0
- package/dist/esm/Errors.d.ts +57 -0
- package/dist/esm/Errors.d.ts.map +1 -0
- package/dist/esm/Errors.js +67 -0
- package/dist/esm/Errors.js.map +1 -0
- package/dist/esm/Identity.d.ts +62 -0
- package/dist/esm/Identity.d.ts.map +1 -0
- package/dist/esm/Identity.js +269 -0
- package/dist/esm/Identity.js.map +1 -0
- package/dist/esm/Model.d.ts +75 -0
- package/dist/esm/Model.d.ts.map +1 -0
- package/dist/esm/Model.js +137 -0
- package/dist/esm/Model.js.map +1 -0
- package/dist/esm/Signer.d.ts +19 -0
- package/dist/esm/Signer.d.ts.map +1 -0
- package/dist/esm/Signer.js +39 -0
- package/dist/esm/Signer.js.map +1 -0
- package/dist/esm/Tls.d.ts +71 -0
- package/dist/esm/Tls.d.ts.map +1 -0
- package/dist/esm/Tls.js +79 -0
- package/dist/esm/Tls.js.map +1 -0
- package/dist/esm/Transport.d.ts +29 -0
- package/dist/esm/Transport.d.ts.map +1 -0
- package/dist/esm/Transport.js +195 -0
- package/dist/esm/Transport.js.map +1 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/package.json +1 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProjectAccess = exports.SecretCoordinate = exports.Secret = void 0;
|
|
4
|
+
const Errors_js_1 = require("./Errors.js");
|
|
5
|
+
/**
|
|
6
|
+
* A secret read from a Burrow — fetched whole in a single signed call. Project it locally (no re-fetch):
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const db = await burrow.getSecret("payments/prod/DATABASE");
|
|
10
|
+
* db.value; // a single-value secret
|
|
11
|
+
* db.toMap(); // every field as name → value
|
|
12
|
+
* db.getField("password"); // one field
|
|
13
|
+
* const [user, pass] = db.getFields("username", "password"); // in order — destructures
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* A shape mismatch (e.g. `value` on a structured secret, or `toMap()` on a single one) throws
|
|
17
|
+
* {@link SecretShapeException}; a missing field throws {@link FieldNotFoundException}.
|
|
18
|
+
*/
|
|
19
|
+
class Secret {
|
|
20
|
+
name;
|
|
21
|
+
singleValue;
|
|
22
|
+
singleType;
|
|
23
|
+
singleVersion;
|
|
24
|
+
fieldsByName;
|
|
25
|
+
constructor(
|
|
26
|
+
/** The secret's name (the final segment of its `project/env/NAME` coordinate). */
|
|
27
|
+
name, singleValue, singleType, singleVersion, fieldsByName) {
|
|
28
|
+
this.name = name;
|
|
29
|
+
this.singleValue = singleValue;
|
|
30
|
+
this.singleType = singleType;
|
|
31
|
+
this.singleVersion = singleVersion;
|
|
32
|
+
this.fieldsByName = fieldsByName;
|
|
33
|
+
}
|
|
34
|
+
/** True when this is a structured (multi-field) secret rather than a single value. */
|
|
35
|
+
get isStructured() {
|
|
36
|
+
return this.fieldsByName !== null;
|
|
37
|
+
}
|
|
38
|
+
/** The single value. Throws {@link SecretShapeException} if this is a structured secret. */
|
|
39
|
+
get value() {
|
|
40
|
+
if (this.singleValue === null) {
|
|
41
|
+
throw new Errors_js_1.SecretShapeException(`'${this.name}' is a structured secret; use toMap(), getField(), or getFields()`);
|
|
42
|
+
}
|
|
43
|
+
return this.singleValue;
|
|
44
|
+
}
|
|
45
|
+
/** The declared type of a single-value secret; null for a structured one. */
|
|
46
|
+
get type() {
|
|
47
|
+
return this.singleType;
|
|
48
|
+
}
|
|
49
|
+
/** The current version of a single-value secret; null for a structured one. */
|
|
50
|
+
get version() {
|
|
51
|
+
return this.singleVersion;
|
|
52
|
+
}
|
|
53
|
+
/** Every field as a name → value map. Throws {@link SecretShapeException} if this is a single-value secret. */
|
|
54
|
+
toMap() {
|
|
55
|
+
const out = {};
|
|
56
|
+
for (const [name, field] of this.structured())
|
|
57
|
+
out[name] = field.value;
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
/** The typed fields. Throws {@link SecretShapeException} if this is a single-value secret. */
|
|
61
|
+
fields() {
|
|
62
|
+
return [...this.structured().values()];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* One field's value. Throws {@link SecretShapeException} if single-value, or
|
|
66
|
+
* {@link FieldNotFoundException} if absent.
|
|
67
|
+
*/
|
|
68
|
+
getField(field) {
|
|
69
|
+
const f = this.structured();
|
|
70
|
+
const hit = f.get(field);
|
|
71
|
+
if (hit === undefined)
|
|
72
|
+
throw new Errors_js_1.FieldNotFoundException(this.name, field, f.keys());
|
|
73
|
+
return hit.value;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The named fields' values, in the order given — for destructuring:
|
|
77
|
+
* `const [user, pass] = secret.getFields("username", "password")`. Throws {@link SecretShapeException} if
|
|
78
|
+
* single-value, or {@link FieldNotFoundException} if any name is absent.
|
|
79
|
+
*/
|
|
80
|
+
getFields(...names) {
|
|
81
|
+
const f = this.structured();
|
|
82
|
+
return names.map((n) => {
|
|
83
|
+
const hit = f.get(n);
|
|
84
|
+
if (hit === undefined)
|
|
85
|
+
throw new Errors_js_1.FieldNotFoundException(this.name, n, f.keys());
|
|
86
|
+
return hit.value;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
structured() {
|
|
90
|
+
if (this.fieldsByName === null) {
|
|
91
|
+
throw new Errors_js_1.SecretShapeException(`'${this.name}' is a single-value secret; use value`);
|
|
92
|
+
}
|
|
93
|
+
return this.fieldsByName;
|
|
94
|
+
}
|
|
95
|
+
/** @internal */
|
|
96
|
+
static single(name, value, type, version) {
|
|
97
|
+
return new Secret(name, value, type, version, null);
|
|
98
|
+
}
|
|
99
|
+
/** @internal */
|
|
100
|
+
static structured(name, fields) {
|
|
101
|
+
return new Secret(name, null, null, null, fields);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.Secret = Secret;
|
|
105
|
+
/** A secret this machine can read, addressed by its `project / env / name` coordinate. */
|
|
106
|
+
class SecretCoordinate {
|
|
107
|
+
project;
|
|
108
|
+
environment;
|
|
109
|
+
name;
|
|
110
|
+
constructor(project, environment, name) {
|
|
111
|
+
this.project = project;
|
|
112
|
+
this.environment = environment;
|
|
113
|
+
this.name = name;
|
|
114
|
+
}
|
|
115
|
+
/** The `project/env/NAME` slug form, as the Burrow lists it and `BurrowClient.getSecret` takes it. */
|
|
116
|
+
toString() {
|
|
117
|
+
return `${this.project}/${this.environment}/${this.name}`;
|
|
118
|
+
}
|
|
119
|
+
/** Parse a `project/env/NAME` slug into its parts. */
|
|
120
|
+
static parse(slug) {
|
|
121
|
+
// Split into at most three parts: a secret name may legitimately contain a slash, the coordinate's
|
|
122
|
+
// first two separators may not.
|
|
123
|
+
const first = slug.indexOf("/");
|
|
124
|
+
if (first < 0)
|
|
125
|
+
return new SecretCoordinate(slug, "", "");
|
|
126
|
+
const second = slug.indexOf("/", first + 1);
|
|
127
|
+
if (second < 0)
|
|
128
|
+
return new SecretCoordinate(slug.slice(0, first), slug.slice(first + 1), "");
|
|
129
|
+
return new SecretCoordinate(slug.slice(0, first), slug.slice(first + 1, second), slug.slice(second + 1));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.SecretCoordinate = SecretCoordinate;
|
|
133
|
+
/** A project this machine can read, and the environment categories it holds a grant for. */
|
|
134
|
+
class ProjectAccess {
|
|
135
|
+
project;
|
|
136
|
+
categories;
|
|
137
|
+
constructor(project, categories) {
|
|
138
|
+
this.project = project;
|
|
139
|
+
this.categories = categories;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.ProjectAccess = ProjectAccess;
|
|
143
|
+
//# sourceMappingURL=Model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Model.js","sourceRoot":"","sources":["../../src/Model.ts"],"names":[],"mappings":";;;AAAA,2CAA2E;AAS3E;;;;;;;;;;;;;GAaG;AACH,MAAa,MAAM;IAGN;IACQ;IACA;IACA;IACA;IANnB;IACE,kFAAkF;IACzE,IAAY,EACJ,WAA0B,EAC1B,UAAyB,EACzB,aAA4B,EAC5B,YAAqD;QAJ7D,SAAI,GAAJ,IAAI,CAAQ;QACJ,gBAAW,GAAX,WAAW,CAAe;QAC1B,eAAU,GAAV,UAAU,CAAe;QACzB,kBAAa,GAAb,aAAa,CAAe;QAC5B,iBAAY,GAAZ,YAAY,CAAyC;IACrE,CAAC;IAEJ,sFAAsF;IACtF,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC;IACpC,CAAC;IAED,4FAA4F;IAC5F,IAAI,KAAK;QACP,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,gCAAoB,CAC5B,IAAI,IAAI,CAAC,IAAI,mEAAmE,CACjF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,6EAA6E;IAC7E,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,+EAA+E;IAC/E,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,+GAA+G;IAC/G,KAAK;QACH,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACvE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,8FAA8F;IAC9F,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,KAAa;QACpB,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,SAAS;YAAE,MAAM,IAAI,kCAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACpF,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,GAAG,KAAe;QAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACrB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,GAAG,KAAK,SAAS;gBAAE,MAAM,IAAI,kCAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAChF,OAAO,GAAG,CAAC,KAAK,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,UAAU;QAChB,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/B,MAAM,IAAI,gCAAoB,CAAC,IAAI,IAAI,CAAC,IAAI,uCAAuC,CAAC,CAAC;QACvF,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,gBAAgB;IAChB,MAAM,CAAC,MAAM,CAAC,IAAY,EAAE,KAAa,EAAE,IAAY,EAAE,OAAe;QACtE,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,gBAAgB;IAChB,MAAM,CAAC,UAAU,CAAC,IAAY,EAAE,MAAwC;QACtE,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;CACF;AAxFD,wBAwFC;AAED,0FAA0F;AAC1F,MAAa,gBAAgB;IAEhB;IACA;IACA;IAHX,YACW,OAAe,EACf,WAAmB,EACnB,IAAY;QAFZ,YAAO,GAAP,OAAO,CAAQ;QACf,gBAAW,GAAX,WAAW,CAAQ;QACnB,SAAI,GAAJ,IAAI,CAAQ;IACpB,CAAC;IAEJ,sGAAsG;IACtG,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5D,CAAC;IAED,sDAAsD;IACtD,MAAM,CAAC,KAAK,CAAC,IAAY;QACvB,mGAAmG;QACnG,gCAAgC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,IAAI,gBAAgB,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAC5C,IAAI,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7F,OAAO,IAAI,gBAAgB,CACzB,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EACpB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,EAC7B,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CACvB,CAAC;IACJ,CAAC;CACF;AA1BD,4CA0BC;AAED,4FAA4F;AAC5F,MAAa,aAAa;IAEb;IACA;IAFX,YACW,OAAe,EACf,UAA6B;QAD7B,YAAO,GAAP,OAAO,CAAQ;QACf,eAAU,GAAV,UAAU,CAAmB;IACrC,CAAC;CACL;AALD,sCAKC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MachineSigner = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
/**
|
|
6
|
+
* Builds the Ed25519-signed `Ratel-*` headers for a machine-plane request. The canonical string MUST
|
|
7
|
+
* byte-match the Burrow's `MachineSignature.canonical`, or every read is rejected 401:
|
|
8
|
+
*
|
|
9
|
+
* ```
|
|
10
|
+
* ACTION \n resource[0] \n … \n resource[n] \n TIMESTAMP \n NONCE \n CLIENT (no trailing newline)
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* TIMESTAMP is unix millis as a decimal string; the SAME string goes in the header and the signed bytes. A
|
|
14
|
+
* fresh timestamp + nonce per call makes a captured request unreplayable (the Burrow enforces a tight
|
|
15
|
+
* timestamp window and a single-use nonce).
|
|
16
|
+
*/
|
|
17
|
+
exports.MachineSigner = {
|
|
18
|
+
canonical(action, resource, timestamp, nonce, client) {
|
|
19
|
+
let out = `${action}\n`;
|
|
20
|
+
for (const part of resource)
|
|
21
|
+
out += `${part}\n`;
|
|
22
|
+
out += `${timestamp}\n${nonce}\n${client}`;
|
|
23
|
+
return Buffer.from(out, "utf8");
|
|
24
|
+
},
|
|
25
|
+
/** The signed `Ratel-*` headers for one request. */
|
|
26
|
+
sign(machineId, key, action, resource, client, nowMillis) {
|
|
27
|
+
const timestamp = String(nowMillis);
|
|
28
|
+
// Standard base64 with padding — the Burrow decodes with java.util.Base64's standard decoder. 16 bytes
|
|
29
|
+
// encodes to 24 characters, well inside the Burrow's 64-character nonce bound.
|
|
30
|
+
const nonce = (0, node_crypto_1.randomBytes)(16).toString("base64");
|
|
31
|
+
// Ed25519 signs the message directly: the digest algorithm must be null, not a hash name.
|
|
32
|
+
const signature = (0, node_crypto_1.sign)(null, exports.MachineSigner.canonical(action, resource, timestamp, nonce, client), key).toString("base64");
|
|
33
|
+
return {
|
|
34
|
+
"Ratel-Machine": machineId,
|
|
35
|
+
"Ratel-Timestamp": timestamp,
|
|
36
|
+
"Ratel-Nonce": nonce,
|
|
37
|
+
"Ratel-Signature": signature,
|
|
38
|
+
"Ratel-Client": client,
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=Signer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Signer.js","sourceRoot":"","sources":["../../src/Signer.ts"],"names":[],"mappings":";;;AAAA,6CAA6E;AAE7E;;;;;;;;;;;GAWG;AACU,QAAA,aAAa,GAAG;IAC3B,SAAS,CACP,MAAc,EACd,QAA2B,EAC3B,SAAiB,EACjB,KAAa,EACb,MAAc;QAEd,IAAI,GAAG,GAAG,GAAG,MAAM,IAAI,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,QAAQ;YAAE,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC;QAChD,GAAG,IAAI,GAAG,SAAS,KAAK,KAAK,KAAK,MAAM,EAAE,CAAC;QAC3C,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,oDAAoD;IACpD,IAAI,CACF,SAAiB,EACjB,GAAc,EACd,MAAc,EACd,QAA2B,EAC3B,MAAc,EACd,SAAiB;QAEjB,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,uGAAuG;QACvG,+EAA+E;QAC/E,MAAM,KAAK,GAAG,IAAA,yBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjD,0FAA0F;QAC1F,MAAM,SAAS,GAAG,IAAA,kBAAS,EACzB,IAAI,EACJ,qBAAa,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,EACnE,GAAG,CACJ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,OAAO;YACL,eAAe,EAAE,SAAS;YAC1B,iBAAiB,EAAE,SAAS;YAC5B,aAAa,EAAE,KAAK;YACpB,iBAAiB,EAAE,SAAS;YAC5B,cAAc,EAAE,MAAM;SACvB,CAAC;IACJ,CAAC;CACF,CAAC"}
|
package/dist/cjs/Tls.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PinStore = exports.TlsMode = void 0;
|
|
4
|
+
exports.publicKeyPin = publicKeyPin;
|
|
5
|
+
exports.fingerprintsEqual = fingerprintsEqual;
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
/** The three trust modes, as values: `TlsMode.Pinned`, `TlsMode.PinnedTo("aa:bb:…")`, `TlsMode.SystemTrust`. */
|
|
10
|
+
exports.TlsMode = {
|
|
11
|
+
Pinned: { kind: "pinned" },
|
|
12
|
+
PinnedTo: (fingerprint) => ({ kind: "pinnedTo", fingerprint }),
|
|
13
|
+
SystemTrust: { kind: "systemTrust" },
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* SHA-256 of a certificate's PUBLIC KEY (its SubjectPublicKeyInfo) as lowercase colon-separated hex — the
|
|
17
|
+
* form the Burrow shows in Settings → Network and carries in a bootstrap code.
|
|
18
|
+
*
|
|
19
|
+
* The key rather than the whole certificate. A Burrow's certificate legitimately changes — a custom domain
|
|
20
|
+
* added to its SANs, an ACME renewal, a refresh — while the Burrow itself is the same one. Pinning the
|
|
21
|
+
* certificate turned each of those into "this is a different server", and a machine that had done nothing
|
|
22
|
+
* wrong stopped being able to read secrets.
|
|
23
|
+
*
|
|
24
|
+
* Parsed through `X509Certificate` and exported as SPKI DER rather than read off `getPeerCertificate().pubkey`,
|
|
25
|
+
* because that field's encoding is not documented to be SPKI and a pin has to hash exactly what the Burrow
|
|
26
|
+
* hashed.
|
|
27
|
+
*/
|
|
28
|
+
function publicKeyPin(der) {
|
|
29
|
+
const spki = new node_crypto_1.X509Certificate(Buffer.from(der)).publicKey.export({ type: "spki", format: "der" });
|
|
30
|
+
const hex = (0, node_crypto_1.createHash)("sha256").update(spki).digest("hex");
|
|
31
|
+
return (hex.match(/../g) ?? []).join(":");
|
|
32
|
+
}
|
|
33
|
+
/** Compare two fingerprints ignoring case and separators, so "AA:BB…" and "aabb…" match. */
|
|
34
|
+
function fingerprintsEqual(a, b) {
|
|
35
|
+
const norm = (s) => s.replace(/[^A-Za-z0-9]/g, "").toLowerCase();
|
|
36
|
+
const na = norm(a);
|
|
37
|
+
return na.length > 0 && na === norm(b);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* One Burrow's pinned key, at `<identity dir>/known_cert`, shared with the `ratel` CLI.
|
|
41
|
+
*
|
|
42
|
+
* Per burrow rather than one map for the machine. The pin and the identity are the same trust relationship:
|
|
43
|
+
* removing a Burrow should forget it entirely, and a shared file left the pin behind for a Burrow that no
|
|
44
|
+
* longer had an identity. It also means two Burrows can never contend for one file.
|
|
45
|
+
*
|
|
46
|
+
* A single value, not a map keyed by URL: the pin is the Burrow's KEY, so the same Burrow reached by its LAN
|
|
47
|
+
* address, its public address or its relay hostname presents the same one.
|
|
48
|
+
*
|
|
49
|
+
* Reads tolerate a missing or unreadable file (treated as unpinned); writes are atomic (temp file + rename)
|
|
50
|
+
* so concurrent SDK/CLI processes can't tear it. A null directory keeps the pin in memory only.
|
|
51
|
+
*/
|
|
52
|
+
class PinStore {
|
|
53
|
+
file;
|
|
54
|
+
constructor(dir) {
|
|
55
|
+
this.file = dir === null ? null : (0, node_path_1.join)(dir, "known_cert");
|
|
56
|
+
}
|
|
57
|
+
read() {
|
|
58
|
+
if (this.file === null)
|
|
59
|
+
return null;
|
|
60
|
+
try {
|
|
61
|
+
return (0, node_fs_1.readFileSync)(this.file, "utf8").trim() || null;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
write(pin) {
|
|
68
|
+
if (this.file === null)
|
|
69
|
+
return;
|
|
70
|
+
if (this.read() === pin)
|
|
71
|
+
return;
|
|
72
|
+
// Best-effort: a read-only home just means the next process re-pins. Never fail a read over it.
|
|
73
|
+
try {
|
|
74
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(this.file), { recursive: true });
|
|
75
|
+
const tmp = `${this.file}.tmp`;
|
|
76
|
+
(0, node_fs_1.writeFileSync)(tmp, `${pin}\n`);
|
|
77
|
+
(0, node_fs_1.renameSync)(tmp, this.file);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// ignored
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.PinStore = PinStore;
|
|
85
|
+
//# sourceMappingURL=Tls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tls.js","sourceRoot":"","sources":["../../src/Tls.ts"],"names":[],"mappings":";;;AA+CA,oCAIC;AAGD,8CAIC;AA1DD,6CAA0D;AAC1D,qCAA6E;AAC7E,yCAA0C;AAyB1C,gHAAgH;AACnG,QAAA,OAAO,GAAG;IACrB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAa;IACrC,QAAQ,EAAE,CAAC,WAAmB,EAAW,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IAC/E,WAAW,EAAE,EAAE,IAAI,EAAE,aAAa,EAAa;CACvC,CAAC;AAEX;;;;;;;;;;;;GAYG;AACH,SAAgB,YAAY,CAAC,GAAe;IAC1C,MAAM,IAAI,GAAG,IAAI,6BAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACrG,MAAM,GAAG,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,4FAA4F;AAC5F,SAAgB,iBAAiB,CAAC,CAAS,EAAE,CAAS;IACpD,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACjF,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACnB,OAAO,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAa,QAAQ;IACF,IAAI,CAAgB;IAErC,YAAY,GAAkB;QAC5B,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACpC,IAAI,CAAC;YACH,OAAO,IAAA,sBAAY,EAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAW;QACf,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO;QAC/B,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO;QAChC,gGAAgG;QAChG,IAAI,CAAC;YACH,IAAA,mBAAS,EAAC,IAAA,mBAAO,EAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,MAAM,CAAC;YAC/B,IAAA,uBAAa,EAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC;YAC/B,IAAA,oBAAU,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,UAAU;QACZ,CAAC;IACH,CAAC;CACF;AA7BD,4BA6BC"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Transport = void 0;
|
|
4
|
+
const node_http_1 = require("node:http");
|
|
5
|
+
const node_net_1 = require("node:net");
|
|
6
|
+
const node_tls_1 = require("node:tls");
|
|
7
|
+
const Errors_js_1 = require("./Errors.js");
|
|
8
|
+
const Tls_js_1 = require("./Tls.js");
|
|
9
|
+
const TIMEOUT_MS = 15_000;
|
|
10
|
+
/**
|
|
11
|
+
* Performs signed machine-plane GETs against one Burrow, applying the configured {@link TlsMode}. Burrows
|
|
12
|
+
* serve HTTPS self-signed by default, so `TlsMode.Pinned` pins the certificate trust-on-first-use and
|
|
13
|
+
* refuses a changed one. Maps the Burrow's HTTP status + `{"error": …}` body to the typed
|
|
14
|
+
* {@link BurrowException}s, and surfaces the Burrow's own rejection reason verbatim.
|
|
15
|
+
*
|
|
16
|
+
* The TLS handshake is completed and the pin checked BEFORE the HTTP request is handed the socket, so a
|
|
17
|
+
* mismatched certificate never sees the signed `Ratel-*` headers. That ordering is the whole point of
|
|
18
|
+
* pinning, and it is why this dials the socket itself rather than letting the HTTP agent do it.
|
|
19
|
+
*/
|
|
20
|
+
class Transport {
|
|
21
|
+
tls;
|
|
22
|
+
base;
|
|
23
|
+
pins;
|
|
24
|
+
/** The fingerprint currently enforced. Null in trust-on-first-use mode until the first pin is learned. */
|
|
25
|
+
pinned;
|
|
26
|
+
constructor(burrowUrl, tls,
|
|
27
|
+
/** This Burrow's identity directory — where its pinned key lives, beside the key that signs for it. */
|
|
28
|
+
identityDir) {
|
|
29
|
+
this.tls = tls;
|
|
30
|
+
this.base = burrowUrl.replace(/\/+$/, "");
|
|
31
|
+
this.pins = new Tls_js_1.PinStore(identityDir);
|
|
32
|
+
this.pinned = tls.kind === "pinnedTo" ? tls.fingerprint : tls.kind === "pinned" ? this.pins.read() : null;
|
|
33
|
+
}
|
|
34
|
+
/** Signed GET, returning the response body on 2xx; throws a typed {@link BurrowException} otherwise. */
|
|
35
|
+
async get(path, headers) {
|
|
36
|
+
const url = this.resolve(path);
|
|
37
|
+
const conn = await this.connect(url);
|
|
38
|
+
let status;
|
|
39
|
+
let body;
|
|
40
|
+
try {
|
|
41
|
+
({ status, body } = await exchange(conn.socket, url, headers));
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
throw new Errors_js_1.BurrowTransportException(`reaching burrow ${this.base}: ${messageOf(e)}`, { cause: e });
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
conn.socket.destroy();
|
|
48
|
+
}
|
|
49
|
+
if (status < 200 || status > 299)
|
|
50
|
+
throw this.errorFor(status, body);
|
|
51
|
+
this.commitPinIfNew(conn.fingerprint);
|
|
52
|
+
return body;
|
|
53
|
+
}
|
|
54
|
+
resolve(path) {
|
|
55
|
+
let url;
|
|
56
|
+
try {
|
|
57
|
+
url = new URL(this.base + path);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
throw new Errors_js_1.BurrowTransportException(`invalid burrow URL '${this.base}${path}': ${messageOf(e)}`, { cause: e });
|
|
61
|
+
}
|
|
62
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
63
|
+
throw new Errors_js_1.BurrowTransportException(`burrow URL '${this.base}' is not http(s)`);
|
|
64
|
+
}
|
|
65
|
+
return url;
|
|
66
|
+
}
|
|
67
|
+
/** Dial the Burrow and, for the pinned modes, verify its certificate before anything is written. */
|
|
68
|
+
connect(url) {
|
|
69
|
+
const host = url.hostname;
|
|
70
|
+
const port = url.port.length > 0 ? Number(url.port) : url.protocol === "https:" ? 443 : 80;
|
|
71
|
+
// Pinning is authoritative for a self-signed Burrow, so the CA chain and hostname checks are waived —
|
|
72
|
+
// the certificate is reached by IP or a self-signed domain that no SAN or CA would match. SystemTrust
|
|
73
|
+
// keeps the full standard verification and needs no pin check of its own.
|
|
74
|
+
const pinning = this.tls.kind !== "systemTrust";
|
|
75
|
+
const socket = url.protocol === "http:"
|
|
76
|
+
? (0, node_net_1.connect)({ host, port })
|
|
77
|
+
: (0, node_tls_1.connect)({
|
|
78
|
+
host,
|
|
79
|
+
port,
|
|
80
|
+
// SNI carries a hostname; an IP literal is not a legal server name.
|
|
81
|
+
...((0, node_net_1.isIP)(host) === 0 ? { servername: host } : {}),
|
|
82
|
+
rejectUnauthorized: !pinning,
|
|
83
|
+
});
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const finish = (settle) => {
|
|
86
|
+
socket.removeListener("error", onError);
|
|
87
|
+
socket.removeListener("timeout", onTimeout);
|
|
88
|
+
socket.removeListener("secureConnect", onSecure);
|
|
89
|
+
socket.removeListener("connect", onPlain);
|
|
90
|
+
socket.setTimeout(0);
|
|
91
|
+
// Hold a no-op error listener so a fault between here and the HTTP client taking the socket over is
|
|
92
|
+
// never an unhandled 'error' event, which would take the process down.
|
|
93
|
+
socket.on("error", ignore);
|
|
94
|
+
settle();
|
|
95
|
+
};
|
|
96
|
+
const onError = (e) => finish(() => reject(new Errors_js_1.BurrowTransportException(`reaching burrow ${this.base}: ${e.message}`, { cause: e })));
|
|
97
|
+
const onTimeout = () => {
|
|
98
|
+
socket.destroy();
|
|
99
|
+
finish(() => reject(new Errors_js_1.BurrowTransportException(`reaching burrow ${this.base}: timed out after ${TIMEOUT_MS}ms`)));
|
|
100
|
+
};
|
|
101
|
+
const onPlain = () => finish(() => resolve({ socket, fingerprint: null }));
|
|
102
|
+
const onSecure = () => {
|
|
103
|
+
if (!pinning) {
|
|
104
|
+
finish(() => resolve({ socket, fingerprint: null }));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const der = socket.getPeerCertificate().raw;
|
|
108
|
+
if (der === undefined || der.length === 0) {
|
|
109
|
+
socket.destroy();
|
|
110
|
+
finish(() => reject(new Errors_js_1.BurrowCertificateException("Burrow presented no certificate")));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const seen = (0, Tls_js_1.publicKeyPin)(der);
|
|
114
|
+
const pin = this.pinned;
|
|
115
|
+
if (pin !== null && !(0, Tls_js_1.fingerprintsEqual)(seen, pin)) {
|
|
116
|
+
socket.destroy();
|
|
117
|
+
finish(() => reject(new Errors_js_1.BurrowCertificateException(`Burrow key does not match the pinned one (pinned=${pin}, got=${seen})`)));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
finish(() => resolve({ socket, fingerprint: seen }));
|
|
121
|
+
};
|
|
122
|
+
socket.setTimeout(TIMEOUT_MS);
|
|
123
|
+
socket.once("timeout", onTimeout);
|
|
124
|
+
socket.once("error", onError);
|
|
125
|
+
if (url.protocol === "https:")
|
|
126
|
+
socket.once("secureConnect", onSecure);
|
|
127
|
+
else
|
|
128
|
+
socket.once("connect", onPlain);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
commitPinIfNew(fingerprint) {
|
|
132
|
+
if (fingerprint === null)
|
|
133
|
+
return;
|
|
134
|
+
if (this.tls.kind !== "pinned")
|
|
135
|
+
return; // only TOFU persists; PinnedTo is caller-fixed, never learned
|
|
136
|
+
if (this.pinned !== null)
|
|
137
|
+
return;
|
|
138
|
+
this.pins.write(fingerprint);
|
|
139
|
+
this.pinned = fingerprint; // enforce on subsequent requests within this process too
|
|
140
|
+
}
|
|
141
|
+
errorFor(status, body) {
|
|
142
|
+
let reason = "";
|
|
143
|
+
try {
|
|
144
|
+
const parsed = JSON.parse(body);
|
|
145
|
+
if (parsed !== null && typeof parsed === "object") {
|
|
146
|
+
const e = parsed.error;
|
|
147
|
+
if (typeof e === "string")
|
|
148
|
+
reason = e;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Not JSON — fall back to the raw body below.
|
|
153
|
+
}
|
|
154
|
+
if (reason.trim().length === 0)
|
|
155
|
+
reason = body.trim().length > 0 ? body.trim() : "(no message)";
|
|
156
|
+
switch (status) {
|
|
157
|
+
case 401:
|
|
158
|
+
return new Errors_js_1.BurrowAuthException(reason);
|
|
159
|
+
case 403:
|
|
160
|
+
return new Errors_js_1.BurrowForbiddenException(reason);
|
|
161
|
+
case 404:
|
|
162
|
+
return new Errors_js_1.BurrowNotFoundException(reason);
|
|
163
|
+
default:
|
|
164
|
+
return new Errors_js_1.BurrowServerException(status, reason);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.Transport = Transport;
|
|
169
|
+
/** Write the GET over an already-connected (and, for HTTPS, already-verified) socket and read the response. */
|
|
170
|
+
function exchange(socket, url, headers) {
|
|
171
|
+
return new Promise((resolve, reject) => {
|
|
172
|
+
const req = (0, node_http_1.request)({
|
|
173
|
+
method: "GET",
|
|
174
|
+
// No agent, and createConnection hands back the socket we already dialled — host/port here only shape
|
|
175
|
+
// the request line, nothing is dialled again.
|
|
176
|
+
createConnection: () => socket,
|
|
177
|
+
host: url.hostname,
|
|
178
|
+
path: url.pathname + url.search,
|
|
179
|
+
headers: { ...headers, Accept: "application/json", Host: url.host },
|
|
180
|
+
});
|
|
181
|
+
req.setTimeout(TIMEOUT_MS, () => req.destroy(new Error(`timed out after ${TIMEOUT_MS}ms`)));
|
|
182
|
+
req.on("error", reject);
|
|
183
|
+
req.on("response", (res) => {
|
|
184
|
+
const chunks = [];
|
|
185
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
186
|
+
res.on("error", reject);
|
|
187
|
+
res.on("end", () => resolve({ status: res.statusCode ?? 0, body: Buffer.concat(chunks).toString("utf8") }));
|
|
188
|
+
});
|
|
189
|
+
req.end();
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function ignore() {
|
|
193
|
+
// Deliberately empty: see the note in Transport.connect.
|
|
194
|
+
}
|
|
195
|
+
function messageOf(e) {
|
|
196
|
+
return e instanceof Error ? e.message : String(e);
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=Transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Transport.js","sourceRoot":"","sources":["../../src/Transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SecretShapeException = exports.FieldNotFoundException = exports.BurrowTransportException = exports.BurrowServerException = exports.BurrowNotFoundException = exports.BurrowIdentityException = exports.BurrowForbiddenException = exports.BurrowException = exports.BurrowCertificateException = exports.BurrowAuthException = exports.TlsMode = exports.MachineIdentity = exports.Identities = exports.SecretCoordinate = exports.Secret = exports.ProjectAccess = exports.SDK_VERSION = exports.DEFAULT_CLIENT_TAG = exports.Burrow = void 0;
|
|
4
|
+
var Burrow_js_1 = require("./Burrow.js");
|
|
5
|
+
Object.defineProperty(exports, "Burrow", { enumerable: true, get: function () { return Burrow_js_1.Burrow; } });
|
|
6
|
+
Object.defineProperty(exports, "DEFAULT_CLIENT_TAG", { enumerable: true, get: function () { return Burrow_js_1.DEFAULT_CLIENT_TAG; } });
|
|
7
|
+
Object.defineProperty(exports, "SDK_VERSION", { enumerable: true, get: function () { return Burrow_js_1.SDK_VERSION; } });
|
|
8
|
+
var Model_js_1 = require("./Model.js");
|
|
9
|
+
Object.defineProperty(exports, "ProjectAccess", { enumerable: true, get: function () { return Model_js_1.ProjectAccess; } });
|
|
10
|
+
Object.defineProperty(exports, "Secret", { enumerable: true, get: function () { return Model_js_1.Secret; } });
|
|
11
|
+
Object.defineProperty(exports, "SecretCoordinate", { enumerable: true, get: function () { return Model_js_1.SecretCoordinate; } });
|
|
12
|
+
var Identity_js_1 = require("./Identity.js");
|
|
13
|
+
Object.defineProperty(exports, "Identities", { enumerable: true, get: function () { return Identity_js_1.Identities; } });
|
|
14
|
+
Object.defineProperty(exports, "MachineIdentity", { enumerable: true, get: function () { return Identity_js_1.MachineIdentity; } });
|
|
15
|
+
var Tls_js_1 = require("./Tls.js");
|
|
16
|
+
Object.defineProperty(exports, "TlsMode", { enumerable: true, get: function () { return Tls_js_1.TlsMode; } });
|
|
17
|
+
var Errors_js_1 = require("./Errors.js");
|
|
18
|
+
Object.defineProperty(exports, "BurrowAuthException", { enumerable: true, get: function () { return Errors_js_1.BurrowAuthException; } });
|
|
19
|
+
Object.defineProperty(exports, "BurrowCertificateException", { enumerable: true, get: function () { return Errors_js_1.BurrowCertificateException; } });
|
|
20
|
+
Object.defineProperty(exports, "BurrowException", { enumerable: true, get: function () { return Errors_js_1.BurrowException; } });
|
|
21
|
+
Object.defineProperty(exports, "BurrowForbiddenException", { enumerable: true, get: function () { return Errors_js_1.BurrowForbiddenException; } });
|
|
22
|
+
Object.defineProperty(exports, "BurrowIdentityException", { enumerable: true, get: function () { return Errors_js_1.BurrowIdentityException; } });
|
|
23
|
+
Object.defineProperty(exports, "BurrowNotFoundException", { enumerable: true, get: function () { return Errors_js_1.BurrowNotFoundException; } });
|
|
24
|
+
Object.defineProperty(exports, "BurrowServerException", { enumerable: true, get: function () { return Errors_js_1.BurrowServerException; } });
|
|
25
|
+
Object.defineProperty(exports, "BurrowTransportException", { enumerable: true, get: function () { return Errors_js_1.BurrowTransportException; } });
|
|
26
|
+
Object.defineProperty(exports, "FieldNotFoundException", { enumerable: true, get: function () { return Errors_js_1.FieldNotFoundException; } });
|
|
27
|
+
Object.defineProperty(exports, "SecretShapeException", { enumerable: true, get: function () { return Errors_js_1.SecretShapeException; } });
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAAsE;AAA7D,mGAAA,MAAM,OAAA;AAAE,+GAAA,kBAAkB,OAAA;AAAE,wGAAA,WAAW,OAAA;AAGhD,uCAAqE;AAA5D,yGAAA,aAAa,OAAA;AAAE,kGAAA,MAAM,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAEhD,6CAA4D;AAAnD,yGAAA,UAAU,OAAA;AAAE,8GAAA,eAAe,OAAA;AACpC,mCAAmC;AAA1B,iGAAA,OAAO,OAAA;AAChB,yCAWqB;AAVnB,gHAAA,mBAAmB,OAAA;AACnB,uHAAA,0BAA0B,OAAA;AAC1B,4GAAA,eAAe,OAAA;AACf,qHAAA,wBAAwB,OAAA;AACxB,oHAAA,uBAAuB,OAAA;AACvB,oHAAA,uBAAuB,OAAA;AACvB,kHAAA,qBAAqB,OAAA;AACrB,qHAAA,wBAAwB,OAAA;AACxB,mHAAA,sBAAsB,OAAA;AACtB,iHAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type BurrowClient } from "./BurrowClient.js";
|
|
2
|
+
import { TlsMode } from "./Tls.js";
|
|
3
|
+
/** The SDK version, reported in the `Ratel-Client` header for the Burrow's audit trail. */
|
|
4
|
+
export declare const SDK_VERSION = "0.1.0";
|
|
5
|
+
/** The default `Ratel-Client` tag. It contains "sdk", so the Burrow classifies reads as the SDK channel. */
|
|
6
|
+
export declare const DEFAULT_CLIENT_TAG = "ratel-sdk-node/0.1.0";
|
|
7
|
+
/** Options common to both ways of opening a client. */
|
|
8
|
+
export interface BurrowOptions {
|
|
9
|
+
/** How to trust the Burrow's TLS certificate. Defaults to `TlsMode.Pinned` (trust-on-first-use). */
|
|
10
|
+
tls?: TlsMode;
|
|
11
|
+
/** The `Ratel-Client` tag recorded against each read. Defaults to {@link DEFAULT_CLIENT_TAG}. */
|
|
12
|
+
clientTag?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Options for {@link Burrow.connect} — an explicit identity, no `~/.burrow` file involved. */
|
|
15
|
+
export interface ConnectOptions extends BurrowOptions {
|
|
16
|
+
burrowUrl: string;
|
|
17
|
+
machineId: string;
|
|
18
|
+
/** The PKCS#8 PEM of the machine's Ed25519 private key. */
|
|
19
|
+
privateKeyPem: string;
|
|
20
|
+
/**
|
|
21
|
+
* The directory a `TlsMode.Pinned` trust-on-first-use pin is written into, as `known_cert`.
|
|
22
|
+
*
|
|
23
|
+
* One directory per Burrow, so an app connecting to two of them must give each its own — a shared
|
|
24
|
+
* directory would have the second overwrite the first's pin. Omitted keeps the pin in memory for the life
|
|
25
|
+
* of the client and writes nothing, which is what a container with no writable state wants; pass
|
|
26
|
+
* `TlsMode.PinnedTo` there instead, so trust does not restart from scratch on every boot.
|
|
27
|
+
*/
|
|
28
|
+
pinStoreDir?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Entry point for reading secrets from a Burrow with a machine identity.
|
|
32
|
+
*
|
|
33
|
+
* A machine is bootstrapped into a Burrow from its Machines page (the `curl | sh` install), which writes an
|
|
34
|
+
* identity under `~/.burrow`. From then on:
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* const burrow = Burrow(); // the one identity on this host
|
|
38
|
+
* const db = await burrow.getSecret("payments/prod/DATABASE");
|
|
39
|
+
* const [user, pass] = db.getFields("username", "password");
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Point it at a specific identity by slug / name / machine id / URL, or by path:
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* Burrow("burrow-a1b2c3d4e5f60718"); // selector
|
|
46
|
+
* Burrow("/home/you/.burrow/burrows/burrow-a1b2c3d4e5f60718"); // path (dir or identity.json)
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* For an app that ships its own key rather than the `~/.burrow` file, use {@link Burrow.connect}.
|
|
50
|
+
*/
|
|
51
|
+
export interface BurrowFactory {
|
|
52
|
+
(target?: string | null, options?: BurrowOptions): BurrowClient;
|
|
53
|
+
/** The default `Ratel-Client` tag. It contains "sdk", so the Burrow classifies reads as the SDK channel. */
|
|
54
|
+
readonly DEFAULT_CLIENT_TAG: string;
|
|
55
|
+
/** Connect with an explicit identity rather than one discovered under `~/.burrow`. */
|
|
56
|
+
connect(options: ConnectOptions): BurrowClient;
|
|
57
|
+
}
|
|
58
|
+
export declare const Burrow: BurrowFactory;
|
|
59
|
+
//# sourceMappingURL=Burrow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Burrow.d.ts","sourceRoot":"","sources":["../../src/Burrow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,2FAA2F;AAC3F,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,4GAA4G;AAC5G,eAAO,MAAM,kBAAkB,yBAAkC,CAAC;AAElE,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,oGAAoG;IACpG,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,+FAA+F;AAC/F,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,aAAa;IAC5B,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAEhE,4GAA4G;IAC5G,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAEpC,sFAAsF;IACtF,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,YAAY,CAAC;CAChD;AAED,eAAO,MAAM,MAAM,EAAE,aAAoE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DefaultBurrowClient } from "./BurrowClient.js";
|
|
2
|
+
import { Identities, parseEd25519PrivateKey } from "./Identity.js";
|
|
3
|
+
import { TlsMode } from "./Tls.js";
|
|
4
|
+
/** The SDK version, reported in the `Ratel-Client` header for the Burrow's audit trail. */
|
|
5
|
+
export const SDK_VERSION = "0.1.0";
|
|
6
|
+
/** The default `Ratel-Client` tag. It contains "sdk", so the Burrow classifies reads as the SDK channel. */
|
|
7
|
+
export const DEFAULT_CLIENT_TAG = `ratel-sdk-node/${SDK_VERSION}`;
|
|
8
|
+
/**
|
|
9
|
+
* Open a client. `target` is one of:
|
|
10
|
+
* - omitted — the single identity on this host (under `~/.burrow`, or `$BURROW_HOME`);
|
|
11
|
+
* - a selector — a burrow slug, name, machine id, or URL;
|
|
12
|
+
* - a filesystem path — a burrow identity directory or an `identity.json` file.
|
|
13
|
+
*/
|
|
14
|
+
function open(target, options = {}) {
|
|
15
|
+
const id = Identities.select(target);
|
|
16
|
+
return new DefaultBurrowClient(id.burrowUrl, id.machineId, id.loadPrivateKey(), options.clientTag ?? DEFAULT_CLIENT_TAG, options.tls ?? TlsMode.Pinned, id.directory);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Connect with an explicit identity — for an app that manages its own key material rather than reading the
|
|
20
|
+
* `~/.burrow` file.
|
|
21
|
+
*/
|
|
22
|
+
function connect(options) {
|
|
23
|
+
const key = parseEd25519PrivateKey(options.privateKeyPem, "provided PEM");
|
|
24
|
+
return new DefaultBurrowClient(options.burrowUrl, options.machineId, key, options.clientTag ?? DEFAULT_CLIENT_TAG, options.tls ?? TlsMode.Pinned, options.pinStoreDir ?? null);
|
|
25
|
+
}
|
|
26
|
+
export const Burrow = Object.assign(open, { DEFAULT_CLIENT_TAG, connect });
|
|
27
|
+
//# sourceMappingURL=Burrow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Burrow.js","sourceRoot":"","sources":["../../src/Burrow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,2FAA2F;AAC3F,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAEnC,4GAA4G;AAC5G,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,WAAW,EAAE,CAAC;AA2BlE;;;;;GAKG;AACH,SAAS,IAAI,CAAC,MAAsB,EAAE,UAAyB,EAAE;IAC/D,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,IAAI,mBAAmB,CAC5B,EAAE,CAAC,SAAS,EACZ,EAAE,CAAC,SAAS,EACZ,EAAE,CAAC,cAAc,EAAE,EACnB,OAAO,CAAC,SAAS,IAAI,kBAAkB,EACvC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAC7B,EAAE,CAAC,SAAS,CACb,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,OAAuB;IACtC,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAC1E,OAAO,IAAI,mBAAmB,CAC5B,OAAO,CAAC,SAAS,EACjB,OAAO,CAAC,SAAS,EACjB,GAAG,EACH,OAAO,CAAC,SAAS,IAAI,kBAAkB,EACvC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAC7B,OAAO,CAAC,WAAW,IAAI,IAAI,CAC5B,CAAC;AACJ,CAAC;AAiCD,MAAM,CAAC,MAAM,MAAM,GAAkB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC"}
|