@lamalibre/portlama-agent 1.0.8 → 1.0.9
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/lib/panel-api.js +173 -0
package/package.json
CHANGED
package/src/lib/panel-api.js
CHANGED
|
@@ -451,6 +451,179 @@ export async function deleteSiteFile(panelUrlOrConfig, p12Path, p12Password, sit
|
|
|
451
451
|
}
|
|
452
452
|
}
|
|
453
453
|
|
|
454
|
+
// ---------------------------------------------------------------------------
|
|
455
|
+
// Ticket system API functions
|
|
456
|
+
// ---------------------------------------------------------------------------
|
|
457
|
+
|
|
458
|
+
// --- Ticket API functions ---
|
|
459
|
+
// These use config-object only (no dual positional args). The ticket system is new
|
|
460
|
+
// and only called from code that already uses config objects, so the legacy positional
|
|
461
|
+
// calling convention used by older functions above is not needed here.
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Fetch pending tickets from the agent's inbox.
|
|
465
|
+
* @param {object} config - Agent config object
|
|
466
|
+
* @returns {Promise<{ tickets: Array }>}
|
|
467
|
+
*/
|
|
468
|
+
export async function fetchTicketInbox(config) {
|
|
469
|
+
const url = `${config.panelUrl}/api/tickets/inbox`;
|
|
470
|
+
try {
|
|
471
|
+
const { stdout } = await curlAuthenticated(config, [url]);
|
|
472
|
+
return JSON.parse(stdout);
|
|
473
|
+
} catch (err) {
|
|
474
|
+
throw new Error(`Failed to fetch ticket inbox. Details: ${err.stderr || err.message}`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Validate a ticket from the inbox.
|
|
480
|
+
* @param {object} config - Agent config object
|
|
481
|
+
* @param {string} ticketId - The ticket ID to validate
|
|
482
|
+
* @returns {Promise<object>}
|
|
483
|
+
*/
|
|
484
|
+
export async function validateTicket(config, ticketId) {
|
|
485
|
+
const url = `${config.panelUrl}/api/tickets/validate`;
|
|
486
|
+
const curlArgs = [
|
|
487
|
+
'-X', 'POST',
|
|
488
|
+
'-H', 'Content-Type: application/json',
|
|
489
|
+
'-d', JSON.stringify({ ticketId }),
|
|
490
|
+
url,
|
|
491
|
+
];
|
|
492
|
+
try {
|
|
493
|
+
const { stdout } = await curlAuthenticated(config, curlArgs);
|
|
494
|
+
return JSON.parse(stdout);
|
|
495
|
+
} catch (err) {
|
|
496
|
+
throw new Error(`Failed to validate ticket. Details: ${err.stderr || err.message}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Register an instance for a ticket scope.
|
|
502
|
+
* @param {object} config - Agent config object
|
|
503
|
+
* @param {string} scope - The scope capability (e.g. "shell:connect")
|
|
504
|
+
* @param {object} transport - Transport configuration
|
|
505
|
+
* @returns {Promise<object>}
|
|
506
|
+
*/
|
|
507
|
+
export async function registerTicketInstance(config, scope, transport) {
|
|
508
|
+
const url = `${config.panelUrl}/api/tickets/instances`;
|
|
509
|
+
const curlArgs = [
|
|
510
|
+
'-X', 'POST',
|
|
511
|
+
'-H', 'Content-Type: application/json',
|
|
512
|
+
'-d', JSON.stringify({ scope, transport }),
|
|
513
|
+
url,
|
|
514
|
+
];
|
|
515
|
+
try {
|
|
516
|
+
const { stdout } = await curlAuthenticated(config, curlArgs);
|
|
517
|
+
return JSON.parse(stdout);
|
|
518
|
+
} catch (err) {
|
|
519
|
+
throw new Error(`Failed to register ticket instance. Details: ${err.stderr || err.message}`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Send an instance heartbeat.
|
|
525
|
+
* @param {object} config - Agent config object
|
|
526
|
+
* @param {string} instanceId - The instance ID
|
|
527
|
+
* @returns {Promise<object>}
|
|
528
|
+
*/
|
|
529
|
+
export async function sendInstanceHeartbeat(config, instanceId) {
|
|
530
|
+
const url = `${config.panelUrl}/api/tickets/instances/${encodeURIComponent(instanceId)}/heartbeat`;
|
|
531
|
+
const curlArgs = ['-X', 'POST', url];
|
|
532
|
+
try {
|
|
533
|
+
const { stdout } = await curlAuthenticated(config, curlArgs);
|
|
534
|
+
return JSON.parse(stdout);
|
|
535
|
+
} catch (err) {
|
|
536
|
+
throw new Error(`Failed to send instance heartbeat. Details: ${err.stderr || err.message}`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Request a ticket for a target agent.
|
|
542
|
+
* @param {object} config - Agent config object
|
|
543
|
+
* @param {string} scope - Capability scope
|
|
544
|
+
* @param {string} instanceId - The instance ID
|
|
545
|
+
* @param {string} target - Target agent label
|
|
546
|
+
* @returns {Promise<object>}
|
|
547
|
+
*/
|
|
548
|
+
export async function requestTicket(config, scope, instanceId, target) {
|
|
549
|
+
const url = `${config.panelUrl}/api/tickets`;
|
|
550
|
+
const curlArgs = [
|
|
551
|
+
'-X', 'POST',
|
|
552
|
+
'-H', 'Content-Type: application/json',
|
|
553
|
+
'-d', JSON.stringify({ scope, instanceId, target }),
|
|
554
|
+
url,
|
|
555
|
+
];
|
|
556
|
+
try {
|
|
557
|
+
const { stdout } = await curlAuthenticated(config, curlArgs);
|
|
558
|
+
return JSON.parse(stdout);
|
|
559
|
+
} catch (err) {
|
|
560
|
+
throw new Error(`Failed to request ticket. Details: ${err.stderr || err.message}`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Report a session creation to the panel.
|
|
566
|
+
* @param {object} config - Agent config object
|
|
567
|
+
* @param {string} ticketId - The ticket ID
|
|
568
|
+
* @param {string} sessionId - The session ID
|
|
569
|
+
* @returns {Promise<object>}
|
|
570
|
+
*/
|
|
571
|
+
export async function reportSessionCreation(config, ticketId, sessionId) {
|
|
572
|
+
const url = `${config.panelUrl}/api/tickets/sessions`;
|
|
573
|
+
const curlArgs = [
|
|
574
|
+
'-X', 'POST',
|
|
575
|
+
'-H', 'Content-Type: application/json',
|
|
576
|
+
'-d', JSON.stringify({ ticketId, sessionId }),
|
|
577
|
+
url,
|
|
578
|
+
];
|
|
579
|
+
try {
|
|
580
|
+
const { stdout } = await curlAuthenticated(config, curlArgs);
|
|
581
|
+
return JSON.parse(stdout);
|
|
582
|
+
} catch (err) {
|
|
583
|
+
throw new Error(`Failed to report session creation. Details: ${err.stderr || err.message}`);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Send a session heartbeat to the panel for re-validation.
|
|
589
|
+
* @param {object} config - Agent config object
|
|
590
|
+
* @param {string} sessionId - The session ID
|
|
591
|
+
* @returns {Promise<{ authorized: boolean, reason?: string }>}
|
|
592
|
+
*/
|
|
593
|
+
export async function sendSessionHeartbeat(config, sessionId) {
|
|
594
|
+
const url = `${config.panelUrl}/api/tickets/sessions/${encodeURIComponent(sessionId)}/heartbeat`;
|
|
595
|
+
const curlArgs = ['-X', 'POST', url];
|
|
596
|
+
try {
|
|
597
|
+
const { stdout } = await curlAuthenticated(config, curlArgs);
|
|
598
|
+
return JSON.parse(stdout);
|
|
599
|
+
} catch (err) {
|
|
600
|
+
throw new Error(`Failed to send session heartbeat. Details: ${err.stderr || err.message}`);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Update session status on the panel.
|
|
606
|
+
* @param {object} config - Agent config object
|
|
607
|
+
* @param {string} sessionId - The session ID
|
|
608
|
+
* @param {string} status - New status: 'active' or 'grace'
|
|
609
|
+
* @returns {Promise<object>}
|
|
610
|
+
*/
|
|
611
|
+
export async function updateSessionStatus(config, sessionId, status) {
|
|
612
|
+
const url = `${config.panelUrl}/api/tickets/sessions/${encodeURIComponent(sessionId)}`;
|
|
613
|
+
const curlArgs = [
|
|
614
|
+
'-X', 'PATCH',
|
|
615
|
+
'-H', 'Content-Type: application/json',
|
|
616
|
+
'-d', JSON.stringify({ status, lastActivityAt: new Date().toISOString() }),
|
|
617
|
+
url,
|
|
618
|
+
];
|
|
619
|
+
try {
|
|
620
|
+
const { stdout } = await curlAuthenticated(config, curlArgs);
|
|
621
|
+
return JSON.parse(stdout);
|
|
622
|
+
} catch (err) {
|
|
623
|
+
throw new Error(`Failed to update session status. Details: ${err.stderr || err.message}`);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
454
627
|
/**
|
|
455
628
|
* Execute an unauthenticated curl POST to a panel URL.
|
|
456
629
|
* Used for the enrollment endpoint which doesn't require mTLS.
|