Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fd4e9eb
Platform-specific defaults for Windows
ferricoxide Jun 3, 2026
462567c
Download and execute installer/setup EXE
ferricoxide Jun 3, 2026
b7d59f9
Try to ensure adequate idempotency:
ferricoxide Jun 3, 2026
952b1b3
Make an overrideable version-parameter available
ferricoxide Jun 3, 2026
7d5262a
Update to account for non-vendor download URIs
ferricoxide Jun 3, 2026
1936e4a
Externalize requisite-script's logic to the install-helper script
ferricoxide Jun 3, 2026
8d69a59
Fix copy-paystah error
ferricoxide Jun 3, 2026
f55de39
Ensure no orphans after copy
ferricoxide Jun 3, 2026
440dc98
With real contents, this is no longer needed
ferricoxide Jun 3, 2026
6c740ef
Add PowerShell-linting to CI tests
ferricoxide Jun 3, 2026
0559cc5
Make ready to run on STIGed hosts
ferricoxide Jun 4, 2026
d9ed897
Tune process-mitigation exclusions
ferricoxide Jun 4, 2026
a3ff047
Moar enterprise-user 'readiness' tasks
ferricoxide Jun 4, 2026
397da90
fix resource-type delcaration
ferricoxide Jun 4, 2026
9c8f4c9
Gotta be more pedantic
ferricoxide Jun 4, 2026
572ed62
Ensure system PATH-env includes Postman
ferricoxide Jun 4, 2026
71fa8a1
Remove unused directory-components
ferricoxide Jun 4, 2026
0ba0dcc
Reverse win_install tasks
ferricoxide Jun 4, 2026
ec941cf
Ensure that GUI doesn't eat entire screen
ferricoxide Jun 4, 2026
a0376ff
Add P3 standard CI tests for Windows targets
ferricoxide Jun 4, 2026
712c05a
Address PSSScriptAnalyzer lints
ferricoxide Jun 4, 2026
fa91cb7
Updates changelog to describe updates included by PR
ferricoxide Jun 4, 2026
051a23f
Eliminate obsoleted parameters
ferricoxide Jun 4, 2026
4f33ce7
Re-align pillar.examples to current parms' usage
ferricoxide Jun 4, 2026
aeba16b
Add Windows deployment-details to the "Notes" section
ferricoxide Jun 4, 2026
6a33a73
Match version to CHANGELOG's
ferricoxide Jun 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.0
current_version = 0.1.1
commit = True
message = Bumps version to {new_version}
tag = False
Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,56 @@ jobs:
salt-os-version: ${{ matrix.os_version }}
salt-state: ${{ matrix.salt_state }}
salt-pillar-root: ${{ matrix.salt_pillar_root }}

windows:
uses: plus3it/actions-workflows/.github/workflows/test-salt-windows.yml@ddd67e99878a285f728de398c1116151c2d7791a
strategy:
matrix:
os_version:
- windows-2019
- windows-2022
- windows-2025
salt_state:
- postman-api
salt_pillar_root:
- ./tests/pillar/test-postman-api
with:
salt-os-version: ${{ matrix.os_version }}
salt-state: ${{ matrix.salt_state }}
salt-pillar-root: ${{ matrix.salt_pillar_root }}


lint_powershell:
name: PowerShell Linting
runs-on: windows-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Run PSScriptAnalyzer
shell: pwsh
run: |
$files = Get-ChildItem -Path ./ -Include *.ps1 -Recurse
Write-Host "--- Starting PowerShell Static Analysis ---"

$anyErrors = $false

foreach ($file in $files) {
$relativePath = $file.FullName.Replace($PWD.ProviderPath, ".")
$results = Invoke-ScriptAnalyzer -Path $file.FullName -Severity Warning

if ($results) {
Write-Host "FAIL: $relativePath" -ForegroundColor Red
$results | Format-Table -AutoSize
$anyErrors = $true
} else {
Write-Host "PASS: $relativePath" -ForegroundColor Green
}
}

if ($anyErrors) {
Write-Error "Static analysis failed. Please fix the errors above."
exit 1
} else {
Write-Host "--- All files passed analysis! ---"
}
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

### 0.1.1

**Released**: 2026.06.04

**Summary**:

* Added Windows functionality
* Installs the Postman API binary (as downloaded from [vendor site](https://www.postman.com/downloads/))
* Install-location defaults to `C:\Program Files\Postman`
* Install-location overrideable via Pillar's `install_root` parameter
* Installs latest installable version — v12.13.5 as of this document's writing (override via Pillar's `download_uri` parameter)
* Sets appropriate ownerships, permissions, etc. on content loaded into `install_root`
* Creates a desktop-launcher icon for all users
* Creates a launcher icon in the `Start` menus for all users
* Configures the launchers to constrain the initial-startup window to 85% of the display size
* Adds CI tests for Windows platforms (currently Windows Server 2019, 2022 and 2025)
* Updates pillar.example to explain Windows-specific parameters/inputs that may be specified via Pillar
* Update README with platform-notes

### 0.1.0

**Released**: 2026.06.02
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ Executes _just_ the `config` state to uninstall the Postman API client-configura
1. Due to library compatibilities, the installable version of Postman on RHEL 9 (and derivatives) is constrained to < `11.x`. This formula defaults the RHEL 9 (and derivatives) installation to Postman version `10.24.26`
1. To support hardened enterprise baselines (such as the DISA STIG or CIS profiles), this formula defaults to disabling the Chromium application sandbox (`sandbox_enabled: false`) on Red Hat family distributions. These security profiles typically disable unprivileged user namespaces (`user.max_user_namespaces = 0`), which causes Electron-based applications to crash instantly on startup. For less restrictive environments where user namespaces are permitted, the sandbox can be safely re-enabled by setting `sandbox_enabled: true` via Pillar data.

### Windows

1. **Headless Session 0 Execution:** The native Squirrel-based Postman installer package will deadlock or hang indefinitely when executed inside a headless `SYSTEM` context (Session 0) because it attempts to synchronously generate user-centric desktop interactive pathways. This formula handles this limitation by staging a purpose-built PowerShell management wrapper (`install_postman.ps1`) that orchestrates a monitored extraction, forces termination of the blocked installation threads, migrates application files to the designated global `install_root`, and purges staging profiles.
2. **Virtual Framebuffer Scaling Overrides:** To prevent the hardcoded Electron canvas landing layout from overflowing low-resolution framebuffers typical of remote automated pipelines or thin management consoles, system shortcuts are automatically configured with Chromium layout engine switches (`--window-size=1024,768` and `--force-device-scale-factor=0.85`) to guarantee complete interface visibility.

[^1]: As of this README's writing, only Enterprise Linux and related distros (Red Hat and Oracle Enterprise, CentOS Stream, Rocky and Alma Linux). It has only been specifically tested with EL **_9_** variants.
[^2]: As of this README's writing, this functionality has only been tested on Windows Server 2022
11 changes: 9 additions & 2 deletions pillar.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
---
postman-api:
config:
# Path where the system desktop entry file will be generated.
# Path where the system desktop entry file will be generated (Linux only).
desktop_entry: '/usr/share/applications/postman.desktop'

# Relative path to the application icon inside the installation directory.
icon_source: '/app/resources/app/assets/icon.png'

# The root directory tree where the application archive is extracted.
# Natively supports paths containing spaces (e.g., '/opt/Desktop Apps/Postman').
# Natively supports Linux paths and Windows filesystem paths
# (e.g., 'C:\Program Files\Postman').
install_root: '/opt/Postman'

# Controls Chromium's internal application isolation sandbox layer.
Expand All @@ -35,6 +36,8 @@ postman-api:
whitelist_enabled: true

# The system path for the generated wrapper execution bash script.
# Supports Linux paths and Windows execution script pathways
# (e.g., 'C:\Program Files\Postman\postman.cmd').
wrapper_bin: '/usr/local/bin/postman'

pkg:
Expand All @@ -48,4 +51,8 @@ postman-api:

# The internal name designation used for formula mapping identification.
name: 'postman-api'

# The target application version string expected for the deployment
# (e.g., '12.13.5' or 'latest'). Used primarily by Windows targets.
version: 'latest'
...
1 change: 1 addition & 0 deletions postman-api/config/file.sls
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ include:
- postman-api.config.lin_file
{%- elif grains.kernel == "Windows" %}
- postman-api.config.win_file
- postman-api.config.win_readiness
{%- endif %}

Avoid being a null-router (config/file) - Postman API:
Expand Down
32 changes: 32 additions & 0 deletions postman-api/config/win_clean.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# vim: ft=sls

{#- Get the `tplroot` from `tpldir` #}
{%- set tplroot = tpldir.split('/')[0] %}
{%- from tplroot ~ "/map.jinja" import mapdata as postman_api with context %}
{%- set image_execution_options_reg =
'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\'
~ 'Image File Execution Options\\Postman.exe' %}
{%- set start_menu_shortcut_path =
'C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Postman.lnk' %}

Remove Postman Desktop Shortcut:
file.absent:
- name: 'C:\Users\Public\Desktop\Postman.lnk'

Remove Process Mitigation Exclusions:
reg.absent:
- name: '{{ image_execution_options_reg }}'

Remove Protocol Deep Linking Registration:
reg.absent:
- name: 'HKLM\SOFTWARE\Classes\postman'

Remove Start Menu Shortcut:
file.absent:
- name: '{{ start_menu_shortcut_path }}'

Reverse Global Suppression of Automatic Updates:
host.absent:
- ip: '127.0.0.1'
- name: 'dl.pstmn.io'
76 changes: 76 additions & 0 deletions postman-api/config/win_file.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
# vim: ft=sls

{#- Get the `tplroot` from `tpldir` #}
{%- set tplroot = tpldir.split('/')[0] %}
{%- from tplroot ~ "/map.jinja" import mapdata as postman_api with context %}

Configure Postman Desktop Shortcut:
shortcut.present:
- arguments: '--window-size=1024,768 --force-device-scale-factor=0.85'
- icon_index: 0
- icon_location: '{{ postman_api.config.install_root }}\Postman.exe'
- name: 'C:\Users\Public\Desktop\Postman.lnk'
- target: '{{ postman_api.config.install_root }}\Postman.exe'
- working_dir: '{{ postman_api.config.install_root }}'

Configure Process Mitigation Exclusions:
cmd.run:
- name: >-
Set-ProcessMitigation
-Name Postman.exe
-Disable DisallowChildProcessCreation
- shell: powershell
- unless: >-
$postmanProcessMitigation = Get-ProcessMitigation
-Name Postman.exe -ErrorAction SilentlyContinue;
$childProcessStatus = $postmanProcessMitigation.
ChildProcess.DisallowChildProcessCreation;
if ($childProcessStatus -eq 'OFF') { exit 0 }
else { exit 1 }

Configure Protocol Deep Linking Base:
reg.present:
- name: 'HKLM\SOFTWARE\Classes\postman'
- vdata: 'URL:postman Protocol'
- vname: '(Default)'
- vtype: REG_SZ

Configure Protocol Deep Linking Command:
reg.present:
- name: 'HKLM\SOFTWARE\Classes\postman\shell\open\command'
- vdata: '"{{ postman_api.config.install_root }}\Postman.exe" "%1"'
- vname: '(Default)'
- vtype: REG_SZ

Configure Protocol Deep Linking Protocol Value:
reg.present:
- name: 'HKLM\SOFTWARE\Classes\postman'
- vdata: ''
- vname: 'URL Protocol'
- vtype: REG_SZ

Configure Start Menu Shortcut:
shortcut.present:
- arguments: '--window-size=1024,768 --force-device-scale-factor=0.85'
- icon_index: 0
- icon_location: '{{ postman_api.config.install_root }}\Postman.exe'
- name: 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Postman.lnk'
- target: '{{ postman_api.config.install_root }}\Postman.exe'
- working_dir: '{{ postman_api.config.install_root }}'

Harden Postman Directory Permissions:
file.directory:
- name: '{{ postman_api.config.install_root }}'
- win_inheritance: true
- win_owner: 'BUILTIN\Administrators'
- win_perms:
BUILTIN\Administrators:
perms: full_control
BUILTIN\Users:
perms: read_execute

Suppress Automatic Updates Globally:
host.present:
- ip: '127.0.0.1'
- name: 'dl.pstmn.io'
16 changes: 16 additions & 0 deletions postman-api/config/win_readiness.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# vim: ft=sls

{#- Get the `tplroot` from `tpldir` #}
{%- set tplroot = tpldir.split('/')[0] %}
{%- from tplroot ~ "/map.jinja" import mapdata as postman_api with context %}

Configure Postman API into System PATH Entry:
win_path.exists:
- name: '{{ postman_api.config.install_root }}'

Opt Out of Postman API Telemetry:
environ.setenv:
- name: POSTMAN_DISABLE_TELEMETRY
- permanent: HKLM
- value: '1'
Loading
Loading