Source commit: 01875e88a3e25379c309489f9f057dd97c0d37de Public tree identity: sha256:8f37a1aa0cc8f408975daf9cabbe193f8f4c169c6d25e8795e67a3ed5083c76b
99 lines
2.4 KiB
JavaScript
99 lines
2.4 KiB
JavaScript
const crypto = require("crypto");
|
|
|
|
const { nodeIdentity, signedRequestPayloadDigest } = require("./node-signing");
|
|
|
|
function agentIdentity(seedPrefix, agent) {
|
|
const identity = nodeIdentity(seedPrefix, agent);
|
|
return {
|
|
...identity,
|
|
publicKeyFingerprint: `sha256:${crypto
|
|
.createHash("sha256")
|
|
.update(identity.publicKey)
|
|
.digest("hex")}`,
|
|
};
|
|
}
|
|
|
|
function agentWorkflowSignatureMessage({
|
|
tenant,
|
|
project,
|
|
agent,
|
|
requestKind,
|
|
process: processId,
|
|
task = "",
|
|
payloadDigest,
|
|
nonce,
|
|
issuedAtEpochSeconds,
|
|
}) {
|
|
const parts = [
|
|
"clusterflux-agent-workflow-signature:v2",
|
|
tenant,
|
|
project,
|
|
agent,
|
|
requestKind,
|
|
processId,
|
|
task,
|
|
payloadDigest,
|
|
nonce,
|
|
String(issuedAtEpochSeconds),
|
|
];
|
|
return Buffer.concat(
|
|
parts.flatMap((part) => [
|
|
Buffer.from(`${Buffer.byteLength(part)}:`),
|
|
Buffer.from(part),
|
|
Buffer.from("\n"),
|
|
])
|
|
);
|
|
}
|
|
|
|
function signedAgentWorkflowProof(identity, request, options = {}) {
|
|
const nonce =
|
|
options.nonce ||
|
|
`${request.type}-${process.pid}-${Date.now()}-${crypto
|
|
.randomBytes(8)
|
|
.toString("hex")}`;
|
|
const issuedAtEpochSeconds =
|
|
options.issuedAtEpochSeconds || Math.floor(Date.now() / 1000);
|
|
const processId =
|
|
request.type === "launch_task" ? request.task_spec?.process : request.process;
|
|
const task =
|
|
request.type === "launch_task" ? request.task_spec?.task_instance : request.task || "";
|
|
const signature = crypto.sign(
|
|
null,
|
|
agentWorkflowSignatureMessage({
|
|
tenant: request.tenant,
|
|
project: request.project,
|
|
agent: request.actor_agent,
|
|
requestKind: request.type,
|
|
process: processId,
|
|
task,
|
|
payloadDigest: signedRequestPayloadDigest(request),
|
|
nonce,
|
|
issuedAtEpochSeconds,
|
|
}),
|
|
identity.privateKeyObject
|
|
);
|
|
return {
|
|
nonce,
|
|
issued_at_epoch_seconds: issuedAtEpochSeconds,
|
|
signature: `ed25519:${signature.toString("base64")}`,
|
|
};
|
|
}
|
|
|
|
function signedAgentWorkflowRequest(identity, request, options = {}) {
|
|
const unsignedRequest = {
|
|
...request,
|
|
agent_public_key_fingerprint:
|
|
options.publicKeyFingerprint || identity.publicKeyFingerprint,
|
|
};
|
|
return {
|
|
...unsignedRequest,
|
|
agent_signature: signedAgentWorkflowProof(identity, unsignedRequest, options),
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
agentIdentity,
|
|
agentWorkflowSignatureMessage,
|
|
signedAgentWorkflowProof,
|
|
signedAgentWorkflowRequest,
|
|
};
|