Skip to main content

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>