Ajout du support des certificats Airwatch pour l'authentification

This commit is contained in:
Jason SECULA
2025-06-05 14:26:26 +02:00
parent 882cf674a2
commit 8e24abb269
2 changed files with 96 additions and 25 deletions

View File

@ -5,6 +5,8 @@ import base64
import requests
import json
import argparse
from cryptography.hazmat.primitives.serialization import pkcs12, pkcs7
from cryptography.hazmat.primitives import hashes, serialization
from datetime import datetime
parser = argparse.ArgumentParser()
@ -18,6 +20,9 @@ args = parser.parse_args()
settingsDefault = {
"airwatchServer":"https://apimagenta.phm.education.gouv.fr",
"airwatchAPIKey":"",
"airwatchAuthMethod":"CMSURL",
"airwatchCertPath":"",
"airwatchCertPass":"",
"airwatchAPIUser":"",
"airwatchAPIPassword":"",
"glpiServer":"http://127.0.0.1/glpi/",
@ -45,11 +50,19 @@ lockFile = './airwatchSyncGLPI.lock'
debug=args.debug
# Informations du serveur Airwatch
#airwatchServer = 'https://pp-apimagenta.phm.education.gouv.fr'
airwatchServer = settings["airwatchServer"]
airwatchAPIKey = settings["airwatchAPIKey"]
airwatchAPIUser = settings["airwatchAPIUser"]
airwatchAPIPassword = settings["airwatchAPIPassword"]
airwatchAuthMethod = settings["airwatchAuthMethod"]
airwatchAPIUser = None
airwatchAPIPassword = None
airwatchCertPath = None
airwatchCertPass = None
if(airwatchAuthMethod == 'password'):
airwatchAPIUser = settings["airwatchAPIUser"]
airwatchAPIPassword = settings["airwatchAPIPassword"]
else:
airwatchCertPath = settings["airwatchCertPath"]
airwatchCertPass = settings["airwatchCertPass"]
# Informations du serveur GLPI
GLPIServer = settings["glpiServer"]
@ -66,6 +79,31 @@ platformFilterOut = [12]
# ====================================== #
def getAirwatchHeaders(airwatchAuthMethod, airwatchAPIKey, uri, User=None, password=None, CertPath=None, CertPassword=None):
if(airwatchAuthMethod == "password"):
airwatchAPIUserToken = base64.b64encode(f"{airwatchAPIUser}:{airwatchAPIPassword}".encode('ascii')).decode("ascii")
return {
"Authorization": f"Basic {airwatchAPIUserToken}",
"aw-tenant-code": airwatchAPIKey,
"Accept": "application/json"
}
else:
signing_data = uri.split('?')[0]
with open(CertPath, 'rb') as certfile:
cert = certfile.read()
key, certificate, additional_certs = pkcs12.load_key_and_certificates(cert, CertPassword.encode())
options = [pkcs7.PKCS7Options.DetachedSignature]
signed_data = pkcs7.PKCS7SignatureBuilder().set_data(signing_data.encode("UTF-8")).add_signer(certificate, key, hashes.SHA256()).sign(serialization.Encoding.DER, options)
signed_data_b64 = base64.b64encode(signed_data).decode()
return {
"Authorization": f"CMSURL'1 {signed_data_b64}",
"aw-tenant-code": airwatchAPIKey,
"Accept": "application/json"
}
# Vérification de la présence du verrou avant de continuer
if(os.path.isfile(lockFile) and not args.force):
if(debug):
@ -78,15 +116,7 @@ else:
# Adresse de recherche des appareils
# avec limite de 500 appareils par page (limite max de l'API)
airwatchAPIDevicesSearchURI = f"/API/mdm/devices/search?pagesize=500&page="
# User token formé par la concaténation du nom de l'utilisateur API et de son mot de passe converti en base 64
airwatchAPIUserToken = base64.b64encode(f"{airwatchAPIUser}:{airwatchAPIPassword}".encode('ascii')).decode("ascii")
airwatchHeaders = {
"Authorization": f"Basic {airwatchAPIUserToken}",
"aw-tenant-code": airwatchAPIKey,
"Accept": "application/json"
}
airwatchHeaders = getAirwatchHeaders(airwatchAuthMethod, airwatchAPIKey, uri=airwatchAPIDevicesSearchURI, User=airwatchAPIUser, password=airwatchAPIPassword, CertPath=airwatchCertPath, CertPassword=airwatchCertPass)
# Page de départ pour la recherche
pageNumber = 0
@ -95,6 +125,7 @@ pageNumber = 0
devices = []
uri = f"{airwatchServer}{airwatchAPIDevicesSearchURI}{pageNumber}"
if(debug):
print(f"Uri for device search on airwatch : {uri}")
result = requests.get(uri, headers=airwatchHeaders)
@ -121,6 +152,9 @@ while(len(devices) != result["Total"]):
pageNumber += 1
if(debug):
print(f"Nombre d'appareils {len(devices)}")
# ====================== Début suppression des doublons ================================= #
# On récupére les numéros de série
@ -159,6 +193,7 @@ devices = [d for d in devices if d["Id"]["Value"] not in devicesToDelete]
# envoi de la requête de suppression des appareils sur magenta
airwatchAPIDeleteURI = '/API/mdm/devices/'
airwatchHeaders = getAirwatchHeaders(airwatchAuthMethod, airwatchAPIKey, uri=airwatchAPIDeleteURI, User=airwatchAPIUser, password=airwatchAPIPassword, CertPath=airwatchCertPath, CertPassword=airwatchCertPass)
for device in devicesToDelete:
uri = f"{airwatchServer}{airwatchAPIDeleteURI}{device}"
if(debug):
@ -312,6 +347,7 @@ for device in devices:
}
# Récupération des applications présents sur les appareils
airwatchAPIAppsSearchURI = f"/api/mdm/devices/{device['Uuid']}/apps/search"
airwatchHeaders = getAirwatchHeaders(airwatchAuthMethod, airwatchAPIKey, uri=airwatchAPIAppsSearchURI, User=airwatchAPIUser, password=airwatchAPIPassword, CertPath=airwatchCertPath, CertPassword=airwatchCertPass)
uri = f"{airwatchServer}{airwatchAPIAppsSearchURI}"
apps = requests.get(uri, headers=airwatchHeaders).json()
@ -343,6 +379,7 @@ for device in devices:
# Mise à jour du friendly name sur Airwatch
if(device["DeviceFriendlyName"] != f"{data['1']} {platformName} {device['OperatingSystem']} - {device['UserName']}"):
airwatchAPIURI = f"/API/mdm/devices/{device['Id']['Value']}"
airwatchHeaders = getAirwatchHeaders(airwatchAuthMethod, airwatchAPIKey, uri=airwatchAPIURI, User=airwatchAPIUser, password=airwatchAPIPassword, CertPath=airwatchCertPath, CertPassword=airwatchCertPass)
uri = f"{airwatchServer}{airwatchAPIURI}"
updateDeviceDetails = {
"DeviceFriendlyName":f"{data['1']} {platformName} {device['OperatingSystem']} - {device['UserName']}"