From 57fae57d3b32cc7c3702fc9d2669ab59e61e9c41 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Mon, 1 Jun 2026 12:38:34 -0400 Subject: [PATCH] CMM/DODA: fix DODA paths + CyberArk EPM policy doc - 09-Setup-CMM.ps1: Step 2.5 ACL list targeted C:\Program Files\DODA (a path that never exists), so the BUILTIN\Users write grant on DODA was silently skipped. Corrected to C:\Apps\DODA, where Install-DODA.ps1 actually extracts. - Install-DODA.ps1: create C:\Apps\DODA\PreProcess after extract. The DODA zip unpacks flat without it; MergeFiles.exe expects it and crashed with DirectoryNotFoundException (MergeFiles.GetDoDAFolder) when absent. - docs/cyberark-cmm-doda-policy.md: EPM admin reference for elevating the CMM report toolchain. CyberArk EPM elevation is per-process and not inherited, so the external tools PC-DMIS spawns (MergeFiles/PCDToIGES/RotateProbeVector/ DovetailAnalysis) run un-elevated and fail. Doc gives the Application Group (by SHA-256), the Elevate policy, scope, verify steps, and the CREATE_PDF_FROM_RTF.BAS rework that drops Word/Reader from the elevation set. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/cyberark-cmm-doda-policy.md | 144 ++++++++++++++++++ .../gea-shopfloor-cmm/09-Setup-CMM.ps1 | 2 +- .../gea-shopfloor-cmm/Install-DODA.ps1 | 10 ++ 3 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 docs/cyberark-cmm-doda-policy.md diff --git a/docs/cyberark-cmm-doda-policy.md b/docs/cyberark-cmm-doda-policy.md new file mode 100644 index 0000000..6f070c2 --- /dev/null +++ b/docs/cyberark-cmm-doda-policy.md @@ -0,0 +1,144 @@ +# CyberArk EPM - CMM / DODA elevation policy + +Reference for the CyberArk EPM admin. Fixes the "PC-DMIS is elevated but the +tools it calls error that they are not running elevated" problem on CMM bays. + +## Problem (root cause) + +CyberArk EPM elevation is per-process and is NOT inherited by child processes. +The existing policy elevates PC-DMIS (`PCDLRN.exe`), but the external `.exe` +files the PC-DMIS routine spawns (report, geometry, and DODA tools) launch with +the standard user token (Medium integrity) and fail their own "must run +elevated" check, even though the parent PC-DMIS is elevated. The elevation dies +at the process boundary. + +## Flow that breaks + +The PC-DMIS routine drives in-process `.BAS` scripts that shell out to separate +executables: + +| Step | Process | Separate process? | +|------|---------|-------------------| +| Merge / sort report results | `MergeFiles.exe` (.NET), reads `C:\Apps\DODA\PreProcess\` | yes | +| Geometry export | `PCDToIGES.exe`, `RotateProbeVector.exe` | yes | +| DODA calculation | `DovetailAnalysis.exe` (+ embedded JVM and python) | yes | +| RTF -> PDF, display | `winword.exe`, `AcroRd32.exe` | yes (removed by the BAS rework below) | +| Folder create / save | `MAKEDIR.BAS`, `MAKEFOLDER.bas`, `SaveAsFolder.bas` | no (in-process, uses PC-DMIS token) | + +The in-process file operations inherit PC-DMIS's elevated token. The separate +`.exe` files do not. Those are what get blocked. + +## Fix: one Application Group + one Elevate policy + +Do NOT use "elevate all child processes of PC-DMIS". That would elevate +`cmd.exe` and anything PC-DMIS launches, which is a large hole on a locked-down +shopfloor PC. Elevate only the named toolchain. + +### Application Group: CMM-DODA-Tools + +These are in-house, unsigned tools, so match by SHA-256 (or by path + filename +if the install directory is admin-write-only and the confirmed path is known). + +| App | SHA-256 | Spawns children? | +|-----|---------|------------------| +| `MergeFiles.exe` | `e58ce7599d3bdba816c7ecb183d4f52b32ad8be0b8e4f41813824d8eb472d723` | no | +| `PCDToIGES.exe` | `7bdc961c406f7a0f6f8a10752988a17504bdfd691469c08d20f0d5b6673974cf` | no | +| `RotateProbeVector.exe` | `f8a1b5b0025769fe0d28dc12826ef5d1fbcdba3b29383799c1eb04b955abebdc` | no | +| `DovetailAnalysis.exe` | `86dcb0898bdef4687427ce339520a9c9f5a582890c2241d784fa985019eaaec1` | yes (JVM + python) | + +### Elevate policy + +- Target: the `CMM-DODA-Tools` Application Group +- Action: Elevate (run with administrator rights) +- Applies to: the CMM computer set + the `ShopFloor` user +- Child processes: elevate ONLY for `DovetailAnalysis.exe` (it launches the + embedded JVM and python scripts that do the actual file work). The other + three have no children. +- Match basis: SHA-256 hash + +## Explicitly NOT in the policy + +`winword.exe`, `AcroRd32.exe`, `cmd.exe`. The `CREATE_PDF_FROM_RTF.BAS` rework +(Word writes the PDF to user `%TEMP%`, PC-DMIS moves it to the final path with +its own elevated in-process token, display via the default PDF handler) removes +their need for elevation. Keep Office and Reader out of the elevation set. + +## What the EPM admin needs from GE + +- The computer group = the CMM bays (hostname list, OU, or AD group) +- The user = `ShopFloor` (local account) +- If using path matching instead of hash: the confirmed install directory of the + four exes on a bay (`where MergeFiles.exe`) + +## Verify + +- Before: from elevated PC-DMIS, spawn a child `cmd.exe`, then run + `whoami /groups | findstr Label`. Medium Mandatory Level confirms children are + not elevated (the bug). +- After: the four tools run at High Mandatory Level; report generation plus + copy/move/delete to C: and S: succeed; no "not elevated" error. + +## Caveats + +- Hash churn: rebuilding a tool changes its hash, so the Application Group hash + must be re-stamped. Path + filename matching avoids this IF the install + directory is admin-write-only (so a same-named spoof cannot be dropped there). +- Not an ACL fix: the tools hard-check elevation and bail before touching the + filesystem, so pre-granting NTFS ACLs alone will not unblock them. The EPM + elevation is the actual lever. +- Scope tight: match by hash and scope to the CMM computer group + ShopFloor so + this elevation never applies fleet-wide. + +## Related code fixes (PXE imaging side) + +- `09-Setup-CMM.ps1` Step 2.5 ACL list corrected from `C:\Program Files\DODA` + (nonexistent) to `C:\Apps\DODA` (where `Install-DODA.ps1` actually extracts). +- `MergeFiles.exe` expects `C:\Apps\DODA\PreProcess\`, which the DODA zip does + not create (it extracts flat). A missing `PreProcess` directory is the likely + cause of the historical `MergeFiles.GetDoDAFolder` `DirectoryNotFoundException` + crash (see `cmm-utilities` repo `dotNET event.txt`). Have `Install-DODA.ps1` + create the `PreProcess` subdir, or have whoever deploys the toolchain own it. +- The CMM tool chain (`MergeFiles.exe`, `PCDToIGES.exe`, `RotateProbeVector.exe`, + the `.BAS` scripts) lives in the separate `cmm-utilities` repo and is NOT + deployed by PXE imaging today. Decide whether imaging should own it so the + install path, ACLs, and `PreProcess` directory are consistent. + +## CREATE_PDF_FROM_RTF.BAS rework (removes Word/Reader from the elevation set) + +```vb +' CREATE_PDF_FROM_RTF.BAS - rev 1.0: convert in user temp, then move with +' PC-DMIS's own token; display via default handler (no elevation needed). +Sub Main(filename As String, displayReport As String) + Dim rtfFile As String, finalPdf As String, tempPdf As String + rtfFile = filename & ".RTF" + finalPdf = filename & ".PDF" + Dim base As String + base = Mid(filename, InStrRev(filename, "\") + 1) + tempPdf = Environ$("TEMP") & "\" & base & ".PDF" + + ' Word (un-elevated COM) can write to %TEMP% - a user-writable path. + Dim word As Object + Set word = CreateObject("word.application") + word.Visible = False + word.Documents.Open rtfFile + word.ActiveDocument.SaveAs2 tempPdf, 17 ' 17 = wdFormatPDF + word.Quit + Set word = Nothing + + ' Move temp -> final using PC-DMIS's in-process token (elevated via + ' CyberArk), so the protected/S: destination is written without needing + ' Word itself elevated. FileCopy works across volumes; Name does not. + If Dir(finalPdf) <> "" Then Kill finalPdf + FileCopy tempPdf, finalPdf + Kill tempPdf + + ' Display via the default PDF handler in the user's own context. + If UCase(displayReport) = "TRUE" Then + Dim sh As Object + Set sh = CreateObject("Shell.Application") + sh.ShellExecute finalPdf, "", "", "open", 1 + End If + + Kill rtfFile +End Sub +``` diff --git a/playbook/shopfloor-setup/gea-shopfloor-cmm/09-Setup-CMM.ps1 b/playbook/shopfloor-setup/gea-shopfloor-cmm/09-Setup-CMM.ps1 index 789a667..fb65998 100644 --- a/playbook/shopfloor-setup/gea-shopfloor-cmm/09-Setup-CMM.ps1 +++ b/playbook/shopfloor-setup/gea-shopfloor-cmm/09-Setup-CMM.ps1 @@ -180,7 +180,7 @@ $pcdmisDirs = @( 'C:\Program Files\Hexagon\PC-DMIS 2026.1 64-bit', 'C:\ProgramData\Hexagon', 'C:\Program Files (x86)\General Electric\goCMM', - 'C:\Program Files\DODA' + 'C:\Apps\DODA' ) foreach ($dir in $pcdmisDirs) { if (-not (Test-Path -LiteralPath $dir)) { diff --git a/playbook/shopfloor-setup/gea-shopfloor-cmm/Install-DODA.ps1 b/playbook/shopfloor-setup/gea-shopfloor-cmm/Install-DODA.ps1 index cd5e682..1661704 100644 --- a/playbook/shopfloor-setup/gea-shopfloor-cmm/Install-DODA.ps1 +++ b/playbook/shopfloor-setup/gea-shopfloor-cmm/Install-DODA.ps1 @@ -29,6 +29,16 @@ try { exit 1 } +# MergeFiles.exe (cmm-utilities toolchain) reads C:\Apps\DODA\PreProcess\ as +# its working dir. The DODA zip extracts flat without it, so create it here - +# a missing PreProcess dir is the known cause of MergeFiles.GetDoDAFolder +# throwing DirectoryNotFoundException (see cmm-utilities dotNET event.txt). +$preProcess = Join-Path $installDir 'PreProcess' +if (-not (Test-Path $preProcess)) { + New-Item -Path $preProcess -ItemType Directory -Force | Out-Null + Write-Host "Created $preProcess" +} + if (Test-Path (Join-Path $installDir 'DovetailAnalysis.exe')) { Write-Host "DovetailAnalysis.exe verified present" exit 0