fix(jd): publish Guanghu router runtime source
This commit is contained in:
parent
e82a377b58
commit
e2bb573a58
14 changed files with 1492 additions and 73 deletions
162
server-tools/lake-lamp-authz/guanghu-router.test.js
Normal file
162
server-tools/lake-lamp-authz/guanghu-router.test.js
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
"use strict";
|
||||
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
const crypto = require("node:crypto");
|
||||
const {
|
||||
GuanghuRouter,
|
||||
canonicalApproval,
|
||||
canonicalConnect,
|
||||
workorderDigest,
|
||||
} = require("./guanghu-router");
|
||||
|
||||
function registeredDevice() {
|
||||
const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
|
||||
const publicJwk = publicKey.export({ format: "jwk" });
|
||||
return {
|
||||
device: {
|
||||
device_id: "HL-BS-MAC-001",
|
||||
owner_id: "owner",
|
||||
label: "冰朔的 HoloLake",
|
||||
public_key: publicJwk.x,
|
||||
enabled: true,
|
||||
},
|
||||
privateKey,
|
||||
};
|
||||
}
|
||||
|
||||
function signedConnect(router, device, privateKey, now) {
|
||||
const challenge = router.challenge(device.device_id, now);
|
||||
assert.equal(challenge.ok, true);
|
||||
const signature = crypto.sign(
|
||||
null,
|
||||
Buffer.from(canonicalConnect({
|
||||
deviceId: device.device_id,
|
||||
challengeId: challenge.challengeId,
|
||||
nonce: challenge.nonce,
|
||||
clientTimestamp: now,
|
||||
})),
|
||||
privateKey,
|
||||
).toString("base64url");
|
||||
return router.authorizeConnection({
|
||||
deviceId: device.device_id,
|
||||
challengeId: challenge.challengeId,
|
||||
clientTimestamp: now,
|
||||
signature,
|
||||
}, now);
|
||||
}
|
||||
|
||||
test("only a registered device with a valid signature receives a one-time route token", () => {
|
||||
const { device, privateKey } = registeredDevice();
|
||||
const router = new GuanghuRouter({ devices: [device] });
|
||||
assert.deepEqual(router.challenge("unknown-device", 1_000), {
|
||||
ok: false,
|
||||
reason: "device_not_registered",
|
||||
});
|
||||
|
||||
const challenge = router.challenge(device.device_id, 1_000);
|
||||
const rejected = router.authorizeConnection({
|
||||
deviceId: device.device_id,
|
||||
challengeId: challenge.challengeId,
|
||||
clientTimestamp: 1_000,
|
||||
signature: "invalid",
|
||||
}, 1_000);
|
||||
assert.equal(rejected.ok, false);
|
||||
assert.equal(rejected.reason, "device_signature_invalid");
|
||||
|
||||
const authorized = signedConnect(router, device, privateKey, 1_001);
|
||||
assert.equal(authorized.ok, true);
|
||||
assert.match(authorized.routeToken, /^[A-Za-z0-9_-]{40,}$/);
|
||||
assert.equal(router.isApproverOnline("owner"), false);
|
||||
});
|
||||
|
||||
test("the open transport is the online fact and closing it makes the device offline", () => {
|
||||
const { device, privateKey } = registeredDevice();
|
||||
const router = new GuanghuRouter({ devices: [device] });
|
||||
const authorized = signedConnect(router, device, privateKey, 2_000);
|
||||
const events = [];
|
||||
const opened = router.open(authorized.routeToken, event => events.push(event), 2_001);
|
||||
|
||||
assert.equal(opened.ok, true);
|
||||
assert.equal(opened.state, "online");
|
||||
assert.equal(router.isApproverOnline("owner"), true);
|
||||
assert.equal(events[0].type, "router.connected");
|
||||
assert.equal(events[0].receipt.state, "online");
|
||||
assert.equal(router.open(authorized.routeToken, () => {}, 2_002).reason, "route_token_not_found");
|
||||
|
||||
opened.close(2_003);
|
||||
assert.equal(router.isApproverOnline("owner"), false);
|
||||
assert.equal(events.at(-1).type, "router.closed");
|
||||
assert.equal(events.at(-1).receipt.state, "offline");
|
||||
});
|
||||
|
||||
test("authorization cards travel through the already-open route", () => {
|
||||
const { device, privateKey } = registeredDevice();
|
||||
const router = new GuanghuRouter({ devices: [device] });
|
||||
const authorized = signedConnect(router, device, privateKey, 3_000);
|
||||
const events = [];
|
||||
router.open(authorized.routeToken, event => events.push(event), 3_001);
|
||||
const order = {
|
||||
id: "203e12af-f821-4b62-b80f-b3d73df05161",
|
||||
persona: { pid: "ICE-GL-ZY001", name: "铸渊" },
|
||||
target: "JD-FD-PRIMARY",
|
||||
scope: "server-login",
|
||||
action: "read-navigation-map",
|
||||
allowed_actions: ["read-navigation-map", "inspect-services"],
|
||||
description: "进入第五域",
|
||||
resource: "",
|
||||
createdAt: 3_000,
|
||||
expiresAt: 4_000,
|
||||
state: "pending",
|
||||
};
|
||||
assert.equal(router.deliver("owner", order), 1);
|
||||
const card = events.at(-1);
|
||||
assert.equal(card.type, "authorization.requested");
|
||||
assert.equal(card.workorder.id, order.id);
|
||||
assert.equal(card.digest, workorderDigest(order));
|
||||
});
|
||||
|
||||
test("the bound device signs the exact authorization card digest", () => {
|
||||
const { device, privateKey } = registeredDevice();
|
||||
const router = new GuanghuRouter({ devices: [device] });
|
||||
const authorized = signedConnect(router, device, privateKey, 4_000);
|
||||
router.open(authorized.routeToken, () => {}, 4_001);
|
||||
const order = {
|
||||
id: "203e12af-f821-4b62-b80f-b3d73df05161",
|
||||
persona: { pid: "ICE-GL-ZY001", name: "铸渊" },
|
||||
target: "JD-FD-PRIMARY",
|
||||
scope: "server-login",
|
||||
action: "read-navigation-map",
|
||||
allowed_actions: ["read-navigation-map", "inspect-services"],
|
||||
description: "进入第五域",
|
||||
resource: "",
|
||||
createdAt: 4_000,
|
||||
expiresAt: 5_000,
|
||||
state: "pending",
|
||||
};
|
||||
const digest = workorderDigest(order);
|
||||
const signature = crypto.sign(
|
||||
null,
|
||||
Buffer.from(canonicalApproval({
|
||||
deviceId: device.device_id,
|
||||
workorderId: order.id,
|
||||
digest,
|
||||
})),
|
||||
privateKey,
|
||||
).toString("base64url");
|
||||
|
||||
const verified = router.verifyApproval(
|
||||
device.device_id,
|
||||
order,
|
||||
signature,
|
||||
);
|
||||
assert.equal(verified.ok, true);
|
||||
assert.equal(verified.authorizerId, "owner");
|
||||
assert.equal(verified.deviceId, device.device_id);
|
||||
|
||||
const changed = { ...order, action: "inspect-services" };
|
||||
assert.equal(
|
||||
router.verifyApproval(device.device_id, changed, signature).reason,
|
||||
"device_signature_invalid",
|
||||
);
|
||||
});
|
||||
Loading…
Reference in a new issue