Skip to content

Commit e372131

Browse files
authored
Merge pull request #3 from booskit-codes/nightly
1.1 - Nightly merge into main
2 parents acfb6fd + a95d940 commit e372131

4 files changed

Lines changed: 136 additions & 58 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ The program automatically collects and sends the following information from your
1616
- Storage Information (`_snipeit_storage_information_7`)
1717
- Processor / CPU (`_snipeit_processor_cpu_8`)
1818
- IP Address (`_snipeit_ip_address_9`)
19+
- BIOS Release Date (`_snipeit_bios_release_date_10`)
20+
- Windows Username (`_snipeit_windows_username_11`)
21+
- RAM Usage (`_snipeit_ram_used_12`)
22+
- Disk Space Used (`_snipeit_disk_space_used_13`)
1923

2024
[Download the latest version here](https://github.com/booskit-codes/PyITAgent/releases/).
2125

config-example.ini

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
[DEFAULT]
22
site = http://insert_url_here.com/api/v1
3-
api_key = insert_api_key_here
3+
api_key = insert_api_key_here
4+
5+
[GENERAL]
6+
snipeit_status_id = 2
7+
snipeit_company_id = 1
8+
snipeit_category_id = 3
9+
snipeit_fieldset_id = 1

main.py

Lines changed: 84 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,65 @@
55
import sys
66

77
class ITInventoryClient:
8-
def __init__(self, url, access_token):
9-
self.access_token = access_token
8+
def __init__(self, config):
9+
self.config = config
10+
self.access_token = config['DEFAULT']['api_key']
1011
self.headers = {
1112
"accept": "application/json",
1213
"Authorization": f"Bearer {self.access_token}",
1314
"content-type": "application/json"
1415
}
15-
self.url_prefix = url
16+
self.url_prefix = config['DEFAULT']['site']
1617
self.manufacturer = self.run_command("(gwmi win32_computersystem).manufacturer")
1718
self.serial_number = self.determine_serial_number()
1819
self.hostname = self.run_command("(Get-WmiObject Win32_OperatingSystem).CSName")
1920
self.os = self.run_command("(Get-WmiObject Win32_OperatingSystem).Caption")
2021
self.ram_available = self.run_command("[Math]::Round((Get-WmiObject Win32_ComputerSystem).totalphysicalmemory / 1gb,1)")
21-
self.os_install_date = self.run_command("Get-CimInstance Win32_OperatingSystem | Select-Object InstallDate | ForEach{ $_.InstallDate }")
22+
self.ram_used = self.run_command("[Math]::Round(((Get-WmiObject Win32_ComputerSystem).TotalPhysicalMemory - (Get-WmiObject Win32_OperatingSystem).FreePhysicalMemory * 1024) / 1GB, 2)")
23+
self.os_install_date = self.run_command("[math]::Round((New-TimeSpan -Start (Get-Date '1970-01-01') -End (Get-CimInstance Win32_OperatingSystem).InstallDate).TotalSeconds)")
24+
self.bios_release_date = self.run_command("[math]::Round((New-TimeSpan -Start (Get-Date '1970-01-01') -End (Get-CimInstance Win32_BIOS).ReleaseDate).TotalSeconds)")
2225
self.model_number, self.model = self.determine_model_info()
2326
self.ip_address = self.run_command("(Test-Connection (hostname) -count 1).IPv4Address.IPAddressToString")
24-
self.disk_size, self.disk_info = self.determine_disk_info()
25-
self.mac_addresses = self.run_command("(Get-WmiObject Win32_NetworkAdapterConfiguration | where {$_.ipenabled -EQ $true}).Macaddress")
27+
self.disk_size, self.disk_info, self.disk_used = self.determine_disk_info()
28+
self.mac_addresses = self.run_command("(Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled -eq $true} | Select-Object -First 1).MACAddress")
2629
self.processor = self.run_command("(gwmi Win32_processor).name")
30+
self.current_user = self.run_command("[System.Security.Principal.WindowsIdentity]::GetCurrent().Name")
31+
32+
def resolve_payload(self, type, values):
33+
match type:
34+
case "hardware":
35+
return {
36+
'serial': values['serial_number'],
37+
'name': self.hostname,
38+
'asset_tag': values['serial_number'],
39+
'status_id': values['status_id'],
40+
'model_id': values['model_id'],
41+
'company_id': values['company_id'],
42+
'_snipeit_mac_address_1': self.mac_addresses,
43+
'_snipeit_memory_ram_2': self.ram_available,
44+
'_snipeit_operating_system_3': self.os,
45+
'_snipeit_os_install_date_4': self.os_install_date,
46+
'_snipeit_ip_address_9': self.ip_address,
47+
'_snipeit_total_storage_6': self.disk_size,
48+
'_snipeit_storage_information_7': self.disk_info,
49+
'_snipeit_processor_cpu_8': self.processor,
50+
'_snipeit_bios_release_date_10': self.bios_release_date,
51+
'_snipeit_windows_username_11': self.current_user,
52+
'_snipeit_ram_used_12': self.ram_used,
53+
'_snipeit_disk_space_used_13': self.disk_used
54+
}
55+
case "model":
56+
return {
57+
"name": self.model,
58+
"model_number": self.model_number,
59+
"category_id": values['category_id'],
60+
"manufacturer_id": values['manufacturer_id'],
61+
"fieldset_id": values['fieldset_id']
62+
}
63+
case "manufacturer":
64+
return {
65+
values['manufacturer_name']
66+
}
2767

2868
def run_command(self, cmd):
2969
completed = subprocess.run(["powershell.exe", "-Command", cmd], capture_output=True)
@@ -55,7 +95,8 @@ def determine_disk_info(self):
5595
echo "$($_.MediaType) - $($_.Model) - $($_.SerialNumber) - $([Math]::Round($_.Size/1gb,2)) GB"
5696
}
5797
""")
58-
return disk_size, disk_info
98+
disk_used = self.run_command("[Math]::Round(((Get-WmiObject Win32_LogicalDisk -Filter \"DeviceID='C:'\").Size - (Get-WmiObject Win32_LogicalDisk -Filter \"DeviceID='C:'\").FreeSpace) / 1GB, 2)")
99+
return disk_size, disk_info, disk_used
59100

60101
def send_request(self, method, endpoint, payload=None):
61102
url = f"{self.url_prefix}/{endpoint}"
@@ -87,7 +128,10 @@ def get_manufacturer(self, manufacturer_name):
87128

88129
def post_manufacturer(self, manufacturer_name):
89130
endpoint = 'manufacturers'
90-
payload = {'name': manufacturer_name}
131+
values = {
132+
'manufacturer_name': manufacturer_name,
133+
}
134+
payload = self.resolve_payload("manufacturer", values)
91135
response = self.send_request('POST', endpoint, payload=payload)
92136
if response.get('status') == 'success':
93137
return True
@@ -104,15 +148,14 @@ def get_or_create_manufacturer(self, manufacturer_name):
104148
manufacturer_id = self.get_manufacturer(manufacturer_name)
105149
return manufacturer_id
106150

107-
def post_model(self, model_name, model_number, manufacturer_id, category_id=3, fieldset_id=1):
151+
def post_model(self, manufacturer_id, category_id = 3, fieldset_id = 1):
108152
endpoint = 'models'
109-
payload = {
110-
"name": model_name,
111-
"model_number": model_number,
112-
"category_id": category_id,
113-
"manufacturer_id": manufacturer_id,
114-
"fieldset_id": fieldset_id
153+
values = {
154+
'manufacturer_id': manufacturer_id,
155+
'category_id': category_id,
156+
'fieldset_id': fieldset_id
115157
}
158+
payload = self.resolve_payload("model", values)
116159
response = self.send_request('POST', endpoint, payload=payload)
117160
if response.get('status') == 'success':
118161
return True
@@ -131,33 +174,24 @@ def get_model(self, model_name):
131174
print("No model found in database, perhaps create a new one?")
132175
return None
133176

134-
def get_or_create_model(self, model_name, model_number, manufacturer_id):
135-
model_id = self.get_model(model_name)
177+
def get_or_create_model(self, manufacturer_id):
178+
model_id = self.get_model(self.model)
136179
if model_id is None:
137180
print("Creating new model")
138-
success = self.post_model(model_name, model_number, manufacturer_id)
181+
success = self.post_model(manufacturer_id, self.config['GENERAL']['snipeit_category_id'], self.config['GENERAL']['snipeit_fieldset_id'])
139182
if success:
140-
model_id = self.get_model(model_name)
183+
model_id = self.get_model(self.model)
141184
return model_id
142185

143-
def post_hardware(self, serial_number, pc_name, model_id, mac_address, ram_available, operating_system, os_install_date, ipv4, disk_size, disk_info, cpu, status_id=2, company_id=1):
186+
def post_hardware(self, serial_number, model_id, status_id, company_id):
144187
endpoint = 'hardware'
145-
payload = {
146-
'serial': serial_number,
147-
'name': pc_name,
148-
'asset_tag': serial_number, # Assuming this method exists
188+
values = {
189+
'serial_number': serial_number,
149190
'status_id': status_id,
150191
'model_id': model_id,
151192
'company_id': company_id,
152-
'_snipeit_mac_address_1': mac_address,
153-
'_snipeit_memory_ram_2': ram_available,
154-
'_snipeit_operating_system_3': operating_system,
155-
'_snipeit_os_install_date_4': os_install_date,
156-
'_snipeit_ip_address_9': ipv4,
157-
'_snipeit_total_storage_6': disk_size,
158-
'_snipeit_storage_information_7': disk_info,
159-
'_snipeit_processor_cpu_8': cpu
160193
}
194+
payload = self.resolve_payload("hardware", values)
161195
response = self.send_request('POST', endpoint, payload=payload)
162196
if response.get('status') == 'success':
163197
return True
@@ -176,42 +210,33 @@ def get_hardware(self, serial_number):
176210
print("No hardware found in database, perhaps create a new one?")
177211
return None
178212

179-
def patch_hardware(self, hardware_id, serial_number, pc_name, model_id, mac_address, ram_available, operating_system, os_install_date, ipv4, disk_size, disk_info, cpu, status_id=2, company_id=1):
213+
def patch_hardware(self, hardware_id, serial_number, model_id, status_id, company_id):
180214
endpoint = f'hardware/{hardware_id}?deleted=false'
181-
payload = {
182-
'serial': serial_number,
183-
'name': pc_name,
184-
'asset_tag': serial_number, # Assuming this method exists
215+
values = {
216+
'serial_number': serial_number,
185217
'status_id': status_id,
186218
'model_id': model_id,
187219
'company_id': company_id,
188-
'_snipeit_mac_address_1': mac_address,
189-
'_snipeit_memory_ram_2': ram_available,
190-
'_snipeit_operating_system_3': operating_system,
191-
'_snipeit_os_install_date_4': os_install_date,
192-
'_snipeit_ip_address_9': ipv4,
193-
'_snipeit_total_storage_6': disk_size,
194-
'_snipeit_storage_information_7': disk_info,
195-
'_snipeit_processor_cpu_8': cpu
196220
}
221+
payload = self.resolve_payload("hardware", values)
197222
response = self.send_request('PATCH', endpoint, payload=payload)
198223
if response.get('status') == 'success':
199224
return True
200225
else:
201226
print(f"Failed to update hardware: {response.get('messages')}")
202227
return False
203228

204-
def get_or_create_hardware(self, serial_number, pc_name, model_id, mac_address, ram_available, operating_system, os_install_date, ipv4, disk_size, disk_info, cpu, update_hardware):
205-
hardware_id = self.get_hardware(serial_number)
229+
def get_or_create_hardware(self, model_id, update_hardware, status_id = 2, company_id = 1):
230+
hardware_id = self.get_hardware(self.serial_number)
206231
if hardware_id is None:
207232
print("Creating new hardware")
208233
update_hardware = False
209-
success = self.post_hardware(serial_number, pc_name, model_id, mac_address, ram_available, operating_system, os_install_date, ipv4, disk_size, disk_info, cpu)
234+
success = self.post_hardware(self.serial_number, model_id, status_id, company_id)
210235
if success:
211-
hardware_id = self.get_hardware(serial_number)
236+
hardware_id = self.get_hardware(self.serial_number)
212237
if update_hardware:
213238
print("Patching hardware")
214-
self.patch_hardware(hardware_id, serial_number, pc_name, model_id, mac_address, ram_available, operating_system, os_install_date, ipv4, disk_size, disk_info, cpu)
239+
self.patch_hardware(hardware_id, self.serial_number, model_id, status_id, company_id)
215240
return hardware_id
216241

217242
# Resolve pyinstaller's stoopid windows executable path issue
@@ -251,11 +276,7 @@ def main():
251276

252277
# VV Seriously just don't change any of this. VV
253278
config = get_config()
254-
255-
url = config['DEFAULT']['site']
256-
api_key = config['DEFAULT']['api_key']
257-
258-
it_client = ITInventoryClient(url, api_key)
279+
it_client = ITInventoryClient(config)
259280
# ΛΛ Seriously just don't change any of this. ΛΛ
260281

261282
# This will serve as both debugging purposes & just general information, nothing bad with information.
@@ -268,12 +289,16 @@ def main():
268289
Hostname: {it_client.hostname}
269290
OS: {it_client.os}
270291
Ram Available: {it_client.ram_available}
292+
Ram Used: {it_client.ram_used}
271293
OS Install Date: {it_client.os_install_date}
272294
Model Number: {it_client.model_number}
273295
IP Address: {it_client.ip_address}
274296
Disk Size: {it_client.disk_size}
297+
Disk Used: {it_client.disk_used}
275298
MAC Address: {it_client.mac_addresses}
276299
Processor: {it_client.processor}
300+
Current User: {it_client.current_user}
301+
BIOS Release Date: {it_client.bios_release_date}
277302
""")
278303

279304
# Get the manufacturer
@@ -283,14 +308,16 @@ def main():
283308
print("Manufacturer fetched: ", manufacturer_id)
284309

285310
# Get the model
286-
model_id = it_client.get_or_create_model(it_client.model, it_client.model_number, manufacturer_id)
311+
model_id = it_client.get_or_create_model(manufacturer_id)
287312
if model_id is None:
288313
return print("Failed to fetch model")
289314
print("Model fetched: ", model_id)
290315

291316
# Get the hardware, if it exists, update it properly.
317+
snipeit_status_id = config['GENERAL']['snipeit_status_id']
318+
snipeit_company_id = config['GENERAL']['snipeit_company_id']
292319
update_hardware = True
293-
hardware_id = it_client.get_or_create_hardware(it_client.serial_number, it_client.hostname, model_id, it_client.mac_addresses, it_client.ram_available, it_client.os, it_client.os_install_date, it_client.ip_address, it_client.disk_size, it_client.disk_info, it_client.processor, update_hardware)
320+
hardware_id = it_client.get_or_create_hardware(model_id, update_hardware, snipeit_status_id, snipeit_company_id)
294321
if hardware_id is None:
295322
return print("Failed to fetch hardware")
296323
print("Hardware fetched: ", hardware_id)

ps.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import logging
2+
import subprocess
3+
4+
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
5+
6+
class PowerShellLogging:
7+
def __init__(self):
8+
self.manufacturer = self.run_command("(gwmi win32_computersystem).manufacturer")
9+
10+
def run_command(self, cmd):
11+
try:
12+
completed = subprocess.run(["powershell.exe", "-Command", cmd], capture_output=True, text=True)
13+
14+
# Check if the command was executed successfully
15+
if completed.returncode == 0:
16+
logging.info(f"Command executed successfully: {cmd}")
17+
return completed.stdout.strip()
18+
else:
19+
# Log an error if the command failed
20+
logging.error(f"Command failed with return code {completed.returncode}: {cmd}")
21+
logging.error(f"Error output: {completed.stderr.strip()}")
22+
return None
23+
except Exception as e:
24+
# Log any exceptions that occur during execution
25+
logging.exception(f"An exception occurred while executing the command: {cmd}")
26+
return None
27+
28+
def test_powershell():
29+
30+
ps = PowerShellLogging()
31+
32+
# This will serve as both debugging purposes & just general information, nothing bad with information.
33+
print(f"""
34+
Powershell Logging
35+
-------------------------
36+
37+
Manufacturer: {ps.manufacturer}
38+
""")
39+
40+
if __name__ == "__main__":
41+
test_powershell()

0 commit comments

Comments
 (0)