This commit is contained in:
19
.gitea/workflows/build.yaml
Normal file
19
.gitea/workflows/build.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Build python package
|
||||
run-name: building python package GLPIAPI
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
runs-on: windows
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@main
|
||||
- name: Building the package
|
||||
run: |
|
||||
mv ${{ gitea.workspace }}\GLPIAPI.py ${{ gitea.workspace }}\build\src\GLPIAPI\
|
||||
cd ${{ gitea.workspace }}\build
|
||||
python -m build
|
||||
- name: Publish package
|
||||
run: |
|
||||
python -m twine upload -u ${{ secrets.repo_user }} -p ${{ secrets.repo_pass }} --repository-url ${{ secrets.repo_url }} ${{ gitea.workspace }}\build\dist\*
|
||||
if: github.ref_type == 'tag'
|
||||
17
.gitlab-ci.yml
Normal file
17
.gitlab-ci.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
image: python:latest
|
||||
|
||||
variables:
|
||||
TWINE_USERNAME: gitlab-ci-token
|
||||
TWINE_PASSWORD: $CI_JOB_TOKEN
|
||||
|
||||
build: # This job runs in the build stage, which runs first.
|
||||
script:
|
||||
- pip install build twine
|
||||
- mkdir build/src/GLPIAPI/
|
||||
- mv GLPIAPI.py build/src/GLPIAPI/
|
||||
- cd build/
|
||||
- python -m build
|
||||
- python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
|
||||
336
GLPIAPI.py
Normal file
336
GLPIAPI.py
Normal file
@@ -0,0 +1,336 @@
|
||||
import requests
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
class GLPIAPI:
|
||||
def __init__(self, Server, AppToken, UserToken, UserAgent="GLPI API"):
|
||||
self.Server = Server
|
||||
self.AppToken = AppToken
|
||||
self.UserToken = UserToken
|
||||
self.UserAgent = UserAgent
|
||||
self.SessionToken = None
|
||||
self.StatusCode = None
|
||||
self.Headers = None
|
||||
self.InitConnection()
|
||||
|
||||
def InitConnection(self):
|
||||
initURI = '/apirest.php/initSession/'
|
||||
GLPIHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
"Authorization": f"user_token {self.UserToken}",
|
||||
"App-Token": self.AppToken
|
||||
}
|
||||
|
||||
# Récupération d'un token de session
|
||||
uri = f"{self.Server}{initURI}"
|
||||
result = requests.get(uri, headers=GLPIHeaders)
|
||||
self.StatusCode = result.status_code
|
||||
if(result.status_code == 200):
|
||||
self.SessionToken = result.json()["session_token"]
|
||||
self.Headers = {
|
||||
'Content-Type': 'application/json',
|
||||
"Session-Token": self.SessionToken,
|
||||
"App-Token": self.AppToken
|
||||
}
|
||||
|
||||
def GetDevice(self, airwatchDevice=None, serialNumber=None, imei=None):
|
||||
if(airwatchDevice != None):
|
||||
if(airwatchDevice.Imei != ''):
|
||||
# Recherche des appareils en fonction du numéro de série ou de l'imei
|
||||
# l'imei pouvant être dans le champ numéro de série ou les champs imei custom (plugin field)
|
||||
search_parameter = f'is_deleted=0&criteria[0][field]=5&withindexes=true&criteria[0][searchtype]=contains&criteria[0][value]=^{airwatchDevice.SerialNumber}$'\
|
||||
f'&criteria[1][link]=OR&criteria[1][field]=5&criteria[1][searchtype]=contains&criteria[1][value]=^{airwatchDevice.Imei}$'\
|
||||
f'&criteria[2][link]=OR&criteria[2][field]=76667&criteria[2][searchtype]=contains&criteria[2][value]=^{airwatchDevice.Imei}$'\
|
||||
f'&criteria[3][link]=OR&criteria[3][field]=76670&criteria[3][searchtype]=contains&criteria[3][value]=^{airwatchDevice.Imei}$'
|
||||
else:
|
||||
# Recherche des appareils en fonction du numéro de série seulement
|
||||
search_parameter = f'is_deleted=0&criteria[0][field]=5&withindexes=true&criteria[0][searchtype]=contains&criteria[0][value]=^{airwatchDevice.SerialNumber}$'
|
||||
else:
|
||||
if(imei != None):
|
||||
# Recherche des appareils en fonction du numéro de série ou de l'imei
|
||||
# l'imei pouvant être dans le champ numéro de série ou les champs imei custom (plugin field)
|
||||
search_parameter = f'is_deleted=0&criteria[0][field]=5&withindexes=true&criteria[0][searchtype]=contains&criteria[0][value]=^{serialNumber}$'\
|
||||
f'&criteria[1][link]=OR&criteria[1][field]=5&criteria[1][searchtype]=contains&criteria[1][value]=^{imei}$'\
|
||||
f'&criteria[2][link]=OR&criteria[2][field]=76667&criteria[2][searchtype]=contains&criteria[2][value]=^{imei}$'\
|
||||
f'&criteria[3][link]=OR&criteria[3][field]=76670&criteria[3][searchtype]=contains&criteria[3][value]=^{imei}$'
|
||||
else:
|
||||
# Recherche des appareils en fonction du numéro de série seulement
|
||||
search_parameter = f'is_deleted=0&criteria[0][field]=5&withindexes=true&criteria[0][searchtype]=contains&criteria[0][value]=^{serialNumber}$'
|
||||
|
||||
searchUri = f"{self.Server}/apirest.php/search/Computer?{search_parameter}"
|
||||
search = requests.get(searchUri, headers=self.Headers)
|
||||
if(search.status_code == 200):
|
||||
search = search.json()
|
||||
if(search["totalcount"] == 1):
|
||||
deviceID = list(search["data"].keys())[0]
|
||||
data = search["data"][deviceID]
|
||||
|
||||
return deviceID, data, search["totalcount"]
|
||||
elif(search["totalcount"] > 1):
|
||||
deviceID = list(search["data"].keys())
|
||||
return deviceID, search["data"], search["totalcount"]
|
||||
|
||||
return None, None, 0
|
||||
|
||||
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"]
|
||||
|
||||
return None, None, 0
|
||||
|
||||
def UploadFile(self, file, path):
|
||||
manifest = {
|
||||
"input": {
|
||||
"name": file,
|
||||
"is_recursive": 1,
|
||||
"_filename": [file],
|
||||
"documentcategories_id": 4
|
||||
}
|
||||
}
|
||||
fileData = open(path+file, "rb")
|
||||
headers = {
|
||||
"Session-Token": self.SessionToken,
|
||||
"App-Token": self.AppToken
|
||||
}
|
||||
data = {"uploadManifest": json.dumps(manifest)}
|
||||
files = {file: fileData}
|
||||
return requests.post(self.Server+"/apirest.php/Document/", headers=headers, data=data, files=files)
|
||||
|
||||
def SetDocumentToDevice(self, deviceID, documentID):
|
||||
body = {
|
||||
"input": {
|
||||
"documents_id": documentID,
|
||||
"items_id": deviceID,
|
||||
"itemtype": "Computer"
|
||||
}
|
||||
}
|
||||
return requests.post(self.Server+"/apirest.php/Document/"+str(documentID)+"/Document_Item", headers=self.Headers, json=body)
|
||||
|
||||
def UpdateInventory(self, inventory):
|
||||
headers = {
|
||||
"Content-Type":"Application/x-compress",
|
||||
"user-agent":self.UserAgent
|
||||
}
|
||||
return requests.post(self.Server, headers=headers, data=inventory)
|
||||
|
||||
def UpdateSerialNumber(self, deviceid, serialnumber):
|
||||
|
||||
body = {
|
||||
"input" : {
|
||||
"id" : deviceid,
|
||||
"serial" : serialnumber
|
||||
}
|
||||
}
|
||||
uri = f"{self.Server}/apirest.php/Computer/"
|
||||
return requests.put(uri, headers=self.Headers, json=body)
|
||||
|
||||
def UpdateUser(self, deviceid, username):
|
||||
|
||||
body = {
|
||||
"input" : {
|
||||
"id" : deviceid,
|
||||
"users_id" : username
|
||||
}
|
||||
}
|
||||
uri = f"{self.Server}/apirest.php/Computer/"
|
||||
return requests.put(uri, headers=self.Headers, json=body)
|
||||
|
||||
def SetField(self, itemType, containerName, containerID, itemId, fieldName, data):
|
||||
'''Requires fields plugin on GLPI server
|
||||
- containerName is block label name
|
||||
- containerID is block id
|
||||
'''
|
||||
uri = f"{self.Server}/apirest.php/PluginFields{itemType}{containerName}"
|
||||
searchURI = f"{self.Server}/apirest.php/PluginFields{itemType}{containerName}?range=0-999999999"
|
||||
result = requests.get(searchURI, headers=self.Headers)
|
||||
if(result.status_code == 200):
|
||||
result = result.json()
|
||||
fieldItem = None
|
||||
# searching for field item
|
||||
for entry in result:
|
||||
if str(entry["items_id"]) == itemId:
|
||||
fieldItem = entry
|
||||
|
||||
if(fieldItem == None):
|
||||
body = {
|
||||
"input": {
|
||||
"items_id": itemId,
|
||||
"itemtype": itemType,
|
||||
"plugin_fields_containers_id": containerID,
|
||||
fieldName: data
|
||||
}
|
||||
}
|
||||
return requests.post(uri, headers=self.Headers, json=body)
|
||||
else:
|
||||
body = {
|
||||
"input": {
|
||||
"id": fieldItem["id"],
|
||||
fieldName: data
|
||||
}
|
||||
}
|
||||
return requests.put(uri, headers=self.Headers, json=body)
|
||||
|
||||
def CreateInventoryForAirwatchDevice(self, device, deviceName, apps=None):
|
||||
platforms = {
|
||||
2:"Apple iOS",
|
||||
5:"Android",
|
||||
10:"Apple macOS",
|
||||
12:"Windows"
|
||||
}
|
||||
|
||||
if(device.PlatformId in platforms.keys()):
|
||||
platformName = platforms[device.PlatformId]
|
||||
else:
|
||||
platformName = "Unknown"
|
||||
|
||||
processorArchs = {
|
||||
0:{
|
||||
"osArch":"arm64",
|
||||
"softwareArch":"arm64"
|
||||
},
|
||||
9:{
|
||||
"osArch":"64-bit",
|
||||
"softwareArch":"x86_64"
|
||||
}
|
||||
}
|
||||
if(device.Arch in processorArchs.keys()):
|
||||
osArch = processorArchs[device.Arch]["osArch"]
|
||||
softwareArch = processorArchs[device.Arch]["softwareArch"]
|
||||
else:
|
||||
osArch = "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")
|
||||
|
||||
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.SetHardware(deviceName, device.Uuid, device.TotalMemory)
|
||||
inventory.AddUser(device.User)
|
||||
|
||||
if(apps != None):
|
||||
for app in apps:
|
||||
if(app.Status != "Installed"):
|
||||
continue
|
||||
|
||||
install_date = datetime.strptime(app.InstallDate, "%Y-%m-%dT%H:%M:%S.%f").strftime("%Y-%m-%d")
|
||||
|
||||
if(install_date == "1-01-01"):
|
||||
inventory.AddSoftware(app.Name, app.Version, app.Size, softwareArch, app.Guid)
|
||||
else:
|
||||
inventory.AddSoftware(app.Name, app.Version, app.Size, softwareArch, app.Guid, install_date)
|
||||
|
||||
return inventory
|
||||
|
||||
class GLPIInventory:
|
||||
def __init__(self, logdate=None, versionclient=None, tag=None, deviceid=None, itemtype=None):
|
||||
self.logdate = logdate
|
||||
self.versionclient = versionclient
|
||||
self.users = []
|
||||
self.operatingsystem = {}
|
||||
self.softwares = []
|
||||
self.hardware = {}
|
||||
self.tag = tag
|
||||
self.deviceId = deviceid
|
||||
self.itemType = itemtype
|
||||
|
||||
|
||||
def AddUser(self, user):
|
||||
self.users += [{
|
||||
"login": user
|
||||
}]
|
||||
|
||||
def DelUser(self, user):
|
||||
for i in range(0, len(self.users)):
|
||||
if(self.users[i]["login"] == user):
|
||||
del self.users[i]
|
||||
|
||||
def AddSoftware(self, name, version, filesize, arch, guid, install_date=None):
|
||||
if(install_date == None):
|
||||
self.softwares += [{
|
||||
"name": name,
|
||||
"guid": guid,
|
||||
"version": version,
|
||||
"filesize": filesize,
|
||||
"arch": arch
|
||||
}]
|
||||
else:
|
||||
self.softwares += [{
|
||||
"name": name,
|
||||
"guid": guid,
|
||||
"version": version,
|
||||
"install_date": install_date,
|
||||
"filesize": filesize,
|
||||
"arch": arch
|
||||
}]
|
||||
|
||||
def DelSoftware(self, guid):
|
||||
for i in range(0, len(self.softwares)):
|
||||
if(self.softwares[i]["guid"] == guid):
|
||||
del self.softwares[i]
|
||||
|
||||
def SetHardware(self, name, uuid, memory):
|
||||
self.hardware = {
|
||||
"name": name,
|
||||
"uuid": uuid,
|
||||
"memory": memory
|
||||
}
|
||||
|
||||
def SetOperatingSystem(self, name, version, arch):
|
||||
self.operatingsystem = {
|
||||
"name": name,
|
||||
"version": version,
|
||||
"full_name": f"{name} {version}",
|
||||
"arch": arch
|
||||
}
|
||||
|
||||
def Json(self):
|
||||
inventory = {
|
||||
"action": "inventory",
|
||||
"content":{
|
||||
"accesslog":{
|
||||
"logdate": self.logdate
|
||||
},
|
||||
"versionclient": self.versionclient,
|
||||
"users": self.users,
|
||||
"operatingsystem": self.operatingsystem,
|
||||
"softwares": self.softwares,
|
||||
"hardware": self.hardware
|
||||
},
|
||||
"tag": self.tag,
|
||||
"deviceid": self.deviceId,
|
||||
"itemtype": self.itemType
|
||||
}
|
||||
return json.dumps(inventory)
|
||||
23
README.md
Normal file
23
README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# GLPIAPI
|
||||
|
||||
A python module to help making API requests to GLPI servers easier.
|
||||
|
||||
Usage
|
||||
================
|
||||
|
||||
You can create an GLPIAPI object to connect to the API using an APpToken and an UserToken.
|
||||
|
||||
Example :
|
||||
|
||||
```python
|
||||
from GLPIAPI import GLPIAPI
|
||||
|
||||
glpiServer = https://my-glpi-server.local
|
||||
glpiAppToken = "YOUR-APP-TOKEN"
|
||||
glpiUserToken = "YOUR-USER-TOKEN"
|
||||
glpiUserAgent = "GLPI API Connector"
|
||||
|
||||
GLPIConnector = GLPIAPI(Server=glpiServer, AppToken=glpiAppToken, UserToken=glpiUserToken, UserAgent=glpiUserAgent)
|
||||
|
||||
device = GLPIConnector.GetDevice(serialNumber="S0123456789")
|
||||
```
|
||||
16
build/pyproject.toml
Normal file
16
build/pyproject.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools >= 77.0.3",
|
||||
"requests >= 2.32.5"
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "GLPIAPI"
|
||||
version = "1.0.0"
|
||||
description = "A module python to make it easier to use GLPI API"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.7"
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3"
|
||||
]
|
||||
0
build/src/__init__.py
Normal file
0
build/src/__init__.py
Normal file
Reference in New Issue
Block a user