Skip to content

[AIGTWY-4678] MDM/JAMF bootstrap script for headless ug provisioning - #697

Open
david-siqi-liu wants to merge 3 commits into
mainfrom
david/mdm-bootstrap
Open

david-siqi-liu wants to merge 3 commits into
mainfrom
david/mdm-bootstrap

Conversation

@david-siqi-liu

@david-siqi-liu david-siqi-liu commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a headless MDM / JAMF bootstrap for Unity Gateway (AIGTWY-4678):

  • scripts/mdm-bootstrap.sh provisions a bare machine end to end: ensures uv + node, installs ug, writes a PAT-based Databricks profile, runs ug configure --use-pat non-interactively, then probes every workspace-enabled_agents entry with a real one-shot inference call through the gateway.
  • scripts/mdm/ holds JAMF configuration-profile templates for the OS-managed enforcement layer, deployed separately from provisioning.

Two-layer model

  • Provisioning (this script, run as root by JAMF): installs ug + local settings + auth. Runs configure and the probes with stdin from /dev/null so ug stays non-interactive: it writes only local settings and does not attempt the sudo OS-managed reconciliation, so there is no password prompt.
  • Enforcement (scripts/mdm/): JAMF configuration profiles deploy the OS-managed settings that enforce gateway routing even for bare claude / codex launches — Claude Code via com.anthropic.claudecode, Codex via com.openai.codex (base64 TOML). See scripts/mdm/README.md.

How to run it

Inputs are environment variables only (JAMF reserves positional parameters $1-$4).

Required:

  • UG_WORKSPACE_HOST — Databricks workspace URL
  • UG_PAT — personal access token for that workspace

Optional:

  • UG_PROFILE_NAME (default ug-mdm)
  • UG_AGENTS (default: the workspace's enabled_agents)
  • UG_INSTALL_SPEC (default git+https://github.com/databricks/unity-gateway)
  • UG_NODE_VERSION (only used if node is absent)
  • UG_SKIP_PROBE (set to skip the inference probe)

Invocation used to test (macOS):

UG_WORKSPACE_HOST="https://eng-ml-agent-platform.staging.cloud.databricks.com" \
UG_PAT="<pat>" \
./mdm-bootstrap.sh

For JAMF: deploy the script unchanged and upload a 3-line wrapper as the policy script that maps JAMF parameters $5/$6 to UG_WORKSPACE_HOST/UG_PAT (snippet in the script header, staying clear of the reserved $1-$4).

Known gaps (surfaced by this work, to track separately)

  • ug headless auth is PAT-only; no service-principal (OAuth M2M) path for fleet machine identity.
  • ug can't emit the OS-managed profile payloads for MDM packaging (only writes them in place via interactive sudo).

Test evidence (macOS, arm64)

==> Unity Gateway MDM bootstrap (Darwin/arm64)

==> Validating inputs
  ✓ workspace: https://eng-ml-agent-platform.staging.cloud.databricks.com
  ✓ profile:   ug-mdm
    agents: from workspace enabled_agents

==> Dependency: curl + git
  ✓ curl and git present

==> Dependency: uv
  ✓ uv present (uv 0.12.3 (507230998 2026-08-07 aarch64-apple-darwin))

==> Dependency: node + npm
  ✓ node present (v24.20.0), npm present (11.19.0)

==> Installing Unity Gateway (ug)
    uv tool install --force git+https://github.com/databricks/unity-gateway
Resolved 52 packages in 6.10s
Installed 52 packages in 30ms
 + unity-gateway==0.1.0+176.gceb7730 (from git+https://github.com/databricks/unity-gateway@ceb7730fd0c87dbb0db731fc5821f34bfd3e65ed)
   (+ 51 dependency packages)
Installed 2 executables: ucode, ug
  ✓ ug installed (0.1.0+176.gceb7730)

==> Writing Databricks CLI profile [ug-mdm]
  ✓ wrote profile to /Users/david.l/.databrickscfg (mode 600)

==> Configuring ug (headless, PAT)
    ug configure --profile ug-mdm --use-pat
✔ Databricks auth already available for https://eng-ml-agent-platform.staging.cloud.databricks.com
✔ Unity Gateway connected
✔ A managed config is published for your workspace.
• Applying it to the agents your admin enabled: Claude Code, Codex.
• Updated Claude Code: ~/.claude/ucode-settings.json, /Library/Application Support/ClaudeCode/managed-settings.json
• Updated Codex: ~/.codex/ucode.config.toml, ~/.ucode/codex-model-catalog.json, /etc/codex/managed_config.toml
╭────────────────────── Workspace-managed config ───────────────────────╮
│ Workspace: https://eng-ml-agent-platform.staging.cloud.databricks.com │
│ Enabled agents: Claude Code, Codex                                    │
│ MCPs: none configured                                                 │
│ Skills: none configured                                               │
╰───────────────────────────────────────────────────────────────────────╯
• You're all set — run `ug` to launch with your managed settings.
  ✓ ug configured

==> Probing enabled agents (real inference)
  ✓ claude responded: ✔ Databricks auth already available for  https://eng-ml-agen
  ✓ codex responded: ✔ Databricks auth already available for  https://eng-ml-agen
    probed 2 agent(s), 0 failed
  ✓ all enabled agents responded

==> Done
  ✓ ug is installed and configured; enabled agents verified.
    Run 'ug' to launch the default agent.

Note: the "Updated ... managed-settings.json / managed_config.toml" lines reflect OS-managed files already present and compatible from an earlier interactive run on this test machine. The non-interactive configure this script uses does not create or modify the OS-managed files on a fresh machine (per the managed-settings behavior matrix); those are deployed via the Layer 2 profiles.

This pull request and its description were written by Isaac.

@david-siqi-liu david-siqi-liu added the quicktree-assisted PR created with quicktree-assisted workflow label Sep 16, 2026
@david-siqi-liu
david-siqi-liu marked this pull request as ready for review September 16, 2026 23:39
david-siqi-liu and others added 2 commits September 17, 2026 16:59
scripts/mdm-bootstrap.sh provisions a bare machine end to end: ensures
uv + node, installs ug, writes a PAT Databricks profile, runs
`ug configure --use-pat` headlessly (which also installs the enabled
agent CLIs), then probes every managed enabled_agents entry with a
one-shot inference call. Inputs are env vars only (JAMF-safe). For
JAMF mass deployment (AIGTWY-4678).

Co-authored-by: Isaac <no-reply@databricks.com>
Run `ug configure` and the agent probes with stdin from /dev/null so ug
stays non-interactive: it writes only local settings and never attempts
the sudo OS-managed reconciliation, removing the password prompt (matches
JAMF's non-TTY behavior).

Add scripts/mdm/ with JAMF configuration-profile templates for the
OS-managed enforcement layer, deployed separately from provisioning:
Claude Code via com.anthropic.claudecode and Codex via com.openai.codex
(base64 TOML), plus a README explaining the two-layer split. For
AIGTWY-4678.

Co-authored-by: Isaac <no-reply@databricks.com>
Add `test_ug_configure_managed_via_pat`: configure the managed workspace
through a `[ug-mdm]` PAT profile + `ug configure --profile ug-mdm --use-pat`,
exactly as scripts/mdm-bootstrap.sh does, and assert the same managed-config
outcome (no selector, admin's static models in Claude's picker and Codex's
catalog) plus `use_pat` in state and a real launch. This is the only coverage
of the MDM headless auth path; existing managed CUJs use `--workspace` plus
the runner's bearer.

The token comes from the durable `E2E_ADMIN_SP_PAT` CI secret (a stored
SP-minted PAT; the runner's own bearer is hourly M2M). Thread that secret
through the runner's pytest env allowlist and the managed workflow job; the
test skips when it's unset. For AIGTWY-4678.

Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

quicktree-assisted PR created with quicktree-assisted workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant