Skip to content

ci: build signed .intunewin release artifact + registry version marker#121

Merged
ashishkurmi merged 3 commits into
step-security:mainfrom
raysubham:ci/intunewin-release-artifact
May 29, 2026
Merged

ci: build signed .intunewin release artifact + registry version marker#121
ashishkurmi merged 3 commits into
step-security:mainfrom
raysubham:ci/intunewin-release-artifact

Conversation

@raysubham
Copy link
Copy Markdown
Contributor

Summary

  • Add .intunewin artifact to the release pipeline so Intune Win32 deployments can consume the MSI directly via the Intune portal without manual repacking.
  • Add stable HKLM\Software\StepSecurity\AgentVersion registry value the MSI writes on every install. Intune detection rules consume it via String Equals <version>. Required because Intune supersedence breaks ProductCode-based detection (each rebuild regenerates the ProductCode).
  • Microsoft Win32 Content Prep Tool pinned to v1.8.7 (commit 1d6cfcbdf8c28edc596337031f74df951f38f718), fetched via commit-pinned raw URL, then verified by SHA-256 + Microsoft Authenticode signature before use.
  • .intunewin is an encrypted ZIP and cannot itself be Authenticode-signed; the signed MSI inside is preserved verbatim and extracted by IME on the endpoint -- trust chain holds end-to-end (Azure Trusted Signing -> MSI -> MSI-in-.intunewin -> MSI-extracted-on-device). Sigstore + SLSA attestation applied to the outer .intunewin in the same pattern as the MSI artifact.

Test plan

  • `workflow_dispatch` on this branch produces `.intunewin` for x64 + arm64
  • cosign bundles emitted for both `.intunewin` files
  • SLSA attestations emitted for both `.intunewin` files
  • SHA-256 of `IntuneWinAppUtil.exe` matches pinned value on a fresh runner
  • Microsoft Authenticode subject check passes
  • Deploy resulting `.intunewin` via Intune -> install succeeds on a Windows test VM
  • `HKLM\Software\StepSecurity\AgentVersion` populated with current `$version` after install
  • Intune detection rule (registry `String Equals`) reports Detected

Adds a .intunewin release artifact so Intune Win32 deployments can
consume the MSI via the Intune portal without manual repacking, and
adds a stable HKLM\Software\StepSecurity\AgentVersion registry value
written on every install. Intune detection rules consume that value
via `String Equals <version>`; ProductCode-based detection breaks
under Intune supersedence because each rebuild regenerates the
ProductCode, so the stable registry path is required for supersedence
chains to detect installed versions correctly.

Packaging runs in the existing windows-sign-and-package job after the
MSI is Authenticode-signed. The Microsoft Win32 Content Prep Tool is
pinned to v1.8.7 (commit 1d6cfcbdf8c28edc596337031f74df951f38f718),
fetched via commit-pinned raw URL, then verified by SHA-256 and
Microsoft Authenticode signature before use. The .intunewin format
itself is an encrypted ZIP and cannot be Authenticode-signed, but the
signed MSI bytes inside it are preserved verbatim and extracted by
IME on the endpoint -- trust chain holds end-to-end. Sigstore signing
+ SLSA build attestation are applied to the outer .intunewin in the
same pattern as the MSI artifact.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the Windows release and deployment story by producing Intune-friendly .intunewin artifacts in CI and adding a stable registry-based version marker written by the MSI to support Intune detection rules across supersedence scenarios.

Changes:

  • Add a stable HKLM\Software\StepSecurity\AgentVersion registry value (written by the MSI) for Intune/SCCM detection.
  • Extend the GitHub Actions release workflow to download/verify IntuneWinAppUtil.exe, pack x64/arm64 MSIs into .intunewin, then Sigstore-sign and attest those artifacts.
  • Update Windows packaging documentation to describe Intune detection via the registry marker.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packaging/windows/README.md Documents Intune detection using a stable registry value written by the MSI.
packaging/windows/Product.wxs Adds a WiX component that writes HKLM\Software\StepSecurity\AgentVersion to the MSI version and includes it in the main feature.
.github/workflows/release.yml Adds .intunewin packaging, signing, uploading, and provenance attestation steps to the release pipeline.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packaging/windows/README.md Outdated
Comment on lines +125 to +126
distinguishes versions across supersedence. See
[`docs/deploying-via-intune.md`](../../docs/deploying-via-intune.md#page-4-detection-rules).
$sha256 = 'c1ba45b5cb939e84af064bb7ff4b38fb3dfe33c8dc1078fd9b157672eae671f6'
$dst = 'dist/tools/IntuneWinAppUtil.exe'
New-Item -ItemType Directory -Path (Split-Path $dst) -Force | Out-Null
Invoke-WebRequest -Uri $url -OutFile $dst -UseBasicParsing
The relative link to docs/deploying-via-intune.md resolves to a 404 on
main until the separate docs PR lands. Drop the link and point at the
Intune deployment guide in prose so the README has no broken reference
regardless of merge order.
@raysubham raysubham marked this pull request as ready for review May 29, 2026 13:40
Match the packaging shape validated on real Intune during the POC. The
release pipeline now stages install.cmd + uninstall.cmd + the signed MSI
and packs with -s install.cmd, instead of feeding the MSI as the setup
file directly.

Why the wrapper over MSI-direct:
- install.cmd forces /l*v verbose logging to
  %ProgramData%\StepSecurity\install.log on every deploy (MSI-direct
  leaves logging to whatever each admin types in the portal command).
- install.cmd forwards Intune's install-command args (APIKEY, CUSTOMERID,
  APIENDPOINT, SCANFREQUENCY) to msiexec via %*.
- uninstall.cmd gives a single uniform Intune uninstall command across
  every version in a supersedence chain, vs MSI-direct's per-build
  msiexec /x {ProductCode} that diverges as ProductCode rotates.
- Ships exactly the shape already validated end-to-end on Intune, so we
  test what we ship.

The signed MSI is preserved verbatim inside the encrypted payload; the
trust chain is unchanged.
@ashishkurmi ashishkurmi merged commit d40b3a7 into step-security:main May 29, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants