Compare commits

6 Commits
dev ... main

5 changed files with 104 additions and 16 deletions

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
cryptography
requests
toml

View File

@ -2,6 +2,7 @@
import os import os
import argparse import argparse
import logging import logging
import time
from functions import getSettings from functions import getSettings
from includes.airwatchAPI import * from includes.airwatchAPI import *
from includes.GLPIAPI import * from includes.GLPIAPI import *
@ -67,12 +68,20 @@ if(args.staginguser != None):
# ====================================== # # ====================================== #
# Vérification de la présence du verrou avant de continuer # Vérification de la présence du verrou avant de continuer
if(os.path.isfile(lockFile) and not args.force): if(os.path.isfile(lockFile) and not args.force):
# Récupération du temps de création de verrou en minutes
lockTime = (time.time() - os.path.getmtime(lockFile)) // 60
# Recréation du verrou s'il existe depuis plus de 3 heures (crash)
# sinon on quitte, une synchro est déjà en cours
if(lockTime > 180):
os.remove(lockFile)
open(lockFile, "w").close()
else:
logger.debug('Lock file exists, exiting...') logger.debug('Lock file exists, exiting...')
exit(0) exit(0)
else: else:
# Création du verrou s'il n'existe pas
open(lockFile, "w").close() open(lockFile, "w").close()
# Initialisation de l'api Airwatch # Initialisation de l'api Airwatch

View File

@ -5,6 +5,7 @@ def getSettings(settingsPath):
settingsDefault =""" settingsDefault ="""
[AIRWATCH] [AIRWATCH]
Server = "https://airwatchServer" Server = "https://airwatchServer"
ConsoleURI = "https://airwatchConsole"
APIKey = "APIKEY" APIKey = "APIKEY"
# Méthode d'authentification (CMSURL or PASSWORD) # Méthode d'authentification (CMSURL or PASSWORD)

View File

@ -61,6 +61,27 @@ class GLPIAPI:
return None, None, 0 return None, None, 0
return None, None, None return None, None, None
def GetUser(self, username=None, email=None):
if(username != None):
search_parameter = f'is_deleted=0&criteria[0][field]=1&withindexes=true&criteria[0][searchtype]=contains&criteria[0][value]=^{username}$'
elif(email != None):
search_parameter = f'is_deleted=0&criteria[0][field]=5&withindexes=true&criteria[0][searchtype]=contains&criteria[0][value]=^{email}$'
searchUri = f"{self.Server}/apirest.php/search/user?{search_parameter}"
search = requests.get(searchUri, headers=self.Headers)
if(search.status_code == 200):
search = search.json()
if(search["totalcount"] == 1):
userID = list(search["data"].keys())[0]
data = search["data"][userID]
return userID, data, search["totalcount"]
elif(search["totalcount"] > 1):
userID = list(search["data"].keys())
return userID, search["data"], search["totalcount"]
else:
return None, None, 0
def UpdateInventory(self, inventory): def UpdateInventory(self, inventory):
headers = { headers = {
"Content-Type":"Application/x-compress", "Content-Type":"Application/x-compress",
@ -90,11 +111,22 @@ class GLPIAPI:
uri = f"{self.Server}/apirest.php/Computer/" uri = f"{self.Server}/apirest.php/Computer/"
return requests.put(uri, headers=self.Headers, json=body) return requests.put(uri, headers=self.Headers, json=body)
def UpdateAirwatchLink(self, deviceid, airwatchlink):
body = {
"input": {
"id": deviceid,
"appareilsurmagentafield": airwatchlink
}
}
uri = f"{self.Server}/apirest.php/Computer/"
return requests.put(uri, headers=self.Headers, json=body)
def CreateInventoryForAirwatchDevice(self, device, deviceName, apps=None): def CreateInventoryForAirwatchDevice(self, device, deviceName, apps=None):
platforms = { platforms = {
2:"Apple iOS", 2:"Apple iOS",
5:"Android", 5:"Android",
12:"Windows Desktop" 12:"Windows"
} }
if(device.PlatformId in platforms.keys()): if(device.PlatformId in platforms.keys()):
@ -119,9 +151,27 @@ class GLPIAPI:
osArch = "Unknown" osArch = "Unknown"
softwareArch = "Unknown" softwareArch = "Unknown"
windowsOSTranslation = {
"10.0.19043":"10 21H1",
"10.0.19044":"10 21H2",
"10.0.19045":"10 22H2",
"10.0.22000":"11 21H2",
"10.0.22621":"11 22H2",
"10.0.22631":"11 23H2",
"10.0.26100":"11 24H2",
"10.0.26200":"11 25H2"
}
logDate = datetime.strptime(device.LastSeen, "%Y-%m-%dT%H:%M:%S.%f").strftime("%Y-%m-%d %H:%M:%S") logDate = datetime.strptime(device.LastSeen, "%Y-%m-%dT%H:%M:%S.%f").strftime("%Y-%m-%d %H:%M:%S")
inventory = GLPIInventory(logdate=logDate, versionclient=self.UserAgent, tag=device.Group, deviceid=f"{deviceName} - {device.SerialNumber}", itemtype="Computer") inventory = GLPIInventory(logdate=logDate, versionclient=self.UserAgent, tag=device.Group, deviceid=f"{deviceName} - {device.SerialNumber}", itemtype="Computer")
if(platformName == "Windows"):
if(device.OS in windowsOSTranslation.keys()):
inventory.SetOperatingSystem(platformName, windowsOSTranslation[str(device.OS)], osArch)
else:
platformName = "Windows Desktop"
inventory.SetOperatingSystem(platformName, device.OS, osArch)
else:
inventory.SetOperatingSystem(platformName, device.OS, osArch) inventory.SetOperatingSystem(platformName, device.OS, osArch)
inventory.SetHardware(deviceName, device.Uuid, device.TotalMemory) inventory.SetHardware(deviceName, device.Uuid, device.TotalMemory)
inventory.AddUser(device.User) inventory.AddUser(device.User)

View File

@ -2,6 +2,7 @@
import os import os
import argparse import argparse
import logging import logging
import time
from datetime import datetime from datetime import datetime
from functions import getSettings from functions import getSettings
from includes.airwatchAPI import * from includes.airwatchAPI import *
@ -22,7 +23,7 @@ args = parser.parse_args()
if(args.configpath != None and args.configpath != ''): if(args.configpath != None and args.configpath != ''):
settings = getSettings(args.configpath) settings = getSettings(args.configpath)
else: else:
settings = getSettings("{os.path.realpath(os.path.dirname(__file__))}/conf/settings.conf") settings = getSettings(f"{os.path.realpath(os.path.dirname(__file__))}/conf/settings.conf")
#=========== Configuration des logs ===========# #=========== Configuration des logs ===========#
@ -105,11 +106,21 @@ platformFilterOut = [12]
# ====================================== # # ====================================== #
# Vérification de la présence du verrou avant de continuer # Vérification de la présence du verrou avant de continuer
if(os.path.isfile(lockFile) and not args.force): if(os.path.isfile(lockFile) and not args.force):
# Récupération du temps de création de verrou en minutes
lockTime = (time.time() - os.path.getmtime(lockFile)) // 60
# Recréation du verrou s'il existe depuis plus de 3 heures (crash)
# sinon on quitte, une synchro est déjà en cours
if(lockTime > 180):
os.remove(lockFile)
open(lockFile, "w").close()
else:
logger.debug('Lock file exists, exiting...') logger.debug('Lock file exists, exiting...')
exit(0) exit(0)
else: else:
# Création du verrou s'il n'existe pas
open(lockFile, "w").close() open(lockFile, "w").close()
logger.info("========= Synchronization started =========") logger.info("========= Synchronization started =========")
@ -204,17 +215,29 @@ for device in devices:
loggerDouble.error(f"{count} devices matching airwatch device {device.FriendlyName} (Airwatch id={device.Id}) in GLPI (GLPI ids = {', '.join(deviceID)}), skipping this device...") loggerDouble.error(f"{count} devices matching airwatch device {device.FriendlyName} (Airwatch id={device.Id}) in GLPI (GLPI ids = {', '.join(deviceID)}), skipping this device...")
continue continue
if(count == 0): if(count == 0):
loggerMissing.error(f"Device {device.FriendlyName} (id={device.Id}) not found in GLPI, is it in the trash bin ? Skipping device...") deviceIDTrash, dataTrash, countTrash = glpiapi.GetDevice(device)
if(countTrash > 1):
loggerDouble.error(f"{countTrash} devices matching airwatch device {device.FriendlyName} (Airwatch id={device.Id}) in GLPI trashbin (GLPI ids = {', '.join(deviceIDTrash)}), skipping this device...")
elif(countTrash == 1):
logger.warning(f"Device {device.FriendlyName} (Airwatch id={device.Id}) in GLPI trashbin (GLPI id={deviceIDTrash}), skipping...")
else:
loggerMissing.error(f"Device {device.FriendlyName} (Airwatch id={device.Id}) not found in GLPI.")
continue continue
inventory = glpiapi.CreateInventoryForAirwatchDevice(device, data["1"], apps) inventory = glpiapi.CreateInventoryForAirwatchDevice(device, data["1"], apps)
# Mise à jour du friendly name sur Airwatch # Mise à jour du friendly name sur Airwatch
platformName = inventory.operatingsystem["name"] platformName = inventory.operatingsystem["name"]
if(device.FriendlyName != f"{data['1']} {platformName} {device.OS} - {device.User}"): osVersion = inventory.operatingsystem["version"]
newFriendlyName = f"{data['1']} {platformName} {device.OS} - {device.User}" if(device.FriendlyName != f"{data['1']} {platformName} {osVersion} - {device.User}"):
newFriendlyName = f"{data['1']} {platformName} {osVersion} - {device.User}"
logger.info(f"Updating device friendlyname to {newFriendlyName}") logger.info(f"Updating device friendlyname to {newFriendlyName}")
airwatch.SetDeviceFriendlyName(device, newFriendlyName) airwatch.SetDeviceFriendlyName(device, newFriendlyName)
# Mise à jour de l'url vers la page airwatch de l'appareil sur GLPI
airwatchlink = f"{settings['AIRWATCH']['ConsoleURI']}/AirWatch/#/AirWatch/Device/Details/Summary/{device.Id}"
if(data['76689'] != airwatchlink):
glpiapi.UpdateAirwatchLink(deviceID, airwatchlink)
# filtre des plateformes # filtre des plateformes
if(platformFilterEnabled): if(platformFilterEnabled):
if device.PlatformId in platformFilterOut: if device.PlatformId in platformFilterOut:
@ -224,9 +247,11 @@ for device in devices:
logger.info(f"Updating {deviceID} on GLPI") logger.info(f"Updating {deviceID} on GLPI")
glpiapi.UpdateInventory(inventory.Json()) glpiapi.UpdateInventory(inventory.Json())
#if(data['70'] == None and device.User != settings["AIRWATCH"]["StagingUser"]): if(data['70'] == None and device.User != settings["AIRWATCH"]["StagingUser"]):
#logger.info(f"Updating user from {data['70']} to {device.User} in GLPI (id={deviceID})") userID, userData, userCount = glpiapi.GetUser(device.User)
#glpiapi.UpdateUser(deviceID, device.User) if(userCount == 1):
logger.info(f"Updating user from {data['70']} to {device.User} in GLPI (id={deviceID})")
glpiapi.UpdateUser(deviceID, userID)
if(data['5'] != device.SerialNumber): if(data['5'] != device.SerialNumber):
logger.info(f"Updating serial number from {data['5']} to {device.SerialNumber} in GLPI (id={deviceID})") logger.info(f"Updating serial number from {data['5']} to {device.SerialNumber} in GLPI (id={deviceID})")