diff --git a/errorlog.md b/errorlog.md index d5c88a33..4e4b77b2 100644 --- a/errorlog.md +++ b/errorlog.md @@ -19,6 +19,8 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure · +2026-07-04 | Howard-Home | context-loading/dataforth | [correction] grepped for 'datforth' (user misspelling), found nothing, then found wiki hits on second grep but didn't read wiki/clients/dataforth.md or projects/dataforth-dos.md; user had to say 'use the wiki'. Correct: on any client-name trigger, fuzzy-match spelling and READ the wiki article before asking the user for infra facts + 2026-07-04 | Howard-Home | screenconnect/sc-cleanup | [friction] burned many tokens iterating the SERVER/Accounting remap because each WAN-map rebuild re-queried SERVER-named machines (returning all fleet SERVER sessions), re-contaminating; fix = build WAN map ONLY from unique-named (len==1) machines, never from shared names 2026-07-04 | Howard-Home | screenconnect/sc-cleanup | [correction] assumed GetSessionsByName is client-scoped; it matches by NAME across ALL clients, so writing to shared/generic names (SERVER x11, Accounting x3) cross-contaminated other clients' sessions with the last-processed client's Company. Fixed tool to skip when >1 session returned; remapped contaminated sessions to correct client via WAN IP; 5 unidentifiable sessions left blank for manual console tagging (originals were overwritten, unrecoverable). diff --git a/projects/gps-rmm-audit/needs-screenconnect.md b/projects/gps-rmm-audit/needs-screenconnect.md index 007a055b..96f3d423 100644 --- a/projects/gps-rmm-audit/needs-screenconnect.md +++ b/projects/gps-rmm-audit/needs-screenconnect.md @@ -1,146 +1,122 @@ -# GPS clients - Syncro-managed machines NOT in GuruRMM (ACTIVE only) +# Machines not in GuruRMM — by ScreenConnect reachability (CORRECTED) -Machines missing from GuruRMM that checked into Syncro within the last 31 days. Excluded: 50 offline >31d, 0 with no check-in data. Snapshot 2026-07-03. -`folder N` = Syncro policy_folder_id. +Online = ActiveConnections ProcessType==2 (guest agent connected). Recency = GuestInfoUpdateTime. +Rebuilt 2026-07-04. Staging installer pushed to all ONLINE machines (land in Staging -> reassign-staging.py). -## Folder distribution (active gap machines) -- folder 3577293: 12 -- folder 651577: 5 -- folder 4095109: 4 -- folder 2948816: 4 -- folder 677399: 3 -- folder 667252: 3 -- folder 3426849: 3 -- folder 4086884: 2 -- folder 677304: 2 -- folder 3638391: 2 -- folder 3937024: 2 -- folder 4106776: 2 -- folder 3204798: 2 -- folder 4100925: 2 -- folder 651365: 1 -- folder 4086890: 1 -- folder 3842122: 1 -- folder 3996026: 1 -- folder 613008: 1 -- folder 4088509: 1 -- folder 4086846: 1 -- folder 3872949: 1 -- folder 607593: 1 -- folder 4896982: 1 -- folder 696512: 1 -- folder 4086906: 1 -- folder 4095118: 1 -- folder 3121109: 1 -- folder 4088528: 1 -- folder 594524: 1 +## ONLINE now (17) +- CP-QB [Curtis Plumbing] (1563d) +- CURTIS-002-W7 [Curtis Plumbing] (0d) +- DESKTOP-EVA4H1A [Gary A Hartman LLC] (0d) +- IMC-PRINTSERVER [Instrumental Music Center] (0d) +- LAPTOP-UBTI0IE3 [Instrumental Music Center] (0d) +- DESKTOP-ERBA22G [Mineralogical Record] (0d) +- PUGET-CW [Mineralogical Record] (0d) +- CNX-LAB-00 [Ridgetop Group] (0d) +- RGI-DC [Ridgetop Group] (0d) +- RTG-HOST01 [Ridgetop Group] (0d) +- DESKTOP-PL2RCGL [Robyn Pittman] (0d) +- DESKTOP-2KKLG2B [Safesite] (0d) +- STAMBACK-NEW05 [Stamback Septic] (0d) +- MEL-PC [The Prairie Schooner] (0d) +- TPS-SVR [The Prairie Schooner] (0d) +- SERVER-OLD [Zeus Nestora] (0d) +- WHITE-PC [Zeus Nestora] (0d) -## TOTAL active needing install: 64 +## active <=14d (31) +- BRETTWAREHOUSE [Brett Interiors] (0d) +- DESKTOP-6LL5T6B [Brett Interiors] (0d) +- KAT1 [Business Services of Tucson LLC] (0d) +- HSM-CATHY [Horseshoe Management] (1d) +- DESKTOP-3ST7GFD [Inside Track Productions] (0d) +- IMC-LUIS [Instrumental Music Center] (0d) +- IMC-M-EDSERVICE [Instrumental Music Center] (2d) +- LAPTOP-PNVA9G51 [Instrumental Music Center] (4d) +- REPAIRADMIN [Instrumental Music Center] (1d) +- DESKTOP-OC2PH4I [Marty Ryan] (0d) +- CHRISTIPC2024 [Mineralogical Record] (0d) +- DESKTOP-CLJKB39 [Multicultural Counseling Center] (6d) +- PLS-SERVER [PUTT LAND SURVEYING, INC.] (8d) +- DESKTOP-EKC9PRV [Pro-Tech Services] (0d) +- LAPTOP-73UDDTTK [Pro-Tech Services] (1d) +- RWD-CHRIS [Reliant Well Drilling and Pump Corporate] (1d) +- WILLCOXDOTADMIN [Reliant Well Drilling and Pump Corporate] (1d) +- DESKTOP-8KQIDKH [Safesite] (0d) +- DESKTOP-ARNPE1U [Safesite] (1d) +- DESKTOP-B3ELJF5 [Safesite] (1d) +- DESKTOP-BA45FRS [Safesite] (0d) +- DESKTOP-EJM109L [Safesite] (0d) +- DESKTOP-FUB3PAV [Safesite] (3d) +- DESKTOP-V3H99FC [Safesite] (1d) +- DESKTOP-V9F9L23 [Safesite] (9d) +- LAPTOP-NFB98THE [Safesite] (2d) +- JEREE [Stamback Septic] (1d) +- DESKTOP-6HT5SJ9 [The Marc Group] (0d) +- ZEUS-ACCOUNTING [Zeus Nestora] (0d) +- ZEUS-SHERRI [Zeus Nestora] (0d) +- ZEUS1 [Zeus Nestora] (0d) -**Instrumental Music Center** - 6 need install (of 14 not-in-RMM; rest offline >31d) - - DESKTOP-KRHQ5TS (folder 651365, seen 2026-06-16, 17d ago) - - IMC-LUIS (folder 651577, seen 2026-07-03, 0d ago) - - IMC-M-EDSERVICE (folder 651577, seen 2026-07-01, 2d ago) - - LAPTOP-PNVA9G51 (folder 651577, seen 2026-06-30, 3d ago) - - LAPTOP-UBTI0IE3 (folder 651577, seen 2026-07-03, 0d ago) - - REPAIRADMIN (folder 651577, seen 2026-07-02, 1d ago) +## stale 15-45d (4) +- GND-L-3 [Grabb & Durando Law Office] (20d) +- DESKTOP-KRHQ5TS [Instrumental Music Center] (15d) +- RWD-ALLENDESKTO [Reliant Well Drilling and Pump Corporate] (18d) +- DESKTOP-FMDIK0Q [Safesite] (42d) -**Safesite** - 12 need install (of 15 not-in-RMM; rest offline >31d) - - 1225-LENOVO-E14 (folder 3577293, seen 2026-07-01, 2d ago) - - 1225-LENOVO-E14 (folder 3577293, seen 2026-07-01, 2d ago) - - DESKTOP-2KKLG2B (folder 3577293, seen 2026-07-03, 0d ago) - - DESKTOP-8KQIDKH (folder 3577293, seen 2026-07-03, 0d ago) - - DESKTOP-ARNPE1U (folder 3577293, seen 2026-07-02, 1d ago) - - DESKTOP-B3ELJF5 (folder 3577293, seen 2026-07-02, 1d ago) - - DESKTOP-BA45FRS (folder 3577293, seen 2026-07-03, 0d ago) - - DESKTOP-EJM109L (folder 3577293, seen 2026-07-03, 0d ago) - - DESKTOP-FUB3PAV (folder 3577293, seen 2026-07-01, 2d ago) - - DESKTOP-V3H99FC (folder 3577293, seen 2026-07-01, 2d ago) - - DESKTOP-V9F9L23 (folder 3577293, seen 2026-06-09, 24d ago) - - LAPTOP-NFB98THE (folder 3577293, seen 2026-07-01, 2d ago) - -**Horseshoe Management** - 1 need install (of 3 not-in-RMM; rest offline >31d) - - HSM-CATHY (folder 4086890, seen 2026-07-02, 1d ago) - -**Grabb & Durando Law Office** - 2 need install (of 4 not-in-RMM; rest offline >31d) - - GND-ASUSWS (folder 4086884, seen 2026-07-02, 0d ago) - - GND-L-3 (folder 4086884, seen 2026-06-13, 20d ago) - -**Stamback Septic** - 7 need install (of 10 not-in-RMM; rest offline >31d) - - DEREK-LAPTOP (folder 677304, seen 2026-07-03, 0d ago) - - DESKTOP-1BS5JL4 (folder 677399, seen 2026-07-03, 0d ago) - - JEREE (folder 677399, seen 2026-07-02, 1d ago) - - SERVER2 (folder 3638391, seen 2026-07-03, 0d ago) - - STAMBACK-JBECK (folder 677399, seen 2026-07-03, 0d ago) - - STAMBACK-NEW05 (folder 3638391, seen 2026-07-03, 0d ago) - - STAMBACK-NEW06 (folder 677304, seen 2026-07-03, 0d ago) - -**Reliant Well Drilling and Pump Corporate** - 4 need install (of 16 not-in-RMM; rest offline >31d) - - Clark’s iMac (folder 4095109, seen 2026-06-10, 23d ago) - - RWD-ALLENDESKTO (folder 4095109, seen 2026-06-16, 17d ago) - - RWD-CHRIS (folder 4095109, seen 2026-07-02, 1d ago) - - WILLCOXDOTADMIN (folder 4095109, seen 2026-07-02, 1d ago) - -**Zeus Nestora** - 5 need install (of 5 not-in-RMM; rest offline >31d) - - SERVER-OLD (folder 3842122, seen 2026-07-03, 0d ago) - - WHITE-PC (folder 2948816, seen 2026-07-03, 0d ago) - - ZEUS-ACCOUNTING (folder 2948816, seen 2026-07-03, 0d ago) - - ZEUS-SHERRI (folder 2948816, seen 2026-07-03, 0d ago) - - ZEUS1 (folder 2948816, seen 2026-07-03, 0d ago) - -**PUTT LAND SURVEYING, INC.** - 1 need install (of 5 not-in-RMM; rest offline >31d) - - PLS-SERVER (folder 3996026, seen 2026-06-26, 7d ago) - -**Curtis Plumbing** - 2 need install (of 3 not-in-RMM; rest offline >31d) - - CP-QB (folder 613008, seen 2026-07-03, 0d ago) - - CURTIS-002-W7 (folder 4088509, seen 2026-07-03, 0d ago) - -**The Prairie Schooner** - 2 need install (of 4 not-in-RMM; rest offline >31d) - - MEL-PC (folder 4086846, seen 2026-07-03, 0d ago) - - TPS-SVR (folder 3872949, seen 2026-07-03, 0d ago) - -**Mineralogical Record** - 3 need install (of 5 not-in-RMM; rest offline >31d) - - CHRISTIPC2024 (folder 607593, seen 2026-07-03, 0d ago) - - DESKTOP-ERBA22G (folder 3937024, seen 2026-07-03, 0d ago) - - PUGET-CW (folder 3937024, seen 2026-07-03, 0d ago) - -**Ridgetop Group** - 3 need install (of 3 not-in-RMM; rest offline >31d) - - CNX-LAB-00 (folder 667252, seen 2026-07-03, 0d ago) - - RGI-DC (folder 667252, seen 2026-07-03, 0d ago) - - RTG-HOST01 (folder 667252, seen 2026-07-03, 0d ago) - -**Multicultural Counseling Center** - 1 need install (of 2 not-in-RMM; rest offline >31d) - - DESKTOP-CLJKB39 (folder 4896982, seen 2026-06-20, 13d ago) - -**Brett Interiors** - 3 need install (of 3 not-in-RMM; rest offline >31d) - - BRETTWAREHOUSE (folder 4106776, seen 2026-07-03, 0d ago) - - DESKTOP-6LL5T6B (folder 4106776, seen 2026-07-03, 0d ago) - - SERVER (folder 696512, seen 2026-07-03, 0d ago) - -**Heieck, Sheila** - 3 need install (of 3 not-in-RMM; rest offline >31d) - - John Heieck’s iMac (folder 3426849, seen 2026-07-03, 0d ago) - - Sheila's iMac (folder 3426849, seen 2026-07-03, 0d ago) - - Sheila’s MacBook Pro (folder 3426849, seen 2026-07-03, 0d ago) - -**The Marc Group** - 1 need install (of 2 not-in-RMM; rest offline >31d) - - DESKTOP-6HT5SJ9 (folder 4086906, seen 2026-07-03, 0d ago) - -**Business Services of Tucson LLC** - 2 need install (of 2 not-in-RMM; rest offline >31d) - - KAT (folder 3204798, seen 2026-06-03, 30d ago) - - KAT1 (folder 3204798, seen 2026-07-03, 0d ago) - -**Pro-Tech Services** - 2 need install (of 2 not-in-RMM; rest offline >31d) - - DESKTOP-EKC9PRV (folder 4100925, seen 2026-07-03, 0d ago) - - LAPTOP-73UDDTTK (folder 4100925, seen 2026-07-02, 1d ago) - -**Inside Track Productions** - 1 need install (of 1 not-in-RMM; rest offline >31d) - - DESKTOP-3ST7GFD (folder 4095118, seen 2026-07-03, 0d ago) - -**Gary A Hartman LLC** - 1 need install (of 1 not-in-RMM; rest offline >31d) - - DESKTOP-EVA4H1A (folder 3121109, seen 2026-07-03, 0d ago) - -**Robyn Pittman** - 1 need install (of 1 not-in-RMM; rest offline >31d) - - DESKTOP-PL2RCGL (folder 4088528, seen 2026-07-03, 0d ago) - -**Marty Ryan** - 1 need install (of 1 not-in-RMM; rest offline >31d) - - DESKTOP-OC2PH4I (folder 594524, seen 2026-07-03, 0d ago) +## dead/no-session (58) +- DESKTOP-SUFJR0J [Bill Tedards] (no SC) +- TEDARDSLAPTOP [Bill Tedards] (no SC) +- KAT [Business Services of Tucson LLC] (no SC) +- CURTIS-003 [Curtis Plumbing] (no SC) +- GND-ASUSWS [Grabb & Durando Law Office] (no SC) +- GND-JEANNETTE [Grabb & Durando Law Office] (no SC) +- HOMEPC [Grabb & Durando Law Office] (no SC) +- John Heieck’s iMac [Heieck, Sheila] (no SC) +- Sheila's iMac [Heieck, Sheila] (no SC) +- Sheila’s MacBook Pro [Heieck, Sheila] (no SC) +- HSM-RANDI [Horseshoe Management] (no SC) +- HSM-SURFACE [Horseshoe Management] (no SC) +- DESKTOP-JQ0D38J [Instrumental Music Center] (105d) +- DESKTOP-URV3UGR [Instrumental Music Center] (79d) +- IMC-EVENTS [Instrumental Music Center] (110d) +- IMC-L1-GRAPHICS [Instrumental Music Center] (no SC) +- PHIL [Instrumental Music Center] (no SC) +- PHIL2021LAPTOP [Instrumental Music Center] (141d) +- PURCHASINGCOMP [Instrumental Music Center] (79d) +- LHLH [Little Hearts Little Hands] (no SC) +- WIN-KNVO6MUMMEM [Little Hearts Little Hands] (no SC) +- CPC-chris-UZR6E [MVAN Enterprises Inc] (no SC) +- DESKTOP-I7504C5 [MVAN Enterprises Inc] (no SC) +- June’s MacBook Pro [MVAN Enterprises Inc] (no SC) +- MITCH-LAPTOP [MVAN Enterprises Inc] (138d) +- DESKTOP-3VPT017 [Mineralogical Record] (no SC) +- DESKTOP-9QHSCIT [Mineralogical Record] (no SC) +- DESKTOP-S1HPLDF [Multicultural Counseling Center] (64d) +- PLS-FOUR [PUTT LAND SURVEYING, INC.] (no SC) +- PLS-FRONT [PUTT LAND SURVEYING, INC.] (no SC) +- PLS-LAPTOP [PUTT LAND SURVEYING, INC.] (no SC) +- PLS-ONE [PUTT LAND SURVEYING, INC.] (no SC) +- DESKTOP-A3IVMNF [Quantum Wealth Management] (no SC) +- Clark’s iMac [Reliant Well Drilling and Pump Corporate] (no SC) +- DESKTOP-09H7T66 [Reliant Well Drilling and Pump Corporate] (no SC) +- DESKTOP-QIGH458 [Reliant Well Drilling and Pump Corporate] (no SC) +- DESKTOP-V2247T9 [Reliant Well Drilling and Pump Corporate] (no SC) +- LAPTOP-8AUEP9N6 [Reliant Well Drilling and Pump Corporate] (no SC) +- LAPTOP-EJL9PFOU [Reliant Well Drilling and Pump Corporate] (no SC) +- LAPTOP-FR4QN9KF [Reliant Well Drilling and Pump Corporate] (no SC) +- LAPTOP-JQMU8N9K [Reliant Well Drilling and Pump Corporate] (no SC) +- RELIANT-L01 [Reliant Well Drilling and Pump Corporate] (no SC) +- RELIANT-L02 [Reliant Well Drilling and Pump Corporate] (no SC) +- RELIANT-L03 [Reliant Well Drilling and Pump Corporate] (no SC) +- RWD-ALANLAPTOP [Reliant Well Drilling and Pump Corporate] (126d) +- WILCOXADMIN [Reliant Well Drilling and Pump Corporate] (no SC) +- 1225-LENOVO-E16 [Safesite] (49d) +- DESKTOP-QAR6D04 [Safesite] (142d) +- DEREK-LAPTOP [Stamback Septic] (no SC) +- DESKTOP-1BS5JL4 [Stamback Septic] (no SC) +- DESKTOP-JVLQQIJ [Stamback Septic] (no SC) +- SSS-SPARE [Stamback Septic] (no SC) +- STAMBACK-JBECK [Stamback Septic] (no SC) +- STAMBACK-NEW06 [Stamback Septic] (no SC) +- STAMBACK-NEW06 [Stamback Septic] (no SC) +- LAPTOP-JMUNGO [The Marc Group] (54d) +- DESKTOP-SRUOH4R [The Prairie Schooner] (no SC) +- DESKTOP-TS1P9MT [The Prairie Schooner] (no SC) diff --git a/projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md b/projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md index a2eb6947..c405c15b 100644 --- a/projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md +++ b/projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md @@ -194,3 +194,15 @@ Built: - projects/gps-rmm-audit/tools/reassign-staging.py: moves Staging agents to their real client via POST /api/agents/:id/move, matching hostname->Syncro customer business_name->GuruRMM client (main site). Idempotent; --dry supported. Verified runs clean (0 staging agents currently). Next: Howard adds the one-liner to the Syncro all-machines policy; schedule reassign-staging.py (or fold into the daily GPS-RMM-Progress task). Unmatched agents stay in Staging + flagged. + +## Update: Corrected online detection + Staging auto-enroll (WORKS end-to-end) + +Howard caught that machines marked "offline 45+ days" were actually online. Two bugs found + fixed: +1. Online field: was reading GuestConnectedCount (always null -> everything looked offline). Correct = ActiveConnections with ProcessType==2 (guest agent connected); recency via GuestInfoUpdateTime. +2. Age metric: needs-list used Syncro last_synced_at (Syncro agent check-in, goes stale when the agent breaks) instead of ScreenConnect reachability. + +Built projects/gps-rmm-audit/tools/rebuild-and-push.py: rebuilds needs-screenconnect.md by SC reachability (ONLINE now / active<=14d / stale15-45 / dead) and pushes the generic Staging installer (DARK-STORM-3150, base64 -EncodedCommand via SendCommandToSession) to every ONLINE machine. Ran it: 17 online -> pushed all 17 -> 15 enrolled into Staging within ~2 min. (Counts: online 17, active<=14d 31, stale 4, dead 58.) + +reassign-staging.py sorted all 15 to their real clients (Curtis, Mineralogical, IMC, Prairie Schooner, Zeus, Stamback + Ridgetop/Gary Hartman/Robyn Pittman). Surfaced 3 clients I'd wrongly written off as no-footprint (Ridgetop has 3 machines, Gary Hartman 1, Robyn Pittman 1) - onboarded them. Added name normalization to reassign (strip LLC/Inc/Corp/etc.) so Syncro 'Safesite LLC' matches GuruRMM 'Safesite'. Staging now empty (all reassigned). + +Proven pipeline: correct-online -> push staging installer -> enroll -> auto-reassign. Ready to repeat as machines come online (or via the Syncro all-machines policy Howard will add). diff --git a/projects/gps-rmm-audit/tools/reassign-staging.py b/projects/gps-rmm-audit/tools/reassign-staging.py index a087ba20..84d00563 100644 --- a/projects/gps-rmm-audit/tools/reassign-staging.py +++ b/projects/gps-rmm-audit/tools/reassign-staging.py @@ -24,11 +24,16 @@ def syncro_customer(hostname): c=a.get("customer") or {} return c.get("business_name") or c.get("fullname") return None -import urllib.parse +import urllib.parse,re +def norm(s): + s=(s or "").lower().strip() + s=re.sub(r'[.,]',' ',s) + s=re.sub(r'\b(llc|inc|incorporated|corp|corporation|company|co|ltd|the)\b',' ',s) + return re.sub(r'\s+',' ',s).strip() agents=rget("/api/agents") staging=[a for a in agents if a.get("client_name")==STAGING_CLIENT] print(f"{len(staging)} agents in Staging") -# GuruRMM client -> a target site id (prefer 'Main'/'Main Office', else first) +# GuruRMM client -> a target site id (prefer 'Main'/'Main Office', else first); keyed by normalized name clients=rget("/api/clients") name2site={} for c in clients: @@ -36,11 +41,11 @@ for c in clients: sites=rget(f"/api/clients/{c['id']}/sites") if not sites: continue main=next((s for s in sites if s["name"].lower() in ("main","main office","office")), sites[0]) - name2site[c["name"].lower()]=main["id"] + name2site[norm(c["name"])]=main["id"] moved=0; unmatched=[] for a in staging: cust=syncro_customer(a["hostname"]) - site=name2site.get((cust or "").lower()) + site=name2site.get(norm(cust)) if cust and site: if not DRY: move(a["id"],site) moved+=1; print(f" {a['hostname']} -> '{cust}'") diff --git a/projects/gps-rmm-audit/tools/rebuild-and-push.py b/projects/gps-rmm-audit/tools/rebuild-and-push.py new file mode 100644 index 00000000..af8941d8 --- /dev/null +++ b/projects/gps-rmm-audit/tools/rebuild-and-push.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# rebuild-and-push.py — rebuild the "machines not in GuruRMM" list using the CORRECT +# ScreenConnect online signal (ActiveConnections ProcessType==2 = guest agent connected; +# GuestInfoUpdateTime for recency), NOT Syncro's stale last_synced_at. Then push the +# generic STAGING installer to every machine that is ONLINE right now (it will actually +# land instead of queuing). Machines enroll into Staging -> reassign-staging.py sorts them. +# +# Env: RMM, TOK (GuruRMM), SK (Syncro), SC_SECRET (ScreenConnect). --dry = no pushes. +import json,urllib.request,ssl,os,sys,base64,datetime,urllib.parse +sys.stdout.reconfigure(encoding='utf-8',errors='replace') +RMM=os.environ["RMM"]; TOK=os.environ["TOK"]; SK=os.environ["SK"]; SEC=os.environ["SC_SECRET"] +ctx=ssl.create_default_context(); DRY="--dry" in sys.argv +SB="https://computerguru.screenconnect.com/App_Extensions/2d558935-686a-4bd0-9991-07539f5fe749/Service.ashx" +STAGING_ONELINER="irm 'https://rmm.azcomputerguru.com/install/DARK-STORM-3150/windows'|iex" +ENC=base64.b64encode(STAGING_ONELINER.encode("utf-16-le")).decode() +PUSHCMD=f"powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand {ENC}" +def scp(m,b): + req=urllib.request.Request(f"{SB}/{m}",data=json.dumps(b).encode(),method="POST",headers={"CTRLAuthHeader":SEC,"Origin":"https://computerguru.screenconnect.com","Content-Type":"application/json"}) + try:return json.loads(urllib.request.urlopen(req,context=ctx,timeout=25).read().decode("utf-8","replace")) + except Exception as e:return {"__err":str(e)} +def rget(p): + return json.loads("".join(c for c in urllib.request.urlopen(urllib.request.Request(f"{RMM}{p}",headers={"Authorization":f"Bearer {TOK}"}),context=ctx,timeout=30).read().decode("utf-8","replace") if ord(c)>=32 or c in "\t\n\r")) +def assets(cid): + raw=urllib.request.urlopen(urllib.request.Request(f"https://computerguru.syncromsp.com/api/v1/customer_assets?customer_id={cid}&per_page=100&api_key={SK}"),context=ctx,timeout=25).read() + raw="".join(chr(b) for b in raw if b>=32 or b in (9,10,13)) + return [a["name"] for a in json.loads(raw).get("assets",[]) if a.get("asset_type")=="Syncro Device" and a.get("name")] +def online(s): return any(c.get("ProcessType")==2 for c in (s.get("ActiveConnections") or [])) +def recency_days(s): + for f in ("GuestInfoUpdateTime","LastGuestConnectedEventTime"): + t=s.get(f) + if t and not str(t).startswith("0001"): + try: return (datetime.datetime.utcnow()-datetime.datetime.strptime(str(t)[:19],"%Y-%m-%dT%H:%M:%S")).days + except: pass + return None +rmm=set(a["hostname"].lower() for a in rget("/api/agents") if a.get("hostname")) +tgts=json.load(open("projects/gps-rmm-audit/targets.json"))["clients"] +groups={"ONLINE now":[],"active <=14d":[],"stale 15-45d":[],"dead/no-session":[]} +pushed=0; failed=0 +for t in tgts: + for h in assets(t["cid"]): + if h.lower() in rmm: continue + ss=scp("GetSessionsByName",{"sessionName":h}) + if not (isinstance(ss,list) and ss): groups["dead/no-session"].append((t["client"],h,"no SC")); continue + if len(ss)>1: continue # ambiguous shared name -> skip + s=ss[0]; d=recency_days(s) + if online(s): + groups["ONLINE now"].append((t["client"],h,f"{d}d" if d is not None else "?")) + if not DRY: + r=scp("SendCommandToSession",[s["SessionID"],PUSHCMD]) + if isinstance(r,dict) and r.get("__err"): failed+=1 + else: pushed+=1 + elif d is not None and d<=14: groups["active <=14d"].append((t["client"],h,f"{d}d")) + elif d is not None and d<=45: groups["stale 15-45d"].append((t["client"],h,f"{d}d")) + else: groups["dead/no-session"].append((t["client"],h,f"{d}d" if d is not None else "old")) +out=["# Machines not in GuruRMM — by ScreenConnect reachability (CORRECTED)","", + "Online = ActiveConnections ProcessType==2 (guest agent connected). Recency = GuestInfoUpdateTime.", + f"Rebuilt {datetime.date(2026,7,4)}. Staging installer pushed to all ONLINE machines (land in Staging -> reassign-staging.py).",""] +for g,items in groups.items(): + out.append(f"## {g} ({len(items)})") + for c,h,d in sorted(items): out.append(f"- {h} [{c}] ({d})") + out.append("") +open("projects/gps-rmm-audit/needs-screenconnect.md","w",encoding="utf-8").write("\n".join(out)) +print(f"ONLINE now: {len(groups['ONLINE now'])} | active<=14d: {len(groups['active <=14d'])} | stale15-45: {len(groups['stale 15-45d'])} | dead: {len(groups['dead/no-session'])}") +print(f"Staging installer pushed: {pushed} (failed {failed}){' [DRY]' if DRY else ''}")