-
Notifications
You must be signed in to change notification settings - Fork 4
Secrets & Keychain
Add a profile at the prompts and jamf-cli stores the secrets in your system keychain. It prompts for credentials with hidden input, which keeps them out of shell history and process listings.
jamf-cli config add-profile prod \
--url https://jamf.company.com \
--auth-method oauth2
# You'll be prompted: Client ID: abc123
# Client Secret: ********The config file holds a reference:
profiles:
prod:
url: https://jamf.company.com
auth-method: oauth2
client-id: keychain:jamf-cli/prod/client-id
client-secret: keychain:jamf-cli/prod/client-secretThe values live in macOS Keychain (or Linux secret-service).
A credential's accepted source depends on who holds it. The rule keeps secrets out of shell history, ps output and CI logs.
| Credential | Accepted from |
|---|---|
Human: a Jamf Pro account username and password (pro setup --credentials create) |
Interactive prompts only, password read with hidden input. No flag, no environment variable, no stdin. Never stored. |
| Machine: bearer token, client ID, client secret, Jamf School API key, Jamf Security Cloud application secrets |
JAMF_* / JAMFPROTECT_* / JAMFSCHOOL_* / JAMFSECURITY_* environment variables for CI/CD; interactive prompts for manual use; keychain: / env: / file: profile references for persistent storage; --token-file for a file-based bearer token in CI. |
Consequences:
-
No command has a
--password,--token,--client-secret,--token-stdinor--client-secret-stdinflag, and none will be added. A credential inargvshows up inpsand lands in shell history and CI logs. -
Setup commands prompt.
pro setup,protect setup,school setup,security setup,platform setupandconfig add-profilecollect credentials with hidden input, and each refuses--no-input. For unattended use, set the environment variables and skip profiles, or write the profile withenv:/file:references (below). -
A flag may name a credential's source; it may never carry the value.
pro setup --credentials existing|createis the shape that makes the distinction concrete:existingtakes an API client you already created in Jamf Pro,createhas jamf-cli make one, and both branches read every secret from an interactive prompt. Neither accepts one from a flag, an environment variable or stdin, and both refuse--no-input. -
A credential is proved before it is written.
pro setup --credentials existingandconfig add-profileeach do one client-credentials token exchange, and a failure writes nothing.config add-profile --no-verifyskips it for offline pre-seeding; the check is skipped anyway fortokenauth (a bearer token is only testable by spending it) and for anenv:orfile:reference, often written on a machine that cannot reach the server it names.Verification says the pair is valid and nothing about whether its privileges reach any command. A 403 at the point of use answers that, in wording setup cannot produce.
-
Some commands take a secret as payload data (
pro computer-inventory set-auto-admin-password, for instance). Those read it from a file (--password-file) or prompt for it.
On headless systems with no keychain, take one of two approaches.
Environment variables, the shortest path for CI/CD, with no config file:
# Jamf Pro instance (oauth2)
export JAMF_URL="https://jamf.company.com"
export JAMF_CLIENT_ID="your-client-id"
export JAMF_CLIENT_SECRET="your-client-secret"
jamf-cli pro computers list --no-inputFor the platform gateway, the same three variables plus the scope level the integration was created at. The gateway host is enough to select platform auth, which makes an organization-scoped credential (one naming no scope ID) usable this way:
export JAMF_URL="https://us.api.jamfcloud.com"
export JAMF_CLIENT_ID="your-client-id"
export JAMF_CLIENT_SECRET="your-client-secret"
export JAMF_ENVIRONMENT_ID="your-environment-id" # or JAMF_TENANT_ID, and never both
jamf-cli pro blueprints list --no-inputNeither scope ID is a secret: they are identifiers, and they are the part of a platform profile you can commit. Setting both is refused with a usage error, since an integration is created at one level and its credential works with that level alone. See Configuration & Profiles#Scope levels for what each level reaches, and Platform API GA Migration if you are coming from the public beta, whose credentials were revoked at GA.
Config file with secret references, for persistent profiles on headless systems. Write the config file with env: or file: prefixed values:
# CI/CD: reference environment variables
profiles:
ci:
url: https://jamf.company.com
auth-method: oauth2
client-id: env:JAMF_CLIENT_ID
client-secret: env:JAMF_CLIENT_SECRET
# Docker/Kubernetes: reference mounted secret files
container:
url: https://jamf.company.com
auth-method: oauth2
client-id: file:/run/secrets/jamf-client-id
client-secret: file:/run/secrets/jamf-client-secretWith a prefix, jamf-cli stores the value in config as-is and the keychain stays out of it.
| Prefix | Syntax | Resolved at |
|---|---|---|
keychain: |
keychain:jamf-cli/prod/client-secret |
Runtime: reads from system keychain |
env: |
env:JAMF_CLIENT_SECRET |
Runtime: reads from environment variable |
file: |
file:/run/secrets/jamf-token |
Runtime: reads and trims file contents |
jamf-cli resolves secrets at runtime, so the environment variables and files need to exist when you run a command.
The full format is keychain:service/profile/field. Omit the service when it is jamf-cli (the default):
keychain:jamf-cli/prod/client-secret # explicit
keychain:prod/client-secret # equivalent (default service)
Adding a profile: bare secret values go to the keychain. Prefixed values (env:, file:) go into config as-is.
Removing a profile: jamf-cli finds any keychain: references and deletes the matching keychain items:
$ jamf-cli config remove-profile prod
Removed keychain item: jamf-cli/prod/client-secret
Profile "prod" removed.
Setup wizard: each setup command stores its secrets in the keychain, under <profile>/<field>:
| Command | Keychain fields written |
|---|---|
pro setup |
client-id, client-secret, on both --credentials branches. existing stores the pair you typed; create stores the pair it generated. |
platform setup |
client-id, client-secret
|
protect setup |
client-id, client-secret
|
school setup |
network-id, api-key, plus client-id / client-secret when platform access was configured |
security setup |
risk-client-id, risk-client-secret, lifecycle-client-id, lifecycle-client-secret, sse-client-id, sse-client-secret, for the pairs entered |
platform setup and security setup merge into a profile of the same name, so one profile holds both the gateway credentials and the Radar pairs. Running one after the other in either order keeps both.
On headless systems, use config add-profile with env: or file: instead.
Validating: run config validate to check that every secret resolves before you deploy.
The system credential store can refuse a write: a locked login keychain on macOS surfaces as an opaque code like exit status 154. Setup and config add-profile wrap these failures with OS-specific guidance:
-
macOS: unlock the login keychain with
security unlock-keychain ~/Library/Keychains/login.keychain-db, then retry. -
Linux: start and unlock a Secret Service provider (e.g. GNOME Keyring /
gnome-keyring-daemon). -
Anywhere: fall back to a config profile with
env:orfile:secret references (see above), which leave the keychain untouched.
For a one-off command with no saved profile, use environment variables or --token-file. See CI/CD & Scripting#Authentication in CI for the full env var reference and CI pipeline examples.
# Quick one-off with env vars
export JAMF_URL=https://jamf.company.com
export JAMF_CLIENT_ID=abc123
export JAMF_CLIENT_SECRET=s3cret
jamf-cli pro computers list
# Token from a file
jamf-cli --url https://jamf.company.com \
--token-file /run/secrets/jamf-token \
pro computers list- No plaintext secrets in config: the CLI rejects a bare value unless it can auto-store it to the keychain
- Keychain failure is fatal: the CLI reports it and stores nothing in plaintext
-
Config file permissions: created
0600(owner read/write only) in a0700directory -
Safe to share config output:
config showprints references such askeychain:jamf-cli/prod/client-secret, with no secret values -
No credential flags or stdin: the CLI accepts no credential as a flag or through a stdin pipe, which keeps them out of process listings and shell history. Use environment variables, config profiles,
--token-file, or interactive prompts
Repository · Issues · Releases
jamf-cli Wiki
- Home
- Community
- Getting Started
- CLI Reference
- Product Commands
- Workflows
- Configuration
- Reference
Products
- Jamf Pro:
jamf-cli pro - Jamf Platform API:
jamf-cli pro(blueprints, benchmarks, DDM reports) - Jamf Platform:
jamf-cli platform(AI Governance, Jamf Account, audit) - Jamf Protect:
jamf-cli protect - Jamf School:
jamf-cli school - Jamf Security Cloud:
jamf-cli security