main was 16 days and 259 commits behind the line the product is actually built on, at contract 0.30.0 against 0.35.0, with no per-PC credential code at all. It was neither current nor curated - just stale. This brings it forward and, at the same time, makes it mean something: main is what a receiving site installs, and nothing else. WHAT IT CARRIES. Twelve plugins - backups, computers, endpoints, guides, knowledgebase, machines, network, notifications, printers, slides, tools, warranty - plus applications, which is manifest-less core and always ships. The only manifest dependency inside that set is endpoints on computers, and both are in it, so the closure is self-contained. WHAT IT DOES NOT. employees, geenforce, measuringtools, printedparts and usb stay on the site line. So do the Windows installer tree, the VM rehearsal helpers, the agent tooling config, one site's data loader, the internal audit and findings records, and the planner spreadsheet. 1,135 tracked files against 1,438. A REMOVAL THAT BREAKS THE APP IS NOT A REMOVAL, and two nearly shipped: deploy/site-profile-universal.json still named all seventeen plugins. It is the file docs/DEPLOY.md tells a site to provision from, so a fresh install would have failed at `flask plugin apply-profile` with PluginError - the first thing a receiving site does, broken by the branch meant to serve them. It now names the twelve that exist, and its comment says the two must agree. agent/ was never refreshed. Whoever populated this branch copied shopdb/, plugins/, frontend/ and tests/ from the site line and left the agent tree at its September state: 22 C# and PowerShell sources missing, including AgentCredentials, EnrollmentService, AgentHttpFactory and the fleet-alert client, plus one file the site line had deleted still present. The old tree is internally consistent, so it compiles, and nothing in CI builds it - every gate was green over a server that speaks enrollment and per-PC credentials to a bundled agent source that cannot. Resynced whole. DECISIONS THIS ENCODES, rather than defers: - The plugin-authoring lab builds printedparts, whose manifest depends on employees, so it could not stay. The lab remains on the site line and main ships no build-along tutorial. That is a real loss for an adopting developer and is recorded here rather than discovered later. - Recognition, Training and Recertification notifications are no longer seeded. Each splits one notification into a card per employee and renders a photo, which needs a plugin this branch does not bundle. Seeding them would offer an author a type that cannot resolve anybody. A site that installs employees gets them from that plugin's own seed. - Windows/IIS is documented as the legacy path throughout, and the README leads with Docker, because that is what a receiving site gets. The API description is regenerated for THIS branch - 347 paths and 483 operations, down from 415 and 573 - so the published contract describes what is here rather than what the site line serves. docs/CONFIG.md lost the two measuring-tool label keys the code no longer declares, which two lanes had decided opposite ways. Suite: 3124 passed, 6 skipped. Naming and style gates pass. The docs gates run rather than skip, and every index line count is derived from the file it names.
148 lines
8.8 KiB
Markdown
148 lines
8.8 KiB
Markdown
<!-- docmeta
|
|
purpose: howto
|
|
audience: operator, adopter
|
|
status: current
|
|
summary: Get the shipped asset and printer reporters running on a fleet, prove it, and fix it when a bay returns an error.
|
|
loadwith: COLLECTOR-AUTH.md
|
|
-->
|
|
|
|
# Running the collector reporters on a fleet
|
|
|
|
Follow this to put PC reporting on a fleet that does not have it yet, or to move
|
|
an existing fleet off a classic-ASP reporter. The payload contract is
|
|
[COLLECTOR-PAYLOADS](COLLECTOR-PAYLOADS.md) and the credential choice is
|
|
[COLLECTOR-AUTH](COLLECTOR-AUTH.md); you should not need either open to work
|
|
through this page.
|
|
|
|
Adopting the whole tool set at a plant that has none of it is a wider job -
|
|
[ADOPTING-AT-ANOTHER-SITE](ADOPTING-AT-ANOTHER-SITE.md).
|
|
|
|
---
|
|
|
|
## 1. Use the shipped reporters
|
|
|
|
Do not write your own. Two scripts ship in this repository and version with the
|
|
contract they implement:
|
|
|
|
| Script | Reports | Posts to |
|
|
|---|---|---|
|
|
| `plugins/computers/client/Report-AssetToShopDB.ps1` | hostname, BIOS serial, pc-type, logged-in user, make/model, OS, last boot, machine number, device id, every routable NIC | `POST /api/collector/computers` |
|
|
| `plugins/printers/client/Report-PrintersToShopDB.ps1` | every real print queue on the host | `POST /api/collector/printers` |
|
|
|
|
Both run as SYSTEM, always exit 0 so "last run result" stays clean, and log to
|
|
`C:\Logs\Shopfloor\`. Neither names a site: ADR-015 makes a site name in product
|
|
code a defect, and these ship everywhere.
|
|
|
|
Each reads its configuration in this order:
|
|
|
|
1. Its own parameters (`-ApiUrl`, `-ApiKey`), which a scheduled task's arguments
|
|
can supply for testing.
|
|
2. `HKLM:\SOFTWARE\GE\ShopDB` - `BaseUrl` for the server and `CollectorKey` for
|
|
the shared key. This is the secret store every shipped reporter reads, and
|
|
whatever images or configures the bay is what provisions it.
|
|
|
|
With neither, the script logs the reason and exits without posting.
|
|
|
|
**Which credential it sends** is decided on the PC, not in configuration: if the
|
|
PC holds a per-PC credential it is sent as `X-Endpoint-Credential` and the shared
|
|
key is not sent at all; otherwise the shared key goes as `X-API-Key`. If the
|
|
server refuses the credential as invalid or revoked, the reporter retries the
|
|
same POST once with the shared key, which is what makes a revoke a rollback
|
|
rather than an outage.
|
|
|
|
**Shortcut for a single site:** Settings > Computers > Asset reporter generates
|
|
`Report-AssetToShopDB.ps1` with your server's URL already in the parameter
|
|
defaults, and shows its SHA-256. The key is deliberately not included.
|
|
|
|
## 2. Prepare the server
|
|
|
|
1. Enable the `computers` plugin (and `printers`, if you want observed queues).
|
|
2. Mint the credential the fleet will start on - a managed token scoped to
|
|
`collector.ingest`. [COLLECTOR-AUTH](COLLECTOR-AUTH.md) section 4 has the
|
|
steps. An un-enrolled fleet needs this even if you intend to move to per-PC
|
|
credentials, because enrollment itself auto-issues only to a call the shared
|
|
key authenticated.
|
|
3. Set `collector_corporate_ranges` to this site's routable CIDRs. Leave it blank
|
|
and the server falls back to the NIC the bay says carries the default route,
|
|
which is a guess on any bay with two NICs.
|
|
4. Map your imaging pc-types. Unmapped values only warn, but every report warns
|
|
until you do.
|
|
|
|
## 3. Deliver the key to the PCs
|
|
|
|
`HKLM:\SOFTWARE\GE\ShopDB` value `CollectorKey`, ACL'd to SYSTEM and
|
|
Administrators. How it gets there depends on what you run - an imaging task,
|
|
Intune, DSC or by hand - and the options with their trade-offs are in
|
|
[COLLECTOR-AUTH](COLLECTOR-AUTH.md) section 6.
|
|
|
|
Two rules regardless: never bake the key into a script that lives on a file
|
|
share, and never put it in a manifest or a scheduled task's arguments.
|
|
|
|
## 4. Schedule the reporter
|
|
|
|
Reporting is an EVENT on a schedule, not a state to converge on. Two placements,
|
|
pick one:
|
|
|
|
- **As a scheduled task**, registered at imaging time, by Intune, or by hand.
|
|
SYSTEM, RunLevel Highest, at startup plus an interval.
|
|
- **As an entry in whatever enforces configuration on your floor**, run off a
|
|
share every cycle with no local copy. Order the key-provisioning step BEFORE
|
|
it so the key is present the same cycle the first report fires.
|
|
|
|
Either way, run it ALONGSIDE whatever reports today during rollout. Do not
|
|
remove the old path until the new one is proven.
|
|
|
|
## 5. Stage the rollout
|
|
|
|
1. Leave the existing reporting in place. Provision `CollectorKey` and enable the
|
|
plugins.
|
|
2. Add the reporter on a handful of pilot bays, one per pc-type. It cannot break
|
|
enforcement: it never throws and always exits 0.
|
|
3. Verify on the server. Pilot PCs appear or update, `action` is
|
|
`created`/`updated`, and every warning is understood - map any unmapped
|
|
`pctype`, add missing OS strings to the `operatingsystems` vocabulary.
|
|
Cross-check the client log's `OK` lines against the audit log.
|
|
4. Roll it out fleet-wide. From the `common` scope, every pc-type gets it.
|
|
5. Once ShopDB is the system of record and has survived a full imaging cycle,
|
|
retire the old reporter.
|
|
6. Migrate to per-PC credentials, then switch the shared key off. That is its
|
|
own rollout and deliberately comes last: read
|
|
[COLLECTOR-AUTH](COLLECTOR-AUTH.md) for what a PC does to enroll and what an
|
|
admin approves, and `plugins/endpoints/docs/PER-PC-CREDENTIALS-ROLLOUT.md`
|
|
for the order the shared key has to be cleared out of the places it lives.
|
|
Both shipped reporters already send a credential when one is present and fall
|
|
back to the shared key when it is not, so a PC that has not enrolled keeps
|
|
reporting and nothing has to be redeployed to start.
|
|
|
|
## 6. Verify one PC
|
|
|
|
```powershell
|
|
Invoke-RestMethod -Uri 'https://shopdb.example.net/api/computers/by-hostname/<HOSTNAME>'
|
|
```
|
|
|
|
The PC should exist with its serial, type and last-reported timestamp. The
|
|
client log is `C:\Logs\Shopfloor\report-asset-YYYYMMDD.log` (printer queues:
|
|
`report-printers-YYYYMMDD.log`); it records the POST line and the server's
|
|
response verbatim, including which credential it used.
|
|
|
|
## 7. When a bay does not report
|
|
|
|
| Symptom | HTTP | Cause / fix |
|
|
|---|---|---|
|
|
| `Invalid API key` | 401 | The `X-API-Key` header is missing or wrong. Confirm the client key matches `COLLECTOR_API_KEY_COMPUTERS` (or the shared `COLLECTOR_API_KEY`) or is the managed token you minted. Check the client actually read it. The querystring form no longer works. |
|
|
| `Collector API key not configured` | 500 | Fail-closed: no env key set server-side and the caller presented no managed token. A SERVER config gap, not a client problem. |
|
|
| `Endpoint credential is unknown or revoked` | 401 | The PC's credential was revoked, or the database was restored past its issue. The reporter falls back to the shared key on its own; let the PC enroll again to restore it. |
|
|
| `The shared key is not accepted for this endpoint` | 401 | This PC has enrolled, so it must use its own credential - or the shared key is switched off site-wide. Check that `credential.bin` is present and readable by SYSTEM. |
|
|
| `The request names a different endpoint than the credential` | 403 | The hostname in the payload is on a different asset than the credential, or on no computer record at all. The message says which. Do not retry; fix the record. |
|
|
| `No collector registered for plugin computers` | 404 | The plugin is disabled or not loaded on that instance. Enable it. |
|
|
| `hostname is required` / `No data provided` | 400 | Empty body, non-JSON body, or missing identity field. Check `-ContentType 'application/json'`. |
|
|
| `Internal error processing collector payload` | 500 | Generic by design - the server does not leak the cause. The real error is in the server log (`Collector upsert failed for computers`). |
|
|
| `queues is required; send an empty array for a host with no queues` | 400 | The printers payload omitted `queues` entirely. Absent and empty are not the same thing here. |
|
|
| A bay's observed queues all vanished | 200 | It reported `queues: []`, which legitimately clears the host. Check the client log for `posting NOTHING` (a failed enumeration correctly sends nothing) versus an empty set. If the bay really has queues, fix the enumeration on that host. |
|
|
| Observed queues show as `unknown` | 200 | The queue matched no printer asset by port address or name. Add the printer to ShopDB with its IP and re-read - matching happens at read time, so the bay does not need to report again. |
|
|
| `warnings` present but `action` is created/updated | 200 | Soft issues only; the row WAS written. Common: unmapped `pctype`, unknown `osname`, unknown app name, `pcsubtype` not stored. No action needed unless the warning matters to you. |
|
|
| The wrong IP is recorded as primary | 200 | `collector_corporate_ranges` is blank or does not cover this bay. The bay reports every NIC and takes no view; set the ranges. |
|
|
|
|
Client-side logs are under `C:\Logs\Shopfloor\`. Server-side, the Flask app log
|
|
carries upsert failures and per-plugin schema failures.
|