The master PNG was fully opaque, so its white corners showed as a square frame once macOS composited the icon onto its rounded plate. Swap in the auditor-mode artwork, which has transparent corners. Signed-off-by: Ludovic Vielle <ludovic@probo.com>
234 lines
10 KiB
Markdown
234 lines
10 KiB
Markdown
# Release `probo-agent`
|
||
|
||
After confirming commits below, follow the
|
||
[common steps](./README.md#3-common-steps-every-track).
|
||
|
||
## Track facts
|
||
|
||
- **Tag pattern**: `probo-agent/v*`
|
||
- **Version source**: `cmd/probo-agent/VERSION` (single `X.Y.Z` line)
|
||
- **Version bump**: Edit `cmd/probo-agent/VERSION` directly
|
||
- **Changelog**: `cmd/probo-agent/CHANGELOG.md`
|
||
- **Files to stage**: `cmd/probo-agent/VERSION`, `cmd/probo-agent/CHANGELOG.md`
|
||
- **Workflow**: `.github/workflows/release-probo-agent.yaml`
|
||
- **Path filter**: `cmd/probo-agent pkg/deviceagent`
|
||
|
||
## Detect commits
|
||
|
||
```shell
|
||
git log $(git describe --tags --abbrev=0 --match='probo-agent/v*')..HEAD --oneline \
|
||
-- cmd/probo-agent pkg/deviceagent
|
||
```
|
||
|
||
If empty or non-user-facing only, do not release this track.
|
||
|
||
## Build
|
||
|
||
```shell
|
||
make bin/probo-agent
|
||
```
|
||
|
||
On macOS hosts, `make` enables CGO so the menu bar enrollment helper
|
||
is included. Windows tray support is pure Go (`CGO_ENABLED=0`). Linux
|
||
and FreeBSD builds stay pure Go (no tray).
|
||
|
||
## Notes
|
||
|
||
CI builds binaries for linux, windows, and freebsd (amd64/arm64) on
|
||
Linux runners, and builds **CGO-enabled** darwin archives plus a
|
||
signed/notarized fat `.pkg` on a macOS runner. The GitHub
|
||
Release includes those archives, `probo-agent_*_darwin.pkg`,
|
||
`install.sh`, signed checksums, SBOM, and build attestations. The agent
|
||
auto-update path downloads the matching archive plus `checksums.txt` and
|
||
verifies the cosign bundle before installing.
|
||
|
||
The menu bar / tray enrollment flow is **macOS and Windows only**.
|
||
Linux and FreeBSD use `probo-agent install --server …
|
||
--enrollment-token …` from the shell, or the curl-to-sh installer
|
||
documented below. Windows release binaries are cross-compiled from
|
||
Linux with `CGO_ENABLED=0` (tray is pure Go). macOS release binaries
|
||
and the `.pkg` are built on macOS with `CGO_ENABLED=1`.
|
||
|
||
### macOS `.pkg` (MDM / GUI install)
|
||
|
||
Release and local builds use
|
||
`cmd/probo-agent/installer/macos/build.sh` (requires macOS, a
|
||
pre-built fat binary via `lipo`, and the Swift toolchain).
|
||
**Signing is mandatory:** `CODESIGN_IDENTITY` and `APPLE_TEAM_ID`
|
||
must be set. The script compiles `Probo Agent.app` (the headless
|
||
`probo://` URL handler + privileged helper) from
|
||
`cmd/probo-agent/installer/macos/enroll-ui/`, signs nested Mach-Os
|
||
then the app bundle, optionally signs the product with
|
||
`INSTALLER_IDENTITY`, and notarizes/staples when `APPLE_ID` and
|
||
`APPLE_ID_PASSWORD` are set (password is stored into a keychain
|
||
profile; submits use `--keychain-profile` so the secret is not on
|
||
`notarytool submit` argv).
|
||
|
||
The Finder/Dock icon for `Probo Agent.app` comes from a single master
|
||
PNG, `cmd/probo-agent/installer/macos/enroll-ui/Resources/icon-original.png`
|
||
(Probo square mark). At PKG build time `build.sh` pads/resizes it with
|
||
`sips`, compiles `AppIcon.icns` with `iconutil` under the build stage
|
||
directory, and installs it into `Contents/Resources/`. `Info.plist`
|
||
sets `CFBundleIconFile` to `AppIcon`. Do not commit generated
|
||
`.icns` / iconset PNGs.
|
||
|
||
The master PNG must have the rounded-square mark pre-baked with fully
|
||
transparent corners. macOS composites legacy `.icns` icons onto a light
|
||
rounded plate, so any opaque pixel outside the rounded square renders as
|
||
a visible square frame around the mark.
|
||
|
||
There is no unsigned PKG path and no osascript elevation fallback.
|
||
Local testing of browser enrollment requires a Developer ID–signed
|
||
build. CLI enrollment without the app uses `sudo probo-agent install`.
|
||
|
||
```shell
|
||
# Local signed pkg (example)
|
||
export CODESIGN_IDENTITY="Developer ID Application: Probo Inc (TEAMID)"
|
||
export INSTALLER_IDENTITY="Developer ID Installer: Probo Inc (TEAMID)"
|
||
export APPLE_TEAM_ID="TEAMID"
|
||
|
||
GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 go build -o dist/probo-agent_arm64 ./cmd/probo-agent
|
||
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 go build -o dist/probo-agent_amd64 ./cmd/probo-agent
|
||
lipo -create dist/probo-agent_arm64 dist/probo-agent_amd64 -output dist/probo-agent_universal
|
||
cmd/probo-agent/installer/macos/build.sh \
|
||
--binary dist/probo-agent_universal \
|
||
--version "$(cat cmd/probo-agent/VERSION)"
|
||
```
|
||
|
||
PKG postinstall always installs the global tray LaunchAgent, registers
|
||
`probo://`, and installs the privileged helper
|
||
(`com.probo.agent.helper`) under `/Library/PrivilegedHelperTools` as
|
||
root. The only admin authentication is the normal macOS Installer
|
||
prompt for the PKG itself. The LaunchDaemon for `probo-agent run` is
|
||
created only after enrollment (`probo-agent install`, deep link, or MDM
|
||
`/tmp/probo-agent.conf`).
|
||
|
||
Browser enrollment uses `Probo Agent.app` over XPC to the
|
||
PKG-installed helper — no SMJobBless and no admin prompt on the enroll
|
||
path. A missing or dead helper surfaces an error asking to reinstall
|
||
the package.
|
||
|
||
Manual QA checklist (macOS PKG):
|
||
|
||
1. Fresh signed PKG: Installer may ask for admin once; deep link enrolls with no further prompt.
|
||
2. Repeat deep link on an enrolled device: no prompt, immediate success.
|
||
3. After `sudo make -C cmd/probo-agent uninstall`, deep link fails with a clear “reinstall package” error (no osascript).
|
||
4. `sudo make -C cmd/probo-agent uninstall` removes daemon, tray, helper, app, and state.
|
||
5. MDM `/tmp/probo-agent.conf` postinstall still enrolls without a browser prompt.
|
||
6. Notarized PKG passes Gatekeeper; `codesign --verify --deep` succeeds on the app bundle.
|
||
7. Unsigned `build.sh` exits with an error requiring `CODESIGN_IDENTITY`.
|
||
|
||
### Apple signing secrets (GitHub)
|
||
|
||
The `build-macos` job in `release-probo-agent.yaml` expects the same
|
||
secret names as the auditor-mode release workflow. Configure these on
|
||
the probo GitHub repository (or org) before tagging a release:
|
||
|
||
| Secret | Purpose |
|
||
|--------|---------|
|
||
| `APPLE_CERTIFICATE` | Base64-encoded `.p12` (Developer ID) |
|
||
| `APPLE_CERTIFICATE_PASSWORD` | `.p12` password |
|
||
| `KEYCHAIN_PASSWORD` | Ephemeral CI keychain password |
|
||
| `CODESIGN_IDENTITY` | e.g. `Developer ID Application: Probo Inc (TEAMID)` |
|
||
| `INSTALLER_IDENTITY` | e.g. `Developer ID Installer: Probo Inc (TEAMID)` |
|
||
| `APPLE_ID` | Apple ID email for `notarytool store-credentials` |
|
||
| `APPLE_ID_PASSWORD` | App-specific password (stored into a keychain profile; not passed to `submit`) |
|
||
| `APPLE_TEAM_ID` | 10-character Team ID |
|
||
|
||
Local notarization uses the same env vars as CI:
|
||
|
||
```shell
|
||
export APPLE_ID="you@example.com"
|
||
export APPLE_ID_PASSWORD="app-specific-password"
|
||
# optional: NOTARYTOOL_KEYCHAIN_PROFILE=probo-agent-notary (default)
|
||
```
|
||
|
||
Windows enrollment is browser-driven: the console issues a
|
||
`probo://enroll?server=...&token=...` deep link handled by
|
||
`Probo Agent.app` on macOS (PKG-installed helper + XPC) or
|
||
`probo-agent enroll-url` on Windows. After install, register the protocol for the
|
||
current user with
|
||
`cmd/probo-agent/installer/windows/register-protocol.ps1` (per-user
|
||
`HKCU` handler pointing at `probo-agent.exe`). The system tray helper
|
||
(`probo-agent tray`) shows enrollment status; enrollment itself happens
|
||
in the browser.
|
||
|
||
Region labels and console URLs for the macOS installer HTML live in
|
||
`cmd/probo-agent/installer/regions.json`. A Go test keeps US/EU URLs in
|
||
sync with `pkg/deviceagent/server_url.go`.
|
||
|
||
## Install script
|
||
|
||
`cmd/probo-agent/installer/install.sh` is published as `install.sh` on each
|
||
`probo-agent/v*` GitHub Release. It supports Darwin, Linux, and FreeBSD.
|
||
Each published `install.sh` pins one release: the release workflow injects
|
||
the tag and archive SHA-256 checksums into the script before upload.
|
||
|
||
```shell
|
||
# Interactive — curl install.sh from the target release
|
||
curl -fsSL "https://github.com/getprobo/probo/releases/download/probo-agent/vX.Y.Z/install.sh" | sudo sh
|
||
|
||
# Unattended / MDM
|
||
curl -fsSL "…/install.sh" | sudo \
|
||
PROBO_SERVER_URL=https://us.probo.com \
|
||
PROBO_ENROLLMENT_TOKEN='…' sh
|
||
|
||
# Mirror release assets (PROBO_AGENT_RELEASE_BASE must end with the embedded tag)
|
||
PROBO_AGENT_RELEASE_BASE="https://mirror.example/probo-agent/vX.Y.Z" \
|
||
curl -fsSL "…/install.sh" | sudo sh
|
||
```
|
||
|
||
The script downloads only the matching platform archive and verifies its
|
||
SHA-256 against checksums embedded in `install.sh` at release time. This
|
||
anchors trust to the script the user already obtained, rather than a
|
||
co-downloaded `checksums.txt`. Post-install upgrades still use cosign
|
||
bundle verification via the agent auto-update path.
|
||
|
||
The script installs the binary to `/usr/local/bin/probo-agent`, then runs
|
||
`probo-agent install` to enroll and start the OS service. Agent state defaults
|
||
to `/var/lib/probo-agent` (override with `--dir` or `PROBO_AGENT_STATE_DIR`).
|
||
|
||
Environment variables:
|
||
|
||
| Variable | Purpose |
|
||
|----------|---------|
|
||
| `PROBO_AGENT_RELEASE_BASE` | Override release download base URL (must match embedded tag) |
|
||
| `PROBO_AGENT_RELEASE_TAG` | Override embedded release tag (local dev) |
|
||
| `PROBO_AGENT_SKIP_CHECKSUM_VERIFY` | Skip SHA-256 verification (local dev only) |
|
||
| `PROBO_AGENT_STATE_DIR` | Agent state directory (`--dir`; default `/var/lib/probo-agent`) |
|
||
| `PROBO_SERVER_URL` | Probo server base URL (skip interactive prompt) |
|
||
| `PROBO_ENROLLMENT_TOKEN` | One-shot enrollment token (skip interactive prompt) |
|
||
| `PROBO_NO_AUTO_UPDATE` | Set to `true` to pass `--no-auto-update` |
|
||
|
||
Never pass the enrollment token in the curl URL.
|
||
|
||
## Local install (macOS PKG)
|
||
|
||
Primary loop for testing browser enrollment (app + privileged helper):
|
||
|
||
```shell
|
||
export CODESIGN_IDENTITY="Developer ID Application: … (TEAMID)"
|
||
export INSTALLER_IDENTITY="Developer ID Installer: … (TEAMID)" # optional
|
||
export APPLE_TEAM_ID="TEAMID"
|
||
|
||
make -C cmd/probo-agent install # uninstall leftovers → build PKG → installer
|
||
make -C cmd/probo-agent uninstall # full system teardown (idempotent)
|
||
make -C cmd/probo-agent clean # uninstall + wipe dist/ caches / enroll-ui/.build
|
||
```
|
||
|
||
`install` always runs `uninstall` first so previous helpers, apps, and
|
||
Launch Services registrations cannot shadow the new build. Signing env
|
||
vars are required for `pkg` / `install` on Darwin.
|
||
|
||
### CLI-only install (no app / helper)
|
||
|
||
Binary-only path via `installer/install.sh` (any Unix). State under
|
||
`~/.local/share/probo-agent-dev`; staging under `~/.cache/probo-agent-dev`.
|
||
|
||
```shell
|
||
make -C cmd/probo-agent install-cli \
|
||
PROBO_SERVER_URL=https://us.probo.com \
|
||
PROBO_ENROLLMENT_TOKEN='…'
|
||
make -C cmd/probo-agent run
|
||
```
|