This commit is contained in:
2026-06-25 14:43:13 -05:00
parent 6f77fac58e
commit aaa6a9ee26
25 changed files with 1542 additions and 67 deletions

118
README.md
View File

@@ -29,7 +29,7 @@ The current UI is a Vue/Vite view layer over the Express API. All create/update/
- PSADT Best Practice Verifier for saved scripts, rendered profiles, and pasted script content with severity scoring, line-aware findings, remediation text, and rule metadata.
- Intune Publishing Wizard for PSADT Win32 deployment plans, including package source, `.intunewin` tracking, command style, UI compatibility, requirements, detection rules, return-code policy, assignment rings, status, Graph app ID, and visibility.
- Microsoft Graph Intune tracking for PSADT deployments, with Graph environment configuration managed under Config / Intune plus mobile app linking, status sync, failure review, device/user status rows, and sync run history.
- Host Library with searchable/sortable/paginated table, modal add/edit flow, and VMware vCenter VM import wizard with preview filters and credential attachment.
- Host Library with searchable/sortable/paginated table, modal add/edit flow, VMware vCenter VM import wizard, and manual/dynamic Host Groups for RunPlan and script-test targeting.
- Credential Vault as its own menu item with encrypted-at-rest secrets and modal add/edit flow.
- RunPlan Library with searchable/sortable/paginated table, modal composer, and execute action.
- Aggregate job log viewer with search/filter/pagination.
@@ -165,6 +165,7 @@ Important environment variables:
| `VCENTER_API_MODE` | `auto`, `api`, or `rest`. Defaults to `auto`, which tries modern `/api` then legacy `/rest` on incompatible endpoints. |
| `VCENTER_REQUEST_TIMEOUT_MS` | Per-request vCenter HTTP timeout. Defaults to `20000`. |
| `VCENTER_ALLOW_UNTRUSTED_TLS` | Set `true` to allow self-signed/private CA vCenter certificates. |
| `HOST_GROUP_SYNC_INTERVAL_MINUTES` | Minutes between dynamic Host Group rule syncs. Defaults to `60`; set `0` to disable the worker. |
| `CATALOG_CHECK_INTERVAL_MINUTES` | Minutes between catalog upstream-version checks. `0` disables. |
| `AUTO_PROMOTE_INTERVAL_MINUTES` | Minutes between auto-promote soak checks. `0` disables. |
| `TOOLS_DIR` | Directory for bundled tools. Defaults to `./tools`. |
@@ -505,9 +506,20 @@ Payload:
| --- | --- | --- | --- |
| `GET` | `/api/hosts` | User | List host library. |
| `POST` | `/api/hosts` | User | Create host. |
| `GET` | `/api/hosts/import/vcenter/status` | User | Return effective vCenter import configuration status without the password. |
| `GET` | `/api/hosts/import/vcenter/status` | User | Return legacy effective vCenter status plus visible saved vCenter systems. |
| `GET` | `/api/hosts/import/vcenter/connections` | User | List visible saved vCenter systems. |
| `POST` | `/api/hosts/import/vcenter/connections` | User | Create an encrypted vCenter system record. |
| `PUT` | `/api/hosts/import/vcenter/connections/:connectionId` | User | Update a visible vCenter system; omit password to keep the existing secret. |
| `DELETE` | `/api/hosts/import/vcenter/connections/:connectionId` | User | Delete a visible vCenter system. |
| `POST` | `/api/hosts/import/vcenter/connections/:connectionId/test` | User | Authenticate and list VM summaries to verify a vCenter system. |
| `POST` | `/api/hosts/import/vcenter/preview` | User | Authenticate to vCenter, search VM inventory, and return import candidates. |
| `POST` | `/api/hosts/import/vcenter` | User | Import selected vCenter VM candidates as hosts, attaching the chosen credential/defaults. |
| `GET` | `/api/hosts/groups` | User | List visible manual and dynamic Host Groups with member counts. |
| `POST` | `/api/hosts/groups` | User | Create a manual or dynamic Host Group. |
| `PUT` | `/api/hosts/groups/:groupId` | User | Update a visible Host Group. Manual groups accept explicit host members; dynamic groups accept rules. |
| `DELETE` | `/api/hosts/groups/:groupId` | User | Delete a visible Host Group and its membership rows. |
| `POST` | `/api/hosts/groups/:groupId/sync` | User | Recalculate one dynamic Host Group immediately. |
| `POST` | `/api/hosts/groups/sync` | User | Recalculate all dynamic Host Groups immediately. |
| `PUT` | `/api/hosts/:id` | User | Update host. |
| `DELETE` | `/api/hosts/:id` | User | Delete host. |
@@ -525,15 +537,88 @@ Payload:
"tags": ["production", "database"],
"notes": "Primary SQL host",
"visibility": "shared",
"groupId": null
"groupId": null,
"sourceType": "manual",
"sourceConnectionId": null,
"sourceRef": ""
}
```
`transport` can be `winrm`, `ssh`, `local`, or `api`. `visibility` can be
`personal`, `shared`, or `group`; hosts default to `shared`. RunPlans can only
target hosts visible to the operator who creates or edits them.
target hosts visible to the operator who creates or edits them. `sourceType`,
`sourceConnectionId`, and `sourceRef` are hidden provenance fields. Manual
hosts default to `sourceType: "manual"`. vCenter imports set
`sourceType: "vmware"`, `sourceConnectionId` to the selected vCenter system,
and `sourceRef` to the vCenter VM id.
VMware vCenter import uses the effective Config / Integrations values (`vcenter_*` settings or the `VCENTER_*` environment variables). `vcenter_api_mode` can be `auto`, `api`, or `rest`. `api` uses the current vSphere Automation API flow (`POST /api/session`, `GET /api/vcenter/vm`). `rest` uses the legacy/community vCenter REST flow (`POST /rest/com/vmware/cis/session`, `GET /rest/vcenter/vm`). `auto` tries the current `/api` profile first and falls back to `/rest` when the endpoint is not supported.
Host Groups let operators aggregate manual, imported, and VMware-sourced hosts
without duplicating RunPlans. Manual groups store an explicit list of visible
host IDs that an operator can add/remove in the Hosts screen. Dynamic groups
store rules and are recalculated by the API worker every
`host_group_sync_interval_minutes` minutes, by the
`HOST_GROUP_SYNC_INTERVAL_MINUTES` environment variable, or on demand with the
Sync Now actions. Dynamic group membership is rule-owned, so the UI does not
allow hand-picking members for those groups.
Create a manual Host Group:
```json
{
"name": "Engineering Manual",
"description": "Pinned engineering test machines.",
"mode": "manual",
"hostIds": ["hst_101", "hst_205"],
"visibility": "shared",
"groupId": null
}
```
Create a dynamic Host Group:
```json
{
"name": "Engineering",
"description": "Any visible host whose name contains ENG.",
"mode": "dynamic",
"matchMode": "all",
"rules": [
{ "field": "name", "operator": "contains", "value": "ENG" }
],
"visibility": "shared",
"groupId": null
}
```
Dynamic group rule fields are `name`, `fqdn`, `address`, `tags`, `transport`,
`sourceType`, and `osFamily`. Operators can combine rules with `matchMode:
"all"` or `matchMode: "any"`. Operators can use `contains`, `equals`,
`startsWith`, and `endsWith` operators. Rule matching is evaluated only against
hosts the group owner/creator can see through personal/shared/group visibility.
Create/update a saved vCenter system:
```json
{
"name": "Production vCenter",
"baseUrl": "https://vcenter.contoso.local",
"username": "administrator@vsphere.local",
"password": "stored-encrypted-on-save",
"apiMode": "auto",
"requestTimeoutMs": 20000,
"allowUntrustedTls": false,
"enabled": true,
"visibility": "shared",
"groupId": null
}
```
Saved vCenter passwords are encrypted with the same credential-store key used
by the Credential Vault. Existing `vcenter_*` settings and `VCENTER_*`
environment variables remain supported as the `Configured default` import
connection for single-vCenter deployments or Docker-provided configuration.
VMware vCenter import can use a saved vCenter system selected by `connectionId` or the legacy configured default from Config / Integrations (`vcenter_*` settings or `VCENTER_*` environment variables). `apiMode` / `vcenter_api_mode` can be `auto`, `api`, or `rest`. `api` uses the current vSphere Automation API flow (`POST /api/session`, `GET /api/vcenter/vm`). `rest` uses the legacy/community vCenter REST flow (`POST /rest/com/vmware/cis/session`, `GET /rest/vcenter/vm`). `auto` tries the current `/api` profile first and falls back to `/rest` when the endpoint is not supported.
For exact VM-name searches (`field: "name"`, `operator: "equals"`), POSHManager uses the documented server-side name filters: `names=<vm>` for `/api/vcenter/vm` and `filter.names=<vm>` for `/rest/vcenter/vm`. Contains/starts-with/ends-with searches are filtered locally because vCenter VM list filters do not provide wildcard contains semantics. The combined `hostname` field searches both the VM inventory name and the VMware Tools guest `host_name`/FQDN after enrichment. VM display-name matches are checked first, then the rest of the inventory is still enriched for guest-only hostname matches. Networking/IP enrichment is only requested for candidates that match the filter. FQDN and IP discovery depends on VMware Tools data; when guest data is unavailable, the import falls back to the VM name as the host address and records the limitation in host notes.
@@ -547,6 +632,7 @@ Preview payload:
```json
{
"connectionId": "vc_...",
"filter": {
"field": "hostname",
"operator": "contains",
@@ -560,6 +646,7 @@ Import payload:
```json
{
"connectionId": "vc_...",
"filter": {
"field": "hostname",
"operator": "contains",
@@ -582,6 +669,14 @@ previewed candidates that match the filter are considered. Existing visible
hosts with the same name, address, or FQDN are skipped and returned in the
`skipped` array so imports can be rerun safely.
When a script test or RunPlan targets a host with `sourceType: "vmware"`, the
runner checks the current vCenter power state for `sourceRef` through the stored
vCenter connection before spawning PowerShell. VMs that are not `POWERED_ON`
are logged and marked `skipped` for that host, so powered-off machines are not
treated like script failures. If the vCenter connection is missing or the
management API is temporarily unavailable, the runner logs the reason and
continues execution rather than blocking the whole job on a control-plane issue.
### Script Library
| Method | Route | Auth | Description |
@@ -1008,7 +1103,9 @@ The catalog returned by `/api/psadt/catalog` also includes `intune` coverage for
### RunPlans And Jobs
RunPlans pair one script with one or more host IDs. Execution creates a job with per-host log rows.
RunPlans pair one script with one or more direct host IDs, Host Group IDs, or
both. Execution expands Host Groups into their current members and creates a job
with per-host log rows.
| Method | Route | Auth | Description |
| --- | --- | --- | --- |
@@ -1031,10 +1128,17 @@ RunPlan payload:
"visibility": "shared",
"groupId": null,
"parallel": true,
"hostIds": ["hst_..."]
"hostIds": ["hst_..."],
"hostGroupIds": ["hg_..."]
}
```
`hostIds` target individual hosts. `hostGroupIds` target visible Host Groups.
Manual groups run against their saved members. Dynamic groups run against the
membership from the latest scheduler/manual sync, so use the Hosts screen Sync
Now action before execution when a just-imported host should be picked up
immediately.
Execute:
```bash