Medulla's XML-RPC API.php
<!-- IMORTANT
- Vérifier connectivité vers le serveur xmlrpc avec par exemple telnet 10.10.0.10 7080
- Vérification du ssl si pas présent l'importer cf procédure qui va venir
1. Récupérer par exemple le ceritifcat de spo ici /var/lib/pulse2/pki/ca-chain.cert.pem
2. Le copié sur le poste client ici /usr/local/share/ca-certificates/ca-certificates.crt
3. L'importer avec la commande sudo update-ca-certificates
-->
<!-- Gestion des appels XML-RPC -->
<?php
// Démarrage de la session
session_start();
// Stockage des données de connexion dans un tableau associatif
// 'scheme' : Protocole utilisé (https)
// 'host' : Adresse du serveur
// 'port' : Port sur lequel le serveur XML-RPC est accessible
// 'login' et 'password' : Identifiants pour l'authentification
$_SESSION["XMLRPC_agent"] = [
"scheme" => "https",
"host" => "devdemo.siveo.net",
// "host" => "127.0.0.1",
"port" => "7080",
"login" => "mmc",
"password" => "s3cr3t",
];
/**
* Exécute une requête XML-RPC.
*
* @param string $method Le nom de la méthode XML-RPC à appeler.
* @param array $params Les paramètres à passer à la méthode.
* @param bool $includeCookie Indique si le cookie de session doit être inclus dans la requête.
* @return array Un tableau contenant les en-têtes HTTP et le corps de la réponse.
* @throws Exception Si une erreur se produit lors de la connexion ou de l'envoi de la requête.
*/
function executeRequest($method, $params, $includeCookie = false) {
$agentInfo = $_SESSION["XMLRPC_agent"];
$requestXml = xmlrpc_encode_request($method, $params, ['output_type' => 'php', 'verbosity' => 'pretty', 'encoding' => 'UTF-8']);
// On définit les en-têtes HTTP
$url = "/";
$httpQuery = "POST " . $url . " HTTP/1.0\r\n";
$httpQuery .= "User-Agent: MMC web interface\r\n";
$httpQuery .= "Host: " . $agentInfo["host"] . ":" . $agentInfo["port"] . "\r\n";
$httpQuery .= "Content-Type: text/xml\r\n";
$httpQuery .= "Content-Length: " . strlen($requestXml) . "\r\n";
// On ajoute le cookie si nécessaire
if ($includeCookie) {
$httpQuery .= "Cookie: " . $_SESSION['cookie'] . "\r\n";
}
$httpQuery .= "Authorization: Basic " . base64_encode($agentInfo["login"] . ":" . $agentInfo["password"]) . "\r\n\r\n";
$httpQuery .= $requestXml;
// Configurer le contexte SSL
// 'allow_self_signed' est défini sur false pour n'accepter que les certificats signés par une autorité de certification reconnue
// 'verify_peer' est défini sur true pour vérifier le certificat SSL du serveur
$context = stream_context_create();
$proto = $agentInfo["scheme"] == "https" ? "ssl://" : "";
if ($proto) {
stream_context_set_option($context, "ssl", "allow_self_signed", false);
stream_context_set_option($context, "ssl", "verify_peer", true);
}
// On ouvre la connexion au serveur
$socket = stream_socket_client($proto . $agentInfo["host"] . ":" . $agentInfo["port"], $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
if (!$socket) {
throw new Exception("Unable to connect to XML-RPC server: $errstr ($errno)");
}
// On ajoute un délai de 60 secondes pour la lecture
stream_set_timeout($socket, 60);
if (!fwrite($socket, $httpQuery)) {
throw new Exception("Unable to send data to XML-RPC server");
}
$responseXml = '';
while (!feof($socket)) {
$ret = fgets($socket, 128);
$responseXml .= $ret;
}
fclose($socket);
// Séparez les en-têtes HTTP du corps de la réponse
list($headers, $body) = explode("\r\n\r\n", $responseXml, 2);
return [$headers, $body];
}
/**
* Authentifie l'utilisateur et récupère le cookie de session.
* @param string $method Le nom de la méthode XML-RPC à appeler.
* @param array $params Les paramètres à passer à la méthode.
* @return string Le cookie de session.
* @throws Exception Si une erreur se produit lors de l'authentification.
*/
function authenticateAndGetCookie($method, $params) {
list($headers, $body) = executeRequest($method, $params);
// Parsing des en-têtes HTTP pour extraire le cookie de session
$headers_array = array();
$header_lines = explode("\r\n", $headers);
foreach ($header_lines as $header) {
$parts = explode(': ', $header, 2);
if (count($parts) == 2) {
$headers_array[$parts[0]] = $parts[1];
}
}
// Utilisation des en-têtes analysés
if (isset($headers_array['Set-Cookie'])) {
$cookie = $headers_array['Set-Cookie'];
$_SESSION['cookie'] = $cookie;
} else {
throw new Exception('Authentication failed, no cookie received');
}
return $cookie;
}
/**
* Envoie une requête XML-RPC et retourne la réponse uniquement si authentifié par cookie.
* @param string $method Le nom de la méthode XML-RPC à appeler.
* @param array $params Les paramètres à passer à la méthode.
* @return array La réponse XML-RPC.
* @throws Exception Si une erreur se produit lors de l'envoi de la requête.
*/
function sendXmlRpcRequest($method, $params) {
list($headers, $body) = executeRequest($method, $params, true);
$responseXml = substr($body, strpos($body, '<?xml'));
$response = xmlrpc_decode($responseXml, 'UTF-8');
if (is_array($response) && xmlrpc_is_fault($response)) {
throw new Exception("XML-RPC fault: {$response['faultString']} ({$response['faultCode']})");
}
return $response;
}
// Authentification et récupération du cookie
$method = "base.ldapAuth";
$params = ['root', 'Sive0DEVDEMO'];
try {
$responseXml = authenticateAndGetCookie($method, $params);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// ✅ Exemple d'utilisation de la méthode pkgs.get_all_packages pour récupérer la liste des paquets
if(isset($_POST['listPackages'])) {
$method = "pkgs.get_all_packages";
$params = [
'root', // login
false, // sharing_activated
0, // start
10, // end
[
'filter' => '',
// 'filter' => 'hostname',
] // ctx
];
try {
$responseXml = sendXmlRpcRequest($method, $params);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}
// ✅ Exemple d'utilisation de la méthode xmppmaster.get_machines_list pour récupérer la liste des machines
if(isset($_POST['listMachines'])) {
$method = "xmppmaster.get_machines_list";
$params = [
0, // start
20, // end
[
'filter' => '',
'field' => 'allchamp',
'computerpresence' => 'presence', // Définir si on veut les machines présentes
// 'computerpresence' => 'no_presence', // Définir si on veut les machines non présentes
'location' => "UUID0", // glpi_id - entité
] // ctx
];
try {
$responseXml = sendXmlRpcRequest($method, $params);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}
// ✅ Exemple d'utilisation de la méthode glpi.getLastMachineInventoryPart pour récupérer les détails d'une machine
if(isset($_POST['detailMachine'])) {
if (isset($_POST['machineUUID'])) {
$uuid = $_POST['machineUUID'];
$method = "glpi.getLastMachineInventoryPart";
$params = [
$uuid,
'Summary',
0, // minbound
0, // maxbound
"", // filter
[
"hide_win_updates" => false,
"history_delta" => false
], // options
];
try {
$responseXml = sendXmlRpcRequest($method, $params);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
} else {
echo "Pas d'UUID";
}
}
// ✅ Exemple d'utilisation de la méthode msc.add_command_api pour lancer un déploiement
if(isset($_POST['deploy'])) {
$method = "msc.add_command_api";
$pid = "96982fce-hostname_vq918j7wtnwzm610by"; // pid - paquet_id
$target = "UUID1"; // target - uuid_machine
$params = [
$pid, // pid - paquet_id
$target, // target - uuid_machine
array( // params
"do_reboot" => "",
"start_script" => "on",
"clean_on_success" => "on",
"do_wol" => "",
"next_connection_delay" => "60",
"max_connection_attempt" => "3",
"do_inventory" => "on",
"issue_halt_to" => array(),
"maxbw" => "0",
"name" => "devdemo-win-1",
"hostname" => "devdemo-win-1",
"uuid" => $target,
"pid" => $pid,
"gid" => NULL,
// "ltitle" => "TITRE DU DEPLOIEMENT",
// "deployment_intervals" => "",
// "from" => "base|computers|msctabs|tablogs",
// "create_directory" => "on",
// "tab" => "tablaunch",
),
"push", // mode
NULL, // gid (si vous avez un gid, remplacez NULL par la valeur correspondante)
array(), // proxy (si vous avez des informations de proxy, ajoutez-les ici)
0 // cmd_type (si vous avez un type de commande spécifique, remplacez 0 par la valeur correspondante)
];
try {
$responseXml = sendXmlRpcRequest($method, $params);
$commandId = $responseXml; // Récupérer l'ID de la commande
$method2 = "xmppmaster.addlogincommand";
$params2 = [
'root', // login
$commandId, // commandid
'', // grpid
'', // nb_machine_in_grp
'', // instructions_nb_machine_for_exec
'', // instructions_datetime_for_exec
'', // parameterspackage
0, // rebootrequired
0, // shutdownrequired
0, // bandwidth
0, // syncthing
[] // params
];
try {
$responseXml2 = sendXmlRpcRequest($method2, $params2);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}
if(isset($_POST['getAllAudit'])) {
$method = "xmppmaster.get_deploy_by_user_with_interval";
$params = [
"root", // login
"", // state
86400, // intervalsearch
0, // start_pagination
"20", // end_pagination
"", // filt
"command" // typedeploy
];
try {
$responseXml = sendXmlRpcRequest($method, $params);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}
// ✅ Exemple d'utilisation de la méthode xmppmaster.getlinelogssession pour récupérer les logs d'un audit spécifique
if(isset($_POST['getAudit'])) {
if(isset($_POST['commandID'])) {
$commandID = $_POST['commandID'];
$method = "xmppmaster.getlinelogssession";
$params = [
$commandID // sessionname
];
}
try {
$responseXml = sendXmlRpcRequest($method, $params);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}
?>
<!-- Affichage WEB -->
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test XML-RPC</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
th {
background-color: #f2f2f2;
}
.container {
display: flex;
flex-direction: row;
justify-content: space-around;
}
</style>
</head>
<body>
<h2>Test XML-RPC</h2>
<div class="container">
<!-- Formulaire pour le bouton "Lister les paquets" -->
<form method="post">
<button type="submit" name="listPackages">Lister les paquets</button>
</form>
<!-- Formulaire pour le bouton "Lister les machines" -->
<form method="post">
<button type="submit" name="listMachines">Lister les machines</button>
</form>
<!-- Formulaire pour le bouton "Lancer un déploiement" -->
<form method="post">
<button type="submit" name="deploy">Déploiement d'un paquet fixe</button>
</form>
<!-- Formulaire pour le bouton "Lister tous les audits" -->
<form method="post">
<button type="submit" name="getAllAudit">Voir tous les audits</button>
</form>
<!-- Formulaire pour le bouton "Voir un audit"
<form method="post">
<button type="submit" name="getAudit">Voir Audit</button>
</form> -->
</div>
<!-- Affichage du tableau des paquets -->
<div id="response">
<?php
if(isset($_POST['listPackages'])) {
echo '<h3>Voilà la liste des paquets</h3>';
if (isset($responseXml) && is_array($responseXml) && isset($responseXml['datas'])) {
$datas = $responseXml['datas'];
echo '<table>';
echo '<tr>';
echo '<th>Package</th>';
echo '<th>Description</th>';
echo '<th>Version</th>';
echo '<th>UUID du package</th>';
echo '</tr>';
foreach ($datas['name'] as $key => $packageName) {
$description = $datas['description'][$key];
$version = $datas['version'][$key];
$size = number_format($datas['size'][$key] / 1024, 1) . ' kOctets'; // Convertir la taille en kOctets
$uuid = $datas['uuid'][$key];
echo '<tr>';
echo '<td>' . $packageName . '</td>';
echo '<td>' . $description . '</td>';
echo '<td>' . $version . '</td>';
echo '<td>' . $uuid . '</td>';
echo '</tr>';
}
echo '</table>';
}
} elseif(isset($_POST['listMachines'])) {
echo '<h3>Voilà la liste des machines</h3>';
if (isset($responseXml) && is_array($responseXml) && isset($responseXml['data'])) {
$datas = $responseXml['data'];
$totalMachines = count($datas['id']); // Obtenez le nombre total de machines
echo '<table border="1">';
echo '<tr>';
echo '<th>UUID</th>';
echo '<th>Nom de la Machine</th>';
echo '<th>Description</th>';
echo '<th>Système d\'exploitation</th>';
echo '<th>Type</th>';
echo '<th>Dernier Utilisateur</th>';
echo '<th>Entité</th>';
echo '<th>Actions</th>';
echo '</tr>';
for ($i = 0; $i < $totalMachines; $i++) {
// Accédez aux données pertinentes dans le tableau de réponse
$uuid = $datas['uuid_inventorymachine'][$i];
$machineName = $datas['hostname'][$i];
$description = $datas['glpi_description'][$i];
$os = $datas['platform'][$i];
$type = $datas['model'][$i];
$lastUser = $datas['lastuser'][$i];
$entity = $datas['entityname'][$i];
echo '<tr>';
echo '<td>' . $uuid . '</td>';
echo '<td>' . $machineName . '</td>';
echo '<td>' . $description . '</td>';
echo '<td>' . $os . '</td>';
echo '<td>' . $type . '</td>';
echo '<td>' . $lastUser . '</td>';
echo '<td>' . $entity . '</td>';
echo '<td>
<form method="post">
<input type="hidden" name="machineUUID" value="' . $datas['uuid_inventorymachine'][$i] . '">
<button type="submit" name="detailMachine">Détail de la machine</button>
</form>
</td>';
echo '</tr>';
}
echo '</table>';
}
} elseif(isset($_POST['detailMachine'])) {
echo '<h3>Détails de la Machine</h3>';
if (isset($responseXml) && is_array($responseXml) && !empty($responseXml)) {
echo '<table border="1">';
foreach ($responseXml[0] as $attributeArray) {
$attributeName = $attributeArray[0];
if (is_array($attributeArray[1])) {
$attributeValue = isset($attributeArray[1][2]) ? $attributeArray[1][2] : '';
} else {
$attributeValue = $attributeArray[1];
}
echo '<tr>';
echo '<td>' . $attributeName . '</td>';
echo '<td>' . $attributeValue . '</td>';
echo '</tr>';
}
echo '</table>';
}
} elseif(isset($_POST['getAllAudit'])) {
echo '<h3>Voilà tous les audits</h3>';
if (isset($responseXml) && is_array($responseXml) && !empty($responseXml)) {
$datas = $responseXml['tabdeploy'];
echo '<table border="1">';
echo '<tr>';
echo '<th>Session ID</th>';
echo '<th>Title</th>';
echo '<th>State</th>';
echo '<th>Voir les logs de l\'Audit</th>';
echo '</tr>';
foreach (array_keys($datas['sessionid']) as $key) {
echo '<tr>';
echo '<td>' . $datas['sessionid'][$key] . '</td>';
echo '<td>' . $datas['title'][$key] . '</td>';
echo '<td>' . $datas['state'][$key] . '</td>';
echo '<td>
<form method="post">
<input type="hidden" name="commandID" value="'.$datas['sessionid'][$key].'">
<button type="submit" name="getAudit">Voir les logs</button>
</form>
</td>';
echo '</tr>';
}
echo '</table>';
}
} elseif(isset($_POST['getAudit'])) {
echo '<h3>Voilà l\'Audit</h3>';
if (isset($responseXml) && is_array($responseXml) && !empty($responseXml)) {
$datas = $responseXml['log'];
echo '<table border="1">';
echo '<tr>';
echo '<th>Commande</th>';
echo '<th>Date</th>';
echo '<th>Log</th>';
echo '</tr>';
foreach ($datas as $value) {
echo '<tr>';
echo '<td>' . $value['sessionname'] . '</td>';
echo '<td>' . $value['date']->scalar . '</td>';
echo '<td>' . $value['text'] . '</td>';
echo '</tr>';
}
echo '</table>';
}
}
?>
</div>
</body>
</html>