initial commit

This commit is contained in:
2026-03-30 11:51:52 +02:00
commit 7ff76896e6
22 changed files with 1126 additions and 0 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

12
.idea/dataSources.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="GLPI" uuid="5410859a-b931-475a-8e05-b56dc692ad69">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://mys_glpi_prod.appliarmony.net:3306/GLPI</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

14
.idea/deployment.xml generated Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
<serverData>
<paths name="infra-reports">
<serverdata>
<mappings>
<mapping local="$PROJECT_DIR$" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
</component>
</project>

View File

@@ -0,0 +1,46 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredUrls">
<list>
<option value="http://" />
<option value="http://0.0.0.0" />
<option value="http://127.0.0.1" />
<option value="http://activemq.apache.org/schema/" />
<option value="http://cxf.apache.org/schemas/" />
<option value="http://java.sun.com/" />
<option value="http://javafx.com/fxml" />
<option value="http://javafx.com/javafx/" />
<option value="http://json-schema.org/draft" />
<option value="http://localhost" />
<option value="http://maven.apache.org/POM/" />
<option value="http://maven.apache.org/xsd/" />
<option value="http://primefaces.org/ui" />
<option value="http://schema.cloudfoundry.org/spring/" />
<option value="http://schemas.xmlsoap.org/" />
<option value="http://tiles.apache.org/" />
<option value="http://www.ibm.com/webservices/xsd" />
<option value="http://www.jboss.com/xml/ns/" />
<option value="http://www.jboss.org/j2ee/schema/" />
<option value="http://www.springframework.org/schema/" />
<option value="http://www.springframework.org/security/tags" />
<option value="http://www.springframework.org/tags" />
<option value="http://www.thymeleaf.org" />
<option value="http://www.w3.org/" />
<option value="http://xmlns.jcp.org/" />
</list>
</option>
</inspection_tool>
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpInconsistentReturnPointsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpMissingReturnTypeInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/wsinfra.iml" filepath="$PROJECT_DIR$/.idea/wsinfra.iml" />
</modules>
</component>
</project>

28
.idea/php.xml generated Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/include" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.4">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpRuntimeConfiguration" document_root_path="." />
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

6
.idea/sqldialects.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="PROJECT" dialect="TSQL" />
</component>
</project>

14
.idea/webResources.xml generated Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebResourcesPaths">
<contentEntries>
<entry url="file://$PROJECT_DIR$">
<entryData>
<resourceRoots>
<path value="file://$PROJECT_DIR$" />
</resourceRoots>
</entryData>
</entry>
</contentEntries>
</component>
</project>

8
.idea/wsinfra.iml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

125
Glpi/Assign-Ticket.php Normal file
View File

@@ -0,0 +1,125 @@
<?php
// Bypass Auth on API Call
define('IS_API', true);
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin,[
'http://infra-tools.appliarmony.net',
'https://infra-tools.appliarmony.net',
'https://web-infra-reports.process.dkm'
], true)) {
header("Access-Control-Allow-Origin: $origin");
header("Vary: Origin");
}
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Accept');
header('Content-Type: application/json; charset=utf-8');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
// Web-Service Common
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$rc=999;$stdout="?";$actor=$_SERVER['COMPUTERNAME'];$done=0;
$input = file_get_contents('php://input');
$json = json_decode($input, true);
$SourceUser = $json['source'] ?? $_SERVER['CURRENTUSER'] ?? null;
// Main
$ticketId = (int)$json['ticketId'];
$userId = (int)$json['userId'];
// 1) initSession
$initPayload = $glpiUserToken
? ['user_token' => $glpiUserToken]
: ['login' => 'glpi', 'password' => 'glpi'];
$ch = curl_init(rtrim($glpiUrl, '/') . '/initSession');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'App-Token: ' . $glpiAppToken,
],
CURLOPT_POSTFIELDS => json_encode($initPayload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$initResp = curl_exec($ch);
if ($initResp === false) {
die('initSession cURL error: ' . curl_error($ch));
}
$initJson = json_decode($initResp, true);
curl_close($ch);
if (empty($initJson['session_token'])) {
die("initSession failed:\n$initResp");
}
$sessionToken = $initJson['session_token'];
// 2) Update the ticket using POST
$tuPayload = [
'input' => [
'tickets_id' => $ticketId,
'users_id' => $userId,
'type' => 2 // 1=requester, 2=assigned, 3=observer
]
];
$ch = curl_init(rtrim($glpiUrl, '/') . '/Ticket_User');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'App-Token: ' . $glpiAppToken,
'Session-Token: ' . $sessionToken,
],
CURLOPT_POSTFIELDS => json_encode($tuPayload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$tuResp = curl_exec($ch);
$tuCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($tuResp === false) {
die('Ticket_User add cURL error: ' . curl_error($ch));
}
curl_close($ch);
$rc=0;$done=1;$stdout="Ticket $ticketId assigned to $userId ";
// 3) If Zabbix Ticket --> Call acknowledge WS
$rs = Invoke_glpi("SELECT name, content FROM glpi_tickets WHERE id=$ticketId");
$ticketName = $rs[0]['name'] ?? '';
$ticketContent = $rs[0]['content'] ?? '';
if (preg_match('/eventid=(\d+)/', $ticketContent, $m)) {
$eventId = $m[1];
$payload = json_encode(['eventId' => $eventId]);
// Detect Zabbix source
if (str_contains($ticketName, 'ZABBIX OT |')) {
// Zabbix OT Case
postJson("$BaseUrl/Zabbix/Acknowledge-OT-Event.php", $payload);
$stdout .= "| Zabbix OT Acknowledged (Event $eventId)";
}
elseif (str_contains($ticketName, 'ZABBIX IT |')) {
// Zabbix IT Case
postJson("$BaseUrl/Zabbix/Acknowledge-IT-Event.php", $payload);
$stdout .= "| Zabbix IT Acknowledged (Event $eventId)";
}
}
//Answer
$response = [
"RC" => $rc,
"stdout" => $stdout,
];
header('Content-Type: application/json; charset=utf-8');
echo json_encode($response, JSON_UNESCAPED_UNICODE);
// Log to dedicated Table
log2DB();
?>

96
Glpi/Create-Ticket.php Normal file
View File

@@ -0,0 +1,96 @@
<?php
header('Content-Type: application/json');
// 1. Configuration - A ajuster selon ton environnement de prod
$api_url = "https://web-glpi-aim.process.dkm/glpi/apirest.php";
$user_token = "EgoVX0XYLK9SZi5dAyxRUPR8Te2rmmQbunaVpySO";
$app_token = "LQMIylSMr1qIAHh1OdYY8zP6MIyKEIKRt8mJbO6G";
// 2. Mapping des groupes et entités
$groups_mapping = [
"INFRADK" => 13,
"MIPSDK" => 50,
"NETWORKDK" => 60
];
$entities_mapping = [
"OT" => 1,
"IT" => 6
];
// 3. Récupération du JSON
$input = file_get_contents('php://input');
$data = json_decode($input, true);
if (!$data) {
echo json_encode(["RC" => 1, "stdout" => "Invalid JSON input"]);
exit;
}
// 4. Initialisation de la session GLPI
function callGLPI($url, $method = 'GET', $headers = [], $postFields = null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Souvent nécessaire en interne
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($postFields) curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
$result = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($err) return ["error" => $err];
return json_decode($result, true);
}
// Get Session Token
$session = callGLPI("$api_url/initSession", "GET", [
"App-Token: $app_token",
"Authorization: user_token $user_token"
]);
if (!isset($session['session_token'])) {
echo json_encode(["RC" => 1, "stdout" => "GLPI Auth Failed: " . json_encode($session)]);
exit;
}
$sess_token = $session['session_token'];
$headers = [
"Content-Type: application/json",
"App-Token: $app_token",
"Session-Token: $sess_token"
];
// 5. Création du Ticket
$groupId = $groups_mapping[$data['group']] ?? 13; //infra par défaut
$entityId = $entities_mapping[$data['entity']] ?? 1; //OT par défaut
$ticketPayload = json_encode([
"input" => [
"name" => $data['title'],
"content" => $data['description'] . "<br> Source: " . $data['source'],
"type" => 1,
"requesttypes_id" => 15,
"itilcategories_id" => 46,
"_groups_id_assign" => $groupId,
"urgency" => 3,
"impact" => 3,
"priority" => 3,
"entities_id" => $entityId,
"users_id_recipient" => 25255
]
]);
$response = callGLPI("$api_url/Ticket", "POST", $headers, $ticketPayload);
// 6. Fermeture session et retour
callGLPI("$api_url/killSession", "GET", $headers);
if (isset($response['id'])) {
echo json_encode(["RC" => 0, "stdout" => "Ticket created ID: " . $response['id']]);
} else {
echo json_encode(["RC" => 1, "stdout" => "API Error: " . json_encode($response)]);
}

View File

@@ -0,0 +1,12 @@
<?php
// Web-Service Common
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$rc=999;$stdout="?";$actor=$_SERVER['COMPUTERNAME'];$done=0;
$SourceUser = $json['source'] ?? $_SERVER['CURRENTUSER'] ?? null;
// Main
$list = Invoke_Entry01("SELECT distinct(server), policy FROM `infra`.`nb_jobs_full` where status = 4287 and server not like '%vmh%' and policy like '%vmh-%'");
$output = json_encode($list, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo $output;
?>

View File

@@ -0,0 +1,12 @@
<?php
// Web-Service Common
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$rc=999;$stdout="?";$actor=$_SERVER['COMPUTERNAME'];$done=0;
$SourceUser = $json['source'] ?? $_SERVER['CURRENTUSER'] ?? null;
// Main
$list = Invoke_Entry01("SELECT distinct(server), policy FROM `infra`.`nb_jobs_full` where status = 4287 and server not like '%hv%' and policy like '%SRV-%'");
$output = json_encode($list, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo $output;
?>

View File

@@ -0,0 +1,58 @@
<?php
// Bypass Auth on API Call
define('IS_API', true);
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, ['http://infra-tools.appliarmony.net','https://infra-tools.appliarmony.net'], false)) {
header("Access-Control-Allow-Origin: $origin");
header("Vary: Origin");
}
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Accept');
header('Content-Type: application/json; charset=utf-8');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
// Web-Service Common
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$rc=999;$stdout="?";$actor=$_SERVER['COMPUTERNAME'];$done=0;
$input = file_get_contents('php://input');
$json = json_decode($input, true);
$SourceUser = $json['source'] ?? $_SERVER['CURRENTUSER'] ?? null;
// Main
$lun = $json['lun'];
$pos = strrpos($lun, '_');
if ($pos) {
$hostname = substr($lun, 0, $pos);
$extension = substr($lun, $pos + 1);
$result = [
'Hostname' => $hostname,
'Extension' => $extension,
];
$json = json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$answer = PostJson("$bdnuss/Storage/SVC/VOLUME/SVC_VOLUME_DELETE.php", $json);
$rc = (int)json_decode($answer, true)['RC'] ?? 1;
$stdout = json_decode($answer, true)['Msg'] ?? 'Unknown error';
if ($rc === 0) {$done = 1;}
$result = [
'RC' => $rc,
'StdOut' => $stdout,
];
$json = json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}else{
$result = [
'RC' => 1,
'StdOut' => "Invalid LUN format",
];
$json = json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
// Send Answer
echo $json;
// Log to dedicated Table
log2DB();

View File

@@ -0,0 +1,50 @@
<?php
// Web-Service Common
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$rc=999;$stdout="?";$actor=$_SERVER['COMPUTERNAME'];$done=0;
$input = file_get_contents('php://input');
$json = json_decode($input, true);
$SourceUser = $json['source'] ?? $_SERVER['CURRENTUSER'] ?? null;
// Main
$eventId = (int)$json['eventId'];
$ackMessage = "Acknowledged by Infra Web-Service";
echo $eventId;
// 1) Acknowledge the event
$ackPayload = json_encode([
'jsonrpc' => '2.0',
'method' => 'event.acknowledge',
'params' => [
'eventids' => [$eventId],
'action' => 6,
'message' => $ackMessage
],
'id' => 1
]);
$ch = curl_init($zabbixITUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-type: application/json',
'charset=utf-8',
'Authorization: Bearer ' . $zabbixITToken
],
CURLOPT_POSTFIELDS => $ackPayload,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$ackResp = curl_exec($ch);
$ackCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$rc=0;$done=1;$stdout="Event $eventId Acknowledged";
// Log to dedicated Table
log2DB();
?>

View File

@@ -0,0 +1,50 @@
<?php
// Web-Service Common
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$rc=999;$stdout="?";$actor=$_SERVER['COMPUTERNAME'];$done=0;
$input = file_get_contents('php://input');
$json = json_decode($input, true);
$SourceUser = $json['source'] ?? $_SERVER['CURRENTUSER'] ?? null;
// Main
$eventId = (int)$json['eventId'];
$ackMessage = "Acknowledged by Infra Web-Service";
echo $eventId;
// 1) Acknowledge the event
$ackPayload = json_encode([
'jsonrpc' => '2.0',
'method' => 'event.acknowledge',
'params' => [
'eventids' => [$eventId],
'action' => 6,
'message' => $ackMessage
],
'id' => 1
]);
$ch = curl_init($zabbixOTUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-type: application/json',
'charset=utf-8',
'Authorization: Bearer ' . $zabbixOTToken
],
CURLOPT_POSTFIELDS => $ackPayload,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$ackResp = curl_exec($ch);
$ackCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$rc=0;$done=1;$stdout="Event $eventId Acknowledged";
// Log to dedicated Table
log2DB();
?>

45
auth/set-whoami.php Normal file
View File

@@ -0,0 +1,45 @@
<?php
// Accepts JSON { user: "DOM\\user" } from same-origin JS and sets cookie
header('Content-Type: application/json; charset=utf-8');
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$referer = $_SERVER['HTTP_REFERER'] ?? '';
$allowed = 'https://opwsinf.appliarmony.net';
$ok = false;
if ($origin && stripos($origin, $allowed) === 0) $ok = true;
if ($referer && stripos($referer, $allowed) === 0) $ok = true;
if (!$ok) {
http_response_code(403);
echo json_encode(['error'=>'forbidden origin']);
exit;
}
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
if (!is_array($data) || empty($data['user'])) {
http_response_code(400);
echo json_encode(['error'=>'invalid payload']);
exit;
}
$user = $data['user'];
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
$cookie = [
'user' => $user,
'ip' => $ip,
'created' => date('Y-m-d H:i:s'),
'last' => date('Y-m-d H:i:s'),
];
// Cookie host-only (no Domain) ;
setcookie('UserInfo', json_encode($cookie), [
'expires' => time() + 86400*365,
'path' => '/',
// 'domain' => '.appliarmony.net',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
echo json_encode(['ok'=>true, 'user'=>$user]);

11
auth/whoami.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
header('Content-Type: application/json; charset=utf-8');
$user = $_SERVER['REMOTE_USER'] ?? null;
if (!$user) {
http_response_code(401);
echo json_encode(['error'=>'no-user']);
exit;
}
echo json_encode(['user' => $user]);

460
include/all.php Normal file
View File

@@ -0,0 +1,460 @@
<?php
// ---------- General Helpers ----------
function instr($string, $search){
return str_contains($string, $search);
}
function PostJson($url, $content){
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-type: application/json","charset=utf-8"]);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $content);
curl_setopt($curl, CURLOPT_USERNAME, "test");
$retour = curl_exec($curl);
curl_close($curl);
return $retour;
}
function Read_HTML($url){
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$retour = curl_exec($curl);
curl_close($curl);
return $retour;
}
function getSourceInfo(): string {
$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN_IP';
$remoteUser = $_SERVER['REMOTE_USER'] ?? '';
$hostname = @gethostbyaddr($remoteAddr);
$sourceMachine = ($hostname && $hostname !== $remoteAddr) ? explode('.', $hostname)[0] : $remoteAddr;
$sourceUser = '';
if (!empty($remoteUser)) {
$userParts = explode('\\', $remoteUser);
$sourceUser = end($userParts);
}
return !empty($sourceUser) ? "$sourceUser on $sourceMachine" : $sourceMachine;
}
function decypher(string $name): ?string {
$openssl = 'C:\Program Files\FireDaemon OpenSSL 3\bin\openssl.exe';
$cmsFile = "F:\\Include\\dat\\$name.p7m";
$certPem = "F:\\Include\\certs\\cert_only.pem";
$keyPem = "F:\\Include\\certs\\key_only.pem";
foreach ([$openssl,$cmsFile,$certPem,$keyPem] as $p) {
if (!is_file($p)) { error_log("Missing file: $p"); return null; }
}
$cmd = '"' . $openssl . '" cms -decrypt -inform PEM'
. ' -in ' . escapeshellarg($cmsFile)
. ' -recip ' . escapeshellarg($certPem)
. ' -inkey ' . escapeshellarg($keyPem)
. ' -out -';
$spec = [
0 => ['pipe','r'],
1 => ['pipe','w'],
2 => ['pipe','w'],
];
$proc = proc_open($cmd, $spec, $pipes);
if (!is_resource($proc)) { error_log('proc_open failed'); return null; }
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($proc);
if ($code !== 0) {
error_log("OpenSSL failed (code $code): $stderr");
return null;
}
return $stdout;
}
// ---------- DB logging ----------
function log2DB(){
global $input, $done, $rc, $stdout, $SourceUser, $actor;
// Table name
$parts = explode("/", ltrim($_SERVER['SCRIPT_NAME'], '/'));
$ws = strtoupper($parts[0]) . "_" . strtolower($parts[count($parts)-1]);
$ws = str_replace(".php", "", $ws);
$ws = preg_replace('/[^A-Za-z0-9_]/', '_', $ws);
$table = "[dbo].[" . str_replace(']', ']]', $ws) . "]";
// Create table if missing
$create = "
IF OBJECT_ID(N'$table', N'U') IS NULL
BEGIN
CREATE TABLE $table (
idx INT IDENTITY PRIMARY KEY,
ts NVARCHAR(20),
source NVARCHAR(256),
input NVARCHAR(MAX),
actor NVARCHAR(64),
done INT,
rc INT,
stdout NVARCHAR(MAX)
);
END";
Invoke_WSinfra($create);
// Prepare insertion
$ts = date("Y-m-d H:i:s");
$cutmp = $GLOBALS['CURRENT_USER'] ?? (defined('CURRENT_USER') ? CURRENT_USER : 'Anonymous');
$cu = $SourceUser ?? $cutmp;
$ci = $GLOBALS['CURRENT_IP'] ?? (defined('CURRENT_IP') ? CURRENT_IP : ($_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN'));
$s = @gethostbyaddr($ci);
if ($s && $s !== ($_SERVER['X_FORWARDED_FOR'] ?? '')) {
if (!filter_var($s, FILTER_VALIDATE_IP)) {$s = explode('.', $s)[0];}
}
$source = str_replace('\\','_', $cu) . " on " . ($s ?: $ci);
$esc = function($v){ return str_replace("'", "''", (string)$v); };
$ts_e = $esc($ts);
$source_e = $esc($source);
$input_e = $esc($input ?? '');
$stdout_e = $esc($stdout ?? '');
$actor_e = $esc($actor ?? '');
// Insert
$sqlIns = "
INSERT INTO $table (ts, source, input, actor, done, rc, stdout)
VALUES (N'$ts_e', N'$source_e', N'$input_e', N'$actor_e', $done, $rc, N'$stdout_e')";
Invoke_WSinfra($sqlIns);
}
// ---------- DB connections ----------
function Invoke_WebSelfInfra($request){
$user = "Scom-Write";
$pwd = decypher("web-self-infra");
$server = "DUN-PRD-R1SCOM.armony.net\OPS";
$database = "web-self-infra";
$conn = odbc_connect("Driver={SQL Server};Server=$server;Database=$database;", $user, $pwd);
$rs = odbc_exec($conn, $request);
if (instr(strtoupper($request), "SELECT")) {
while ($row = odbc_fetch_array($rs)) {
$answer[] = $row;
}
}
if (isset($answer)) {
return $answer;
}
}
function Invoke_SCOMInfra($request){
$user = "Scom-Write";
$pwd = decypher("scom-infra");
$server = "DUN-PRD-R1SCOM.armony.net\OPS";
$database = "infra";
$conn = odbc_connect("Driver={SQL Server};Server=$server;Database=$database", $user, $pwd);
if (!($conn)) { echo "Pas de connexion"; }
$rs = odbc_exec($conn, $request);
if (instr(strtoupper($request), "SELECT")) {
while ($row = odbc_fetch_array($rs)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
}
function Invoke_Entry01($request){
$user = "infra";
$pwd = decypher("entry01");
$server = "dun-sup-entry01:3306";
$database = "infra";
$conn = new mysqli($server, $user, $pwd, $database);
$rs = $conn->query($request);
$answer = [];
if (instr(strtoupper($request), "SELECT")) {
while ($row = mysqli_fetch_array($rs, MYSQLI_ASSOC)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
}
function Invoke_WebInfraTools($request){
$user = "admin";
$pwd = decypher("web-infra-tools");
$server = "dun-sup-s2entry.armony.net:3306";
$database = "webinfratools";
$conn = new mysqli($server, $user, $pwd, $database);
$rs = $conn->query($request);
$answer = [];
if (instr(strtoupper($request), "SELECT")) {
while ($row = mysqli_fetch_array($rs, MYSQLI_ASSOC)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
}
function Invoke_Infra($request){
error_reporting(E_ALL ^ E_WARNING);
$user = "INFRA_dbo";
$pwd = decypher("infra");
$server = "DUN-PRD-R1MSSQL.armony.net\PRD";
$database = "INFRA";
$conn = odbc_connect("Driver={SQL Server};Server=$server;Database=$database;", $user, $pwd);
if (!($conn)) { echo "Pas de connexion"; }
$rs = odbc_exec($conn, $request);
if (instr(strtoupper($request), "SELECT")) {
while ($row = odbc_fetch_array($rs)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
else {
if ($rs) { return "OK"; }
else { error_reporting(E_ALL); return "ERROR : " . odbc_errormsg($conn); }
}
}
function Invoke_WSinfra($request){
error_reporting(E_ALL ^ E_WARNING);
$user = "WSINFRA_ADMIN";
$pwd = decypher("wsinfraDB");
$server = "DUN-PRD-R1MSSQL.armony.net\PRD";
$database = "WSINFRA";
$conn = odbc_connect("Driver={SQL Server};Server=$server;Database=$database;", $user, $pwd);
if (!($conn)) { echo "Pas de connexion"; }
$rs = odbc_exec($conn, $request);
if (instr(strtoupper($request), "SELECT")) {
while ($row = odbc_fetch_array($rs)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
else {
if ($rs) { return "OK"; }
else { error_reporting(E_ALL); return "ERROR : " . odbc_errormsg($conn); }
}
}
function Invoke_aixcmdb($request){
error_reporting(E_ALL ^ E_WARNING);
$conn_string = "DRIVER={IBM DB2 ODBC DRIVER};"
. "DATABASE=AIXCMDB; "
. "HOSTNAME=db2_aixcmdb.appliarmony.net;"
. "PORT=50000; "
. "PROTOCOL=TCPIP; "
. "UID=aixcmdb;"
. "AUTHENTICATION=SERVER;"
. "PWD=" . decypher('aixcmdb') . ";";
$conn = odbc_connect($conn_string, "", "");
if (!($conn)) { echo "Pas de connexion"; }
$rs = odbc_exec($conn, $request);
if (instr(strtoupper($request), "SELECT")) {
while ($row = odbc_fetch_array($rs)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
else {
if ($rs) { return "OK"; }
else { error_reporting(E_ALL); return "ERROR : " . odbc_errormsg($conn); }
}
}
function Invoke_zabbix($request){
$user = "patrick";
$pwd = decypher("zabbix");
$server = "aztprdzabbix52.armony.net:3306";
$database = "zabbix";
$conn = new mysqli($server, $user, $pwd, $database);
$rs = $conn->query($request);
$answer = [];
if (instr(strtoupper($request), "SELECT")) {
while ($row = mysqli_fetch_array($rs, MYSQLI_ASSOC)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
}
function Invoke_glpi($request){
$user = "glpi_lect_seule";
$pwd = decypher("glpi");
$server = "mys_glpi_prod.appliarmony.net:3306";
$database = "glpi";
$conn = new mysqli($server, $user, $pwd, $database);
$rs = $conn->query($request);
$answer = [];
if (instr(strtoupper($request), "SELECT")) {
while ($row = mysqli_fetch_array($rs, MYSQLI_ASSOC)) { $answer[] = $row; }
}
if (isset($answer)) { return $answer; }
}
// ---------- CONSTANTS & common ----------
$BaseUrl = "https://".$_SERVER['SERVER_NAME'];
$root = $_SERVER['DOCUMENT_ROOT'];
$bdnuss = "http://web-bdnuss-sys-dev.appliarmony.net";
$opwsinf = "https://wsopinf.appliarmony.net";
$zabbixOTUrl = 'https://web-zabbix.process.dkm/zabbix/api_jsonrpc.php';
$zabbixITUrl = 'https://web-zabbix02.appliarmony.net/zabbix/api_jsonrpc.php';
$glpiUrl = 'https://web-glpi-aim.process.dkm/glpi/apirest.php';
// Servers
$dcArmony = "dun-dom-s1dcb";
$dcADArmony = "dun-dom-s1adinf.adarmony.net";
$uxDNS = "dun-com-uxdns01";
$sSCOM = "dun-prd-x1scom";
$sVMM = "dun-sup-s1vmmsv";
// Credentials
$ILOcreds = "Administrator:".decypher("ilo");
$zabbixOTToken = '697132149e1e17058abe455cce7d45e18759539962185a5ea689445b271328ed';
$zabbixITToken = '0551c017d82b00abcf7e0222867731c9a6fb82a276f16cab9a38f077d61d4ebd';
$glpiAppToken = '0Cearpj5pRyCVj4hE7muZmaEgJp8uwbq84fYKlHa';
$glpiUserToken = 'iorbtVjXpwKoo2woYBu1UmZmGTq2xp64CdLtfgkn';
// Identity & Cookie
/* ---------- Detect client ---------- */
function detect_client_name(): string
{
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
$ua_l = strtolower($ua);
// Tokens explicites
$map = [
'powershell' => ['powershell', 'windowspowershell', 'invoke-webrequest'],
'curl' => ['curl/'],
'wget' => ['wget/'],
'python' => ['python-requests', 'urllib', 'python/'],
'postman' => ['postmanruntime'],
'go' => ['go-http-client'],
'nodejs' => ['node-fetch', 'axios/', 'undici', 'node.js', 'nodejs'],
'java' => ['java/', 'apache-httpclient/'],
'php' => ['php/', 'guzzlehttp/'],
];
foreach ($map as $name => $needles) {
foreach ($needles as $n) {
if ($n !== '' && str_contains($ua_l, $n)) return $name;
}
}
// Heuristique “script Mozilla sans en-têtes modernes”
$hasMozilla = stripos($ua, 'Mozilla/') !== false;
$hasSecFetch = isset($_SERVER['HTTP_SEC_FETCH_MODE']) || isset($_SERVER['HTTP_SEC_FETCH_SITE']) || isset($_SERVER['HTTP_SEC_FETCH_DEST']);
$hasSecCH = isset($_SERVER['HTTP_SEC_CH_UA']) || isset($_SERVER['HTTP_SEC_CH_UA_PLATFORM']);
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
$looksLikeScriptAccept = (trim($accept) === '' || $accept === '*/*');
if ($hasMozilla && !$hasSecFetch && !$hasSecCH && $looksLikeScriptAccept) return 'powershell';
return ($ua === '') ? 'shell' : 'browser';
}
function isBrowser(): bool
{
$client = detect_client_name();
if ($client !== 'browser') return false;
$hasSecFetch = isset($_SERVER['HTTP_SEC_FETCH_MODE']) || isset($_SERVER['HTTP_SEC_FETCH_SITE']) || isset($_SERVER['HTTP_SEC_FETCH_DEST']);
$hasSecCH = isset($_SERVER['HTTP_SEC_CH_UA']) || isset($_SERVER['HTTP_SEC_CH_UA_PLATFORM']);
return $hasSecFetch || $hasSecCH;
}
/* ---------- Identity & cookie ---------- */
function Set_Cookie() {
$cookieName = 'UserInfo';
$cookieLife = 86400 * 365;
$cookieDomain = '.appliarmony.net';
$secureFlag = true;
$httpOnly = true;
$sameSite = 'Lax';
$now = date('Y-m-d H:i:s');
// IP client (XFF -> fallback REMOTE_ADDR)
$ip = '';
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$cand = trim($parts[0]);
if (filter_var($cand, FILTER_VALIDATE_IP)) $ip = $cand;
}
if (!$ip && !empty($_SERVER['REMOTE_ADDR'])) $ip = $_SERVER['REMOTE_ADDR'];
// REMOTE_USER ?
$user = $_SERVER['REMOTE_USER'] ?? null;
$hasUser = !empty($user);
// Cookie existant
$cookie = [];
if (!empty($_COOKIE[$cookieName])) {
$decoded = json_decode($_COOKIE[$cookieName], true);
if (is_array($decoded)) $cookie = $decoded;
}
// Si pas d'user → classer le client (curl/pwsh/…/Anonymous)
if (!$hasUser) {
// même logique que detect_client_name() pour rester cohérent
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
$ua_l = strtolower($ua);
$map = [
'powershell' => ['powershell','windowspowershell','invoke-webrequest'],
'curl' => ['curl/'],
'wget' => ['wget/'],
'python' => ['python-requests','urllib','python/'],
'postman' => ['postmanruntime'],
'go' => ['go-http-client'],
'nodejs' => ['node-fetch','axios/','undici','node.js','nodejs'],
'java' => ['java/','apache-httpclient/'],
'php' => ['php/','guzzlehttp/'],
];
$user = 'Anonymous';
foreach ($map as $name => $needles) {
foreach ($needles as $n) { if ($n !== '' && str_contains($ua_l, $n)) { $user = $name; break 2; } }
}
if ($user === 'Anonymous') {
$hasMozilla = stripos($ua, 'Mozilla/') !== false;
$hasSecFetch = isset($_SERVER['HTTP_SEC_FETCH_MODE']) || isset($_SERVER['HTTP_SEC_FETCH_SITE']) || isset($_SERVER['HTTP_SEC_FETCH_DEST']);
$hasSecCH = isset($_SERVER['HTTP_SEC_CH_UA']) || isset($_SERVER['HTTP_SEC_CH_UA_PLATFORM']);
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
$looksLikeScriptAccept = (trim($accept) === '' || $accept === '*/*');
if ($hasMozilla && !$hasSecFetch && !$hasSecCH && $looksLikeScriptAccept) {
$user = 'powershell';
} elseif ($ua === '') {
$user = 'shell';
}
}
}
// Écriture du cookie UNIQUEMENT si vrai REMOTE_USER
if ($hasUser) {
if (empty($cookie) || ($cookie['user'] ?? null) !== $user) {
$cookie = [ 'user'=>$user, 'ip'=>$ip, 'created'=>$now, 'last'=>$now ];
} else {
$cookie['ip'] = $ip ?: ($cookie['ip'] ?? '');
$cookie['last'] = $now;
}
if (!headers_sent()) {
setcookie($cookieName, json_encode($cookie), [
'expires' => time() + $cookieLife,
'path' => '/',
'domain' => $cookieDomain,
'secure' => $secureFlag,
'httponly' => $httpOnly,
'samesite' => $sameSite
]);
}
}
// Publier VARIABLES (mutables) + constantes (compat)
$GLOBALS['CURRENT_USER'] = $user ?? 'Anonymous';
$GLOBALS['CURRENT_IP'] = $ip ?: ($_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN');
if (!defined('CURRENT_USER')) define('CURRENT_USER', $GLOBALS['CURRENT_USER']);
if (!defined('CURRENT_IP')) define('CURRENT_IP', $GLOBALS['CURRENT_IP']);
if (!defined('COOKIE_INFO')) define('COOKIE_INFO', $cookie);
}
/* ----- IMPORTANT : Call Set_Cookie() Now ----- */
Set_Cookie();
/* ----- If still Anonymous and real browser → try silent SSO ----- */
if (($GLOBALS['CURRENT_USER'] ?? 'Anonymous') === 'Anonymous' && isBrowser()) {
echo <<<HTML
<script>
(async function(){
try {
const res = await fetch('/auth/whoami.php', { method: 'GET', credentials: 'include' });
if (res.ok) {
const j = await res.json();
if (j && j.user) {
await fetch('/auth/set-whoami.php', {
method:'POST',
credentials:'include',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({user:j.user})
});
}
}
} catch(e){}
})();
</script>
HTML;
}

24
index.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$ip = defined('CURRENT_IP') ? CURRENT_IP : ($_SERVER['REMOTE_ADDR'] ?? '');
$s = $ip; // fallback par défaut = lIP brute
if ($ip && filter_var($ip, FILTER_VALIDATE_IP)) {
try {
$h = @gethostbyaddr($ip); // @ pour éviter le warning DNS
if ($h && $h !== $ip) {
$s = explode('.', $h)[0]; // court hostname
}
} catch (ValueError $e) {
// IP invalide → on garde $s = $ip
}
} elseif (!$ip) {
$s = 'UNKNOWN_IP';
}
$u = CURRENT_USER ?? "Anonymous";
echo "Hello $u <br>";
echo "Having fun navigating from $s ? <br>";
echo "Nothing to see in here ;) <br>";
echo "<b>Every action is logged !</b> <br>";
?>

12
test.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$input = file_get_contents('php://input');
$data = json_decode($input, true);
if (!$data) {
//echo json_encode(["RC" => 1, "stdout" => "Invalid JSON input"]);
echo $_GET['test'];
exit;
}
echo "envoyé : ".$data['test'];
?>

27
web.config Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpErrors errorMode="Detailed" />
<rewrite>
<rules>
<rule name="Rewrite to PHP" stopProcessing="true">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_FILENAME}.php" matchType="IsFile" />
</conditions>
<action type="Rewrite" url="{R:1}.php" />
</rule>
<rule name="Redirect Extensionless" stopProcessing="true">
<match url="^(.*)\.php$" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_METHOD}" pattern="^GET$" />
</conditions>
<action type="Redirect" url="{R:1}" redirectType="Found" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>