@ornncompute/cli 1.0.128 → 1.0.130
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/package.json +1 -1
- package/src/admin-enrollment.mjs +12 -6
- package/vendor/api-client/orchestrator.js +202 -0
- package/vendor/capabilities/cli.js +86 -84
package/package.json
CHANGED
package/src/admin-enrollment.mjs
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
enrollmentTokensPath,
|
|
3
|
+
remoteRunPath,
|
|
4
|
+
listEnrollmentLogs,
|
|
5
|
+
} from "../vendor/api-client/orchestrator.js";
|
|
1
6
|
import { createHash } from "node:crypto";
|
|
2
7
|
import { lstat, readFile } from "node:fs/promises";
|
|
3
8
|
|
|
@@ -477,7 +482,7 @@ function enrollmentProgressTransport(fetch, runtime, privateKey) {
|
|
|
477
482
|
);
|
|
478
483
|
|
|
479
484
|
return async (path, init = {}) => {
|
|
480
|
-
if (path ===
|
|
485
|
+
if (path === enrollmentTokensPath) {
|
|
481
486
|
const minted = await request(path, init);
|
|
482
487
|
if (minted && typeof minted === "object") {
|
|
483
488
|
tokenId = typeof minted.id === "string" ? minted.id : "";
|
|
@@ -491,7 +496,7 @@ function enrollmentProgressTransport(fetch, runtime, privateKey) {
|
|
|
491
496
|
}
|
|
492
497
|
return minted;
|
|
493
498
|
}
|
|
494
|
-
if (path !==
|
|
499
|
+
if (path !== remoteRunPath || !tokenId) return request(path, init);
|
|
495
500
|
|
|
496
501
|
const remote = request(path, init).then(
|
|
497
502
|
(value) => ({ ok: true, value }),
|
|
@@ -502,10 +507,11 @@ function enrollmentProgressTransport(fetch, runtime, privateKey) {
|
|
|
502
507
|
let currentPoll = Promise.resolve();
|
|
503
508
|
const poll = async () => {
|
|
504
509
|
try {
|
|
505
|
-
const payload = await
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
510
|
+
const payload = await listEnrollmentLogs(
|
|
511
|
+
fetch,
|
|
512
|
+
{},
|
|
513
|
+
AbortSignal.timeout(ENROLLMENT_LOG_READ_TIMEOUT_MS)
|
|
514
|
+
);
|
|
509
515
|
const lines = freshEnrollmentLogLines(payload, tokenId, secrets, seen);
|
|
510
516
|
for (const line of lines) runtime.stderr.write(`${line}\n`);
|
|
511
517
|
} catch {
|
|
@@ -640,12 +640,183 @@ function removeControllerVirtualMachine(request, id, virtualMachineId, options)
|
|
|
640
640
|
method: "DELETE"
|
|
641
641
|
});
|
|
642
642
|
}
|
|
643
|
+
|
|
644
|
+
// ../../packages/api-client/dist/orchestrator/enrollment.js
|
|
645
|
+
var enrollmentTokensPath = "/v1/orchestrator/enrollment-tokens";
|
|
646
|
+
var enrollmentLogsPath = "/v1/orchestrator/enrollment-logs";
|
|
647
|
+
function listEnrollmentTokens(request, query = {}) {
|
|
648
|
+
return request(enrollmentTokensPath + (query.id ? `?id=${encodeURIComponent(query.id)}` : ""), {
|
|
649
|
+
method: "GET"
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
function createEnrollmentToken(request, body) {
|
|
653
|
+
return request(enrollmentTokensPath, { method: "POST", body });
|
|
654
|
+
}
|
|
655
|
+
function revokeEnrollmentToken(request, id, idempotencyKey) {
|
|
656
|
+
return request(`${enrollmentTokensPath}/${encodeURIComponent(id)}`, {
|
|
657
|
+
method: "DELETE",
|
|
658
|
+
...idempotencyKey ? { headers: { "Idempotency-Key": idempotencyKey } } : {}
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
function listEnrollmentCompartments(request, signal) {
|
|
662
|
+
return request("/v1/orchestrator/enrollment/compartments", { method: "GET", signal });
|
|
663
|
+
}
|
|
664
|
+
function listEnrollmentScripts(request, organizationId, signal) {
|
|
665
|
+
const query = organizationId ? `?organization_id=${encodeURIComponent(organizationId)}` : "";
|
|
666
|
+
return request(`/v1/orchestrator/enrollment-scripts${query}`, {
|
|
667
|
+
method: "GET",
|
|
668
|
+
signal
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
function getEnrollmentScriptSource(request, id, query = {}, signal) {
|
|
672
|
+
const params = new URLSearchParams();
|
|
673
|
+
if (query.sha256)
|
|
674
|
+
params.set("sha256", query.sha256);
|
|
675
|
+
if (query.filter)
|
|
676
|
+
params.set("filter", query.filter);
|
|
677
|
+
return request(`/v1/orchestrator/enrollment-scripts/${encodeURIComponent(id)}/source${params.size ? `?${params}` : ""}`, { method: "GET", signal });
|
|
678
|
+
}
|
|
679
|
+
function listEnrollmentLogs(request, query = {}, signal) {
|
|
680
|
+
return request(enrollmentLogsPath + (query.organization_id ? `?organization_id=${encodeURIComponent(query.organization_id)}` : ""), { method: "GET", signal });
|
|
681
|
+
}
|
|
682
|
+
function getEnrollmentAdminSshKey(request, nodeId) {
|
|
683
|
+
return request(`/v1/orchestrator/enrollment/admin-ssh-key?node_id=${encodeURIComponent(nodeId)}`, { method: "GET" });
|
|
684
|
+
}
|
|
685
|
+
function rotateEnrollmentAdminSshKey(request, nodeId) {
|
|
686
|
+
return request(`/v1/orchestrator/enrollment/admin-ssh-key?node_id=${encodeURIComponent(nodeId)}`, { method: "POST" });
|
|
687
|
+
}
|
|
688
|
+
function fakeEnroll(fetcher, body) {
|
|
689
|
+
return fetcher("/v1/orchestrator/fake-enroll", {
|
|
690
|
+
method: "POST",
|
|
691
|
+
headers: { "Content-Type": "application/json" },
|
|
692
|
+
body: JSON.stringify(body)
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
function enrollmentInstallPath(query) {
|
|
696
|
+
const params = new URLSearchParams();
|
|
697
|
+
for (const [key, value] of Object.entries(query)) {
|
|
698
|
+
if (value !== void 0 && value !== false)
|
|
699
|
+
params.set(key, String(value));
|
|
700
|
+
}
|
|
701
|
+
return `/v1/orchestrator/enrollment/install?${params}`;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// ../../packages/api-client/dist/orchestrator/configurable-enrollment.js
|
|
705
|
+
var root = "/v1/orchestrator/enrollment/configurable";
|
|
706
|
+
function queryString(query) {
|
|
707
|
+
const params = new URLSearchParams();
|
|
708
|
+
for (const [key, value] of Object.entries(query))
|
|
709
|
+
if (value !== void 0)
|
|
710
|
+
params.set(key, String(value));
|
|
711
|
+
return params.size ? `?${params}` : "";
|
|
712
|
+
}
|
|
713
|
+
function listEnrollmentProfiles(request, query = {}, signal) {
|
|
714
|
+
return request(`${root}/profiles${queryString(query)}`, { method: "GET", signal });
|
|
715
|
+
}
|
|
716
|
+
async function listAllEnrollmentProfiles(request, query = {}, signal) {
|
|
717
|
+
const profiles = [];
|
|
718
|
+
const seen = /* @__PURE__ */ new Set();
|
|
719
|
+
let after = query.after;
|
|
720
|
+
do {
|
|
721
|
+
if (after && seen.has(after))
|
|
722
|
+
throw new Error("Enrollment profile pagination repeated a cursor.");
|
|
723
|
+
if (after)
|
|
724
|
+
seen.add(after);
|
|
725
|
+
const page = await listEnrollmentProfiles(request, { ...query, after }, signal);
|
|
726
|
+
profiles.push(...page.profiles);
|
|
727
|
+
after = page.next_cursor ?? void 0;
|
|
728
|
+
} while (after);
|
|
729
|
+
return { profiles, next_cursor: null };
|
|
730
|
+
}
|
|
731
|
+
function createEnrollmentProfile(request, body) {
|
|
732
|
+
return request(`${root}/profiles`, { method: "POST", body });
|
|
733
|
+
}
|
|
734
|
+
function updateEnrollmentProfile(request, id, body) {
|
|
735
|
+
return request(`${root}/profiles/${encodeURIComponent(id)}`, {
|
|
736
|
+
method: "PATCH",
|
|
737
|
+
body
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
function listEnrollmentRuns(request, query = {}) {
|
|
741
|
+
return request(`${root}/runs${queryString(query)}`, { method: "GET" });
|
|
742
|
+
}
|
|
743
|
+
function getEnrollmentRun(request, id) {
|
|
744
|
+
return request(`${root}/runs/${encodeURIComponent(id)}`, {
|
|
745
|
+
method: "GET"
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
function createEnrollmentRun(request, body) {
|
|
749
|
+
return request(`${root}/runs`, { method: "POST", body });
|
|
750
|
+
}
|
|
751
|
+
function cancelEnrollmentRun(request, id) {
|
|
752
|
+
return request(`${root}/runs/${encodeURIComponent(id)}`, {
|
|
753
|
+
method: "PATCH",
|
|
754
|
+
body: { action: "cancel" }
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
function getEnrollmentHosts(request, id) {
|
|
758
|
+
return request(`${root}/runs/${encodeURIComponent(id)}/hosts`, { method: "GET" });
|
|
759
|
+
}
|
|
760
|
+
function launchEnrollmentRun(request, id, body) {
|
|
761
|
+
return request(`${root}/runs/${encodeURIComponent(id)}/launch`, {
|
|
762
|
+
method: "POST",
|
|
763
|
+
body
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
function getEnrollmentHost(request, id) {
|
|
767
|
+
return request(`${root}/hosts/${encodeURIComponent(id)}`, {
|
|
768
|
+
method: "GET"
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
function actOnEnrollmentHost(request, id, body) {
|
|
772
|
+
return request(`${root}/hosts/${encodeURIComponent(id)}`, {
|
|
773
|
+
method: "PATCH",
|
|
774
|
+
body
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
function issueEnrollmentCredential(request, id) {
|
|
778
|
+
return request(`${root}/hosts/${encodeURIComponent(id)}/credentials`, {
|
|
779
|
+
method: "POST"
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
function getEnrollmentSteps(request, id) {
|
|
783
|
+
return request(`${root}/hosts/${encodeURIComponent(id)}/steps`, { method: "GET" });
|
|
784
|
+
}
|
|
785
|
+
function getEnrollmentStepCatalog(request, organizationId, signal) {
|
|
786
|
+
return request(`${root}/steps${queryString({ organization_id: organizationId })}`, {
|
|
787
|
+
method: "GET",
|
|
788
|
+
signal
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
function getEnrollmentProfileSource(request, id, signal) {
|
|
792
|
+
return request(`${root}/profiles/${encodeURIComponent(id)}/source`, {
|
|
793
|
+
method: "GET",
|
|
794
|
+
signal
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
function getEnrollmentRunSource(request, id, signal) {
|
|
798
|
+
return request(`${root}/runs/${encodeURIComponent(id)}/source`, {
|
|
799
|
+
method: "GET",
|
|
800
|
+
signal
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
function enrollmentHostEventsPath(id, query = {}) {
|
|
804
|
+
return `${root}/hosts/${encodeURIComponent(id)}/events${queryString(query)}`;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// ../../packages/api-client/dist/orchestrator/remote.js
|
|
808
|
+
var remoteRunPath = "/v1/staff/remote";
|
|
809
|
+
function runRemote(request, body) {
|
|
810
|
+
return request(remoteRunPath, { method: "POST", body });
|
|
811
|
+
}
|
|
643
812
|
export {
|
|
813
|
+
actOnEnrollmentHost,
|
|
644
814
|
addControllerNode,
|
|
645
815
|
addControllerVirtualMachine,
|
|
646
816
|
addReservationSshKey,
|
|
647
817
|
assignNode,
|
|
648
818
|
cancelDriveUpload,
|
|
819
|
+
cancelEnrollmentRun,
|
|
649
820
|
clearDriveContents,
|
|
650
821
|
closeShellSession,
|
|
651
822
|
closeVirtualMachinePort,
|
|
@@ -657,6 +828,9 @@ export {
|
|
|
657
828
|
createController,
|
|
658
829
|
createDisk,
|
|
659
830
|
createDrive,
|
|
831
|
+
createEnrollmentProfile,
|
|
832
|
+
createEnrollmentRun,
|
|
833
|
+
createEnrollmentToken,
|
|
660
834
|
createGhostNodes,
|
|
661
835
|
createNetwork,
|
|
662
836
|
createNetworkPeer,
|
|
@@ -678,11 +852,25 @@ export {
|
|
|
678
852
|
driveArchivePath,
|
|
679
853
|
driveFilePath,
|
|
680
854
|
driveFolderArchivePath,
|
|
855
|
+
enrollmentHostEventsPath,
|
|
856
|
+
enrollmentInstallPath,
|
|
857
|
+
enrollmentLogsPath,
|
|
858
|
+
enrollmentTokensPath,
|
|
859
|
+
fakeEnroll,
|
|
681
860
|
geolocate,
|
|
682
861
|
getContainerRegistry,
|
|
683
862
|
getControllerAccess,
|
|
684
863
|
getCurrentShellSession,
|
|
685
864
|
getDrive,
|
|
865
|
+
getEnrollmentAdminSshKey,
|
|
866
|
+
getEnrollmentHost,
|
|
867
|
+
getEnrollmentHosts,
|
|
868
|
+
getEnrollmentProfileSource,
|
|
869
|
+
getEnrollmentRun,
|
|
870
|
+
getEnrollmentRunSource,
|
|
871
|
+
getEnrollmentScriptSource,
|
|
872
|
+
getEnrollmentStepCatalog,
|
|
873
|
+
getEnrollmentSteps,
|
|
686
874
|
getHardwareCatalog,
|
|
687
875
|
getNetwork,
|
|
688
876
|
getNode,
|
|
@@ -698,14 +886,23 @@ export {
|
|
|
698
886
|
getVirtualMachineLogs,
|
|
699
887
|
hardwareCatalogPath,
|
|
700
888
|
importDisk,
|
|
889
|
+
issueEnrollmentCredential,
|
|
701
890
|
issueNodeSshCertificate,
|
|
702
891
|
keepDriveUploadsAlive,
|
|
892
|
+
launchEnrollmentRun,
|
|
703
893
|
launchReservation,
|
|
894
|
+
listAllEnrollmentProfiles,
|
|
704
895
|
listCatalogImages,
|
|
705
896
|
listControllers,
|
|
706
897
|
listDisks,
|
|
707
898
|
listDriveContents,
|
|
708
899
|
listDrives,
|
|
900
|
+
listEnrollmentCompartments,
|
|
901
|
+
listEnrollmentLogs,
|
|
902
|
+
listEnrollmentProfiles,
|
|
903
|
+
listEnrollmentRuns,
|
|
904
|
+
listEnrollmentScripts,
|
|
905
|
+
listEnrollmentTokens,
|
|
709
906
|
listGitHubBranches,
|
|
710
907
|
listGitHubConnections,
|
|
711
908
|
listGitHubRepositories,
|
|
@@ -735,9 +932,13 @@ export {
|
|
|
735
932
|
pushNodeKeys,
|
|
736
933
|
rebootNode,
|
|
737
934
|
rebootVirtualMachine,
|
|
935
|
+
remoteRunPath,
|
|
738
936
|
removeControllerNode,
|
|
739
937
|
removeControllerVirtualMachine,
|
|
740
938
|
reservationEventsPath,
|
|
939
|
+
revokeEnrollmentToken,
|
|
940
|
+
rotateEnrollmentAdminSshKey,
|
|
941
|
+
runRemote,
|
|
741
942
|
shellSessionAttachPath,
|
|
742
943
|
startDiskUpload,
|
|
743
944
|
startDriveUpload,
|
|
@@ -752,6 +953,7 @@ export {
|
|
|
752
953
|
transferNode,
|
|
753
954
|
updateDisk,
|
|
754
955
|
updateDrive,
|
|
956
|
+
updateEnrollmentProfile,
|
|
755
957
|
updateNetwork,
|
|
756
958
|
updateNode,
|
|
757
959
|
updateNodeKeys,
|
|
@@ -274,6 +274,43 @@ function removeControllerNode(request, id, nodeId3, options) {
|
|
|
274
274
|
});
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
// ../../packages/api-client/dist/orchestrator/enrollment.js
|
|
278
|
+
var enrollmentTokensPath = "/v1/orchestrator/enrollment-tokens";
|
|
279
|
+
function listEnrollmentTokens(request, query3 = {}) {
|
|
280
|
+
return request(enrollmentTokensPath + (query3.id ? `?id=${encodeURIComponent(query3.id)}` : ""), {
|
|
281
|
+
method: "GET"
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function createEnrollmentToken(request, body2) {
|
|
285
|
+
return request(enrollmentTokensPath, { method: "POST", body: body2 });
|
|
286
|
+
}
|
|
287
|
+
function revokeEnrollmentToken(request, id, idempotencyKey) {
|
|
288
|
+
return request(`${enrollmentTokensPath}/${encodeURIComponent(id)}`, {
|
|
289
|
+
method: "DELETE",
|
|
290
|
+
...idempotencyKey ? { headers: { "Idempotency-Key": idempotencyKey } } : {}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
function getEnrollmentAdminSshKey(request, nodeId3) {
|
|
294
|
+
return request(`/v1/orchestrator/enrollment/admin-ssh-key?node_id=${encodeURIComponent(nodeId3)}`, { method: "GET" });
|
|
295
|
+
}
|
|
296
|
+
function rotateEnrollmentAdminSshKey(request, nodeId3) {
|
|
297
|
+
return request(`/v1/orchestrator/enrollment/admin-ssh-key?node_id=${encodeURIComponent(nodeId3)}`, { method: "POST" });
|
|
298
|
+
}
|
|
299
|
+
function enrollmentInstallPath(query3) {
|
|
300
|
+
const params = new URLSearchParams();
|
|
301
|
+
for (const [key, value] of Object.entries(query3)) {
|
|
302
|
+
if (value !== void 0 && value !== false)
|
|
303
|
+
params.set(key, String(value));
|
|
304
|
+
}
|
|
305
|
+
return `/v1/orchestrator/enrollment/install?${params}`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ../../packages/api-client/dist/orchestrator/remote.js
|
|
309
|
+
var remoteRunPath = "/v1/staff/remote";
|
|
310
|
+
function runRemote(request, body2) {
|
|
311
|
+
return request(remoteRunPath, { method: "POST", body: body2 });
|
|
312
|
+
}
|
|
313
|
+
|
|
277
314
|
// ../../packages/capabilities/dist/capabilities/admin-ssh.js
|
|
278
315
|
import { z } from "zod";
|
|
279
316
|
|
|
@@ -757,7 +794,7 @@ var nodeExecCapability = defineCapability({
|
|
|
757
794
|
roles: ["admin"],
|
|
758
795
|
description: "Admin-only. Run one unrestricted command over orchestrator SSH. Pass node_id for an enrolled node (uses its stored admin key), or host + private_key (+ optional username, default root, and port, default 22) for any host, including one not enrolled yet. Always pass timeout_seconds. Not an interactive shell. On NVIDIA hosts use nvidia-smi; on AMD Instinct use amd-smi. Runs on the tool call \u2014 no confirm, no y/N.",
|
|
759
796
|
mutation: "immediate",
|
|
760
|
-
http: { method: "POST", path: "/remote" },
|
|
797
|
+
http: { method: "POST", path: "/v1/staff/remote" },
|
|
761
798
|
slack: {
|
|
762
799
|
parameters: {
|
|
763
800
|
type: "object",
|
|
@@ -775,9 +812,10 @@ var nodeExecCapability = defineCapability({
|
|
|
775
812
|
input: nodeExecInput,
|
|
776
813
|
execute: async (ctx, input) => {
|
|
777
814
|
const { yes: _yes, ...parsed } = nodeExecInput.parse(input);
|
|
778
|
-
return ctx.fetch
|
|
779
|
-
|
|
780
|
-
|
|
815
|
+
return runRemote(ctx.fetch, {
|
|
816
|
+
...parsed,
|
|
817
|
+
node_id: parsed.node_id?.trim(),
|
|
818
|
+
host: parsed.host?.trim()
|
|
781
819
|
});
|
|
782
820
|
}
|
|
783
821
|
});
|
|
@@ -1134,18 +1172,15 @@ var tokenCreateInput = z4.object({
|
|
|
1134
1172
|
var emptyInput = z4.object({});
|
|
1135
1173
|
function buildEnrollmentInstallCommand(options) {
|
|
1136
1174
|
const base3 = (options.base ?? "https://api.ornn.com/v1/orchestrator").replace(/\/+$/, "");
|
|
1137
|
-
const
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
if (options.force)
|
|
1147
|
-
params.push("force=true");
|
|
1148
|
-
const href = `${base3}/enrollment/install?${params.join("&")}`;
|
|
1175
|
+
const path = enrollmentInstallPath({
|
|
1176
|
+
token: options.token,
|
|
1177
|
+
facility_id: options.facilityId,
|
|
1178
|
+
filter: options.filter,
|
|
1179
|
+
ip: options.ip,
|
|
1180
|
+
restore_node_id: options.restoreNodeId,
|
|
1181
|
+
force: options.force
|
|
1182
|
+
});
|
|
1183
|
+
const href = `${base3}${path.replace(/^\/v1\/orchestrator/, "")}`;
|
|
1149
1184
|
return `set -o pipefail; curl -fsSL '${href.replace(/'/g, "'\\''")}' | sudo bash`;
|
|
1150
1185
|
}
|
|
1151
1186
|
function tokenString(row, keys) {
|
|
@@ -1162,10 +1197,10 @@ var tokensListCapability = defineCapability({
|
|
|
1162
1197
|
roles: ["admin"],
|
|
1163
1198
|
description: "List issued enrollment tokens (id, supplier organization_id, status, expiry). Does not return plaintext secrets.",
|
|
1164
1199
|
mutation: "read",
|
|
1165
|
-
http: { method: "GET", path: "/enrollment-tokens" },
|
|
1200
|
+
http: { method: "GET", path: "/v1/orchestrator/enrollment-tokens" },
|
|
1166
1201
|
slack: { parameters: { type: "object", properties: {} } },
|
|
1167
1202
|
input: emptyInput,
|
|
1168
|
-
execute: async (ctx) => ctx.fetch
|
|
1203
|
+
execute: async (ctx) => listEnrollmentTokens(ctx.fetch)
|
|
1169
1204
|
});
|
|
1170
1205
|
var tokensCreateCapability = defineCapability({
|
|
1171
1206
|
id: "tokens.create",
|
|
@@ -1173,7 +1208,7 @@ var tokensCreateCapability = defineCapability({
|
|
|
1173
1208
|
roles: ["admin"],
|
|
1174
1209
|
description: "Admin-only. Mint an enrollment token. Without a host this returns the curl installer. With host + private_key, orchestrator SSHs and runs that curl (same as Bulk Enroll). Never invent a command. Slack waits for a human confirm. ",
|
|
1175
1210
|
mutation: "preview-confirm",
|
|
1176
|
-
http: { method: "POST", path: "/enrollment-tokens" },
|
|
1211
|
+
http: { method: "POST", path: "/v1/orchestrator/enrollment-tokens" },
|
|
1177
1212
|
slack: {
|
|
1178
1213
|
parameters: {
|
|
1179
1214
|
type: "object",
|
|
@@ -1228,13 +1263,10 @@ var tokensCreateCapability = defineCapability({
|
|
|
1228
1263
|
if (!ctx.confirmed) {
|
|
1229
1264
|
return preview("tokens.create", { ...payload, private_key: privateKey ? "[redacted]" : "" });
|
|
1230
1265
|
}
|
|
1231
|
-
const minted = await ctx.fetch
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
...payload.facility_id ? { facility_id: payload.facility_id } : {},
|
|
1236
|
-
...payload.expires_in_seconds ? { expires_in_seconds: payload.expires_in_seconds } : {}
|
|
1237
|
-
}
|
|
1266
|
+
const minted = await createEnrollmentToken(ctx.fetch, {
|
|
1267
|
+
organization_id: organizationId,
|
|
1268
|
+
...payload.facility_id ? { facility_id: payload.facility_id } : {},
|
|
1269
|
+
...payload.expires_in_seconds ? { expires_in_seconds: payload.expires_in_seconds } : {}
|
|
1238
1270
|
});
|
|
1239
1271
|
const token = tokenString(minted, ["token", "plaintext"]) ?? "";
|
|
1240
1272
|
const installCommand = token ? buildEnrollmentInstallCommand({
|
|
@@ -1249,16 +1281,13 @@ var tokensCreateCapability = defineCapability({
|
|
|
1249
1281
|
}
|
|
1250
1282
|
const results = [];
|
|
1251
1283
|
for (const host of hosts) {
|
|
1252
|
-
results.push(await ctx.fetch
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
command: installCommand,
|
|
1260
|
-
timeout_seconds: 600
|
|
1261
|
-
}
|
|
1284
|
+
results.push(await runRemote(ctx.fetch, {
|
|
1285
|
+
host,
|
|
1286
|
+
username: payload.username,
|
|
1287
|
+
port: payload.port,
|
|
1288
|
+
private_key: privateKey,
|
|
1289
|
+
command: installCommand,
|
|
1290
|
+
timeout_seconds: 600
|
|
1262
1291
|
}));
|
|
1263
1292
|
}
|
|
1264
1293
|
return {
|
|
@@ -2730,11 +2759,11 @@ function withVnextBinding(capability, help3) {
|
|
|
2730
2759
|
var adminEnrollmentTokensListCapability2 = {
|
|
2731
2760
|
...withVnextBinding(tokensListCapability, adminHelp3(["admin", "enrollment-tokens", "list"], "List enrollment-token metadata without token bytes.", "ornn admin enrollment-tokens list [--limit 50] [--cursor CURSOR]", "ornn admin enrollment-tokens list --limit 50 --format json")),
|
|
2732
2761
|
execute: async (ctx) => {
|
|
2733
|
-
const payload = await
|
|
2762
|
+
const payload = await listEnrollmentTokens(ctx.fetch);
|
|
2734
2763
|
if (!ctx.cli)
|
|
2735
2764
|
return payload;
|
|
2736
2765
|
return {
|
|
2737
|
-
enrollment_tokens:
|
|
2766
|
+
enrollment_tokens: payload.tokens.map(tokenMetadata).filter((token) => token !== null)
|
|
2738
2767
|
};
|
|
2739
2768
|
}
|
|
2740
2769
|
};
|
|
@@ -2746,18 +2775,6 @@ var tokenRevokeInput = z12.object({
|
|
|
2746
2775
|
idempotency_key: nonEmpty.optional(),
|
|
2747
2776
|
confirm: z12.boolean().optional()
|
|
2748
2777
|
});
|
|
2749
|
-
function rowsFromTokenList(payload) {
|
|
2750
|
-
if (Array.isArray(payload))
|
|
2751
|
-
return payload;
|
|
2752
|
-
if (!payload || typeof payload !== "object")
|
|
2753
|
-
return [];
|
|
2754
|
-
const source = payload;
|
|
2755
|
-
for (const key of ["enrollment_tokens", "tokens", "items", "data"]) {
|
|
2756
|
-
if (Array.isArray(source[key]))
|
|
2757
|
-
return source[key];
|
|
2758
|
-
}
|
|
2759
|
-
return [];
|
|
2760
|
-
}
|
|
2761
2778
|
function tokenMetadata(value) {
|
|
2762
2779
|
if (!value || typeof value !== "object")
|
|
2763
2780
|
return null;
|
|
@@ -2778,10 +2795,8 @@ function codedError(code, message) {
|
|
|
2778
2795
|
return error;
|
|
2779
2796
|
}
|
|
2780
2797
|
async function readExactToken(ctx, tokenId, expectedCreatedAt) {
|
|
2781
|
-
const listed = await ctx.fetch
|
|
2782
|
-
|
|
2783
|
-
});
|
|
2784
|
-
const target = rowsFromTokenList(listed).map(tokenMetadata).find((candidate) => candidate?.id === tokenId);
|
|
2798
|
+
const listed = await listEnrollmentTokens(ctx.fetch, { id: tokenId });
|
|
2799
|
+
const target = listed.tokens.map(tokenMetadata).find((candidate) => candidate?.id === tokenId);
|
|
2785
2800
|
if (!target)
|
|
2786
2801
|
return { disposition: "satisfied", target: null };
|
|
2787
2802
|
if (expectedCreatedAt && target.created_at !== expectedCreatedAt) {
|
|
@@ -2802,7 +2817,7 @@ var adminEnrollmentTokenRevokeCapability = defineCapability({
|
|
|
2802
2817
|
roles: ["admin"],
|
|
2803
2818
|
description: "Internal staff only: revoke one exact enrollment-token generation after reconciling its durable goal.",
|
|
2804
2819
|
mutation: "preview-confirm",
|
|
2805
|
-
http: { method: "DELETE", path: "/enrollment-tokens/{tokenId}" },
|
|
2820
|
+
http: { method: "DELETE", path: "/v1/orchestrator/enrollment-tokens/{tokenId}" },
|
|
2806
2821
|
cli: {
|
|
2807
2822
|
command: ["admin", "enrollment-tokens", "revoke"],
|
|
2808
2823
|
vnext: adminHelp3(["admin", "enrollment-tokens", "revoke"], "Revoke one exact enrollment-token generation.", "ornn admin enrollment-tokens revoke <token-id> [--expected-created-at TIME] []", "ornn admin enrollment-tokens revoke <token-id> --expected-created-at TIME --idempotency-key KEY --format json", ["canonical token UUID", "token created_at generation"], "Review the exact token generation and the loss of future enrollment access.")
|
|
@@ -2830,10 +2845,7 @@ var adminEnrollmentTokenRevokeCapability = defineCapability({
|
|
|
2830
2845
|
if (!current.target.created_at) {
|
|
2831
2846
|
throw codedError("token_identity_unavailable", `Enrollment token ${tokenId} has no stable creation identity and cannot be revoked safely.`);
|
|
2832
2847
|
}
|
|
2833
|
-
const revoked = await ctx.fetch
|
|
2834
|
-
method: "DELETE",
|
|
2835
|
-
...parsed.idempotency_key ? { headers: { "Idempotency-Key": parsed.idempotency_key } } : {}
|
|
2836
|
-
});
|
|
2848
|
+
const revoked = await revokeEnrollmentToken(ctx.fetch, tokenId, parsed.idempotency_key);
|
|
2837
2849
|
return {
|
|
2838
2850
|
id: tokenId,
|
|
2839
2851
|
created_at: current.target.created_at,
|
|
@@ -2879,7 +2891,7 @@ var adminNodeEnrollCapability = defineCapability({
|
|
|
2879
2891
|
roles: ["admin"],
|
|
2880
2892
|
description: "Enroll one explicit node over SSH with an explicit supplier and facility assignment.",
|
|
2881
2893
|
mutation: "preview-confirm",
|
|
2882
|
-
http: { method: "POST", path: "/remote" },
|
|
2894
|
+
http: { method: "POST", path: "/v1/staff/remote" },
|
|
2883
2895
|
cli: {
|
|
2884
2896
|
command: ["admin", "nodes", "enroll"],
|
|
2885
2897
|
vnext: adminHelp3(["admin", "nodes", "enroll"], "Install Ornn management on one explicitly assigned node.", "ornn admin nodes enroll <node-id> --host HOST --supplier UUID --facility UUID [--filter COMPARTMENT_IDS] --identity-file PATH --token-ttl SECONDS --replace-existing-management [--verbose] []", "Unsupported: remote enrollment requires an eligible human terminal.", ["canonical node UUID", "canonical supplier organization UUID", "canonical facility UUID"], "Review node identity, SSH target, assignment, compartment filter, and replacement of existing management.")
|
|
@@ -2903,12 +2915,9 @@ var adminNodeEnrollCapability = defineCapability({
|
|
|
2903
2915
|
if (!parsed.private_key) {
|
|
2904
2916
|
throw codedError("identity_file_unreadable", "The SSH identity file could not be read.");
|
|
2905
2917
|
}
|
|
2906
|
-
const minted = await ctx.fetch
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
organization_id: parsed.organization_id,
|
|
2910
|
-
expires_in_seconds: parsed.expires_in_seconds
|
|
2911
|
-
}
|
|
2918
|
+
const minted = await createEnrollmentToken(ctx.fetch, {
|
|
2919
|
+
organization_id: parsed.organization_id,
|
|
2920
|
+
expires_in_seconds: parsed.expires_in_seconds
|
|
2912
2921
|
});
|
|
2913
2922
|
const token = typeof minted.token === "string" ? minted.token : typeof minted.plaintext === "string" ? minted.plaintext : "";
|
|
2914
2923
|
if (!token) {
|
|
@@ -2922,16 +2931,13 @@ var adminNodeEnrollCapability = defineCapability({
|
|
|
2922
2931
|
restoreNodeId: parsed.node_id,
|
|
2923
2932
|
force: true
|
|
2924
2933
|
});
|
|
2925
|
-
const remote = await ctx.fetch
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
command,
|
|
2933
|
-
timeout_seconds: 600
|
|
2934
|
-
}
|
|
2934
|
+
const remote = await runRemote(ctx.fetch, {
|
|
2935
|
+
host: parsed.host,
|
|
2936
|
+
username: parsed.username,
|
|
2937
|
+
port: parsed.port,
|
|
2938
|
+
private_key: parsed.private_key,
|
|
2939
|
+
command,
|
|
2940
|
+
timeout_seconds: 600
|
|
2935
2941
|
});
|
|
2936
2942
|
return {
|
|
2937
2943
|
node_id: parsed.node_id,
|
|
@@ -2955,7 +2961,7 @@ var adminNodeExportKeyCapability = defineCapability({
|
|
|
2955
2961
|
roles: ["admin"],
|
|
2956
2962
|
description: "Export an enrolled node's private admin key only through an explicit secret destination.",
|
|
2957
2963
|
mutation: "read",
|
|
2958
|
-
http: { method: "GET", path: "/enrollment/admin-ssh-key" },
|
|
2964
|
+
http: { method: "GET", path: "/v1/orchestrator/enrollment/admin-ssh-key" },
|
|
2959
2965
|
cli: {
|
|
2960
2966
|
command: ["admin", "nodes", "export-key"],
|
|
2961
2967
|
vnext: adminHelp3(["admin", "nodes", "export-key"], "Export one node admin key deliberately.", "ornn admin nodes export-key <node-id> (--print | --output PATH) [--overwrite]", "ornn admin nodes export-key <node-id> --output PATH [--overwrite] --format json", ["canonical node UUID"])
|
|
@@ -2965,9 +2971,7 @@ var adminNodeExportKeyCapability = defineCapability({
|
|
|
2965
2971
|
input: nodeKeyInput,
|
|
2966
2972
|
execute: async (ctx, input) => {
|
|
2967
2973
|
const parsed = nodeKeyInput.parse(input);
|
|
2968
|
-
return ctx.fetch
|
|
2969
|
-
method: "GET"
|
|
2970
|
-
});
|
|
2974
|
+
return getEnrollmentAdminSshKey(ctx.fetch, parsed.node_id);
|
|
2971
2975
|
}
|
|
2972
2976
|
});
|
|
2973
2977
|
var adminNodeRotateKeyCapability = defineCapability({
|
|
@@ -2976,7 +2980,7 @@ var adminNodeRotateKeyCapability = defineCapability({
|
|
|
2976
2980
|
roles: ["admin"],
|
|
2977
2981
|
description: "Replace a node's admin key and export the new private key explicitly.",
|
|
2978
2982
|
mutation: "preview-confirm",
|
|
2979
|
-
http: { method: "POST", path: "/enrollment/admin-ssh-key" },
|
|
2983
|
+
http: { method: "POST", path: "/v1/orchestrator/enrollment/admin-ssh-key" },
|
|
2980
2984
|
cli: {
|
|
2981
2985
|
command: ["admin", "nodes", "rotate-key"],
|
|
2982
2986
|
vnext: adminHelp3(["admin", "nodes", "rotate-key"], "Rotate one node admin key and export the replacement deliberately.", "ornn admin nodes rotate-key <node-id> (--print | --output PATH) [--overwrite] []", "Unsupported: key rotation requires an eligible human terminal.", ["canonical node UUID"], "Review the node and loss of access through the previous private key.")
|
|
@@ -2988,9 +2992,7 @@ var adminNodeRotateKeyCapability = defineCapability({
|
|
|
2988
2992
|
const parsed = nodeKeyInput.parse(input);
|
|
2989
2993
|
if (!ctx.confirmed)
|
|
2990
2994
|
return { node_id: parsed.node_id };
|
|
2991
|
-
return ctx.fetch
|
|
2992
|
-
method: "POST"
|
|
2993
|
-
});
|
|
2995
|
+
return rotateEnrollmentAdminSshKey(ctx.fetch, parsed.node_id);
|
|
2994
2996
|
}
|
|
2995
2997
|
});
|
|
2996
2998
|
var replacements2 = {
|