guanghu-ice-heart/server-tools/lake-lamp-authz/guanghu-router.test.js

162 lines
5.3 KiB
JavaScript
Raw Normal View History

"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",
);
});