diff --git a/scripts/StagingUserAssignation.py b/scripts/StagingUserAssignation.py index 970e78d..43b48f1 100644 --- a/scripts/StagingUserAssignation.py +++ b/scripts/StagingUserAssignation.py @@ -4,6 +4,8 @@ import base64 import requests import json import argparse +from cryptography.hazmat.primitives.serialization import pkcs12, pkcs7 +from cryptography.hazmat.primitives import hashes, serialization parser = argparse.ArgumentParser() parser.add_argument("-debug", action=argparse.BooleanOptionalAction) @@ -14,6 +16,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/", @@ -41,11 +46,19 @@ lockFile = './airwatchStagingUserAssignation.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"] +elif(airwatchAuthMethod == 'CMSURL'): + airwatchCertPath = settings["airwatchCertPath"] + airwatchCertPass = settings["airwatchCertPass"] stagingUser = settings["stagingUser"] # Informations du serveur GLPI @@ -55,6 +68,30 @@ GLPIUserToken = settings["glpiUserToken"] # ====================================== # +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): @@ -68,14 +105,7 @@ else: # avec limite de 500 appareils par page (limite max de l'API) airwatchAPIDevicesSearchURI = f"/API/mdm/devices/search?user={stagingUser}&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 @@ -186,7 +216,9 @@ for device in devices: # Vérification que l'appareil est associé à un utilisateur dans GLPI if(device_user != None): # Récupération de l'utilisateur sur Magenta - uri = f"{airwatchServer}/API/system/users/search?username={device_user}" + cmdURI = f'/API/system/users/search?username={device_user}' + airwatchHeaders = getAirwatchHeaders(airwatchAuthMethod, airwatchAPIKey, uri=cmdURI, User=airwatchAPIUser, password=airwatchAPIPassword, CertPath=airwatchCertPath, CertPassword=airwatchCertPass) + uri = f"{airwatchServer}{cmdURI}" if(debug): print(f"Airwatch user search uri : {uri}") user = requests.get(uri, headers=airwatchHeaders) @@ -198,7 +230,9 @@ for device in devices: user = user.json() # Changement de l'utilisateur assigné sur l'appareil dans Magenta - patchUri = f'{airwatchServer}/API/mdm/devices/{device["Id"]["Value"]}/enrollmentuser/{user["Users"][0]["Id"]["Value"]}' + cmdURI = f'/API/mdm/devices/{device["Id"]["Value"]}/enrollmentuser/{user["Users"][0]["Id"]["Value"]}' + patchUri = f'{airwatchServer}{cmdURI}' + airwatchHeaders = getAirwatchHeaders(airwatchAuthMethod, airwatchAPIKey, uri=cmdURI, User=airwatchAPIUser, password=airwatchAPIPassword, CertPath=airwatchCertPath, CertPassword=airwatchCertPass) if(debug): print(f"patchUri = {patchUri}") requests.patch(patchUri, headers=airwatchHeaders) diff --git a/scripts/syncGLPI.py b/scripts/syncGLPI.py index 9fa4d45..16feee7 100644 --- a/scripts/syncGLPI.py +++ b/scripts/syncGLPI.py @@ -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']}"