JumpServer PAM Python SDK and Go Agent
Applications can connect to JumpServer directly with the Python SDK or run the Go Agent on the application host. The Agent runs in the foreground on Linux, macOS and Windows; its built-in systemd installer is Linux-only. Clients fetch rotation credentials at startup and keep a signed Credential Event Stream WebSocket open for subscription-account snapshots and later updates. Credential updates, newer reconnect snapshots and manual account switch requests trigger a fetch.
Python interface conventions
Methods, parameters, and response attributes use snake_case; classes use CapWords. Configure the client with keyword arguments, pass operation arguments directly, and use typed responses. A context manager closes the HTTP session:
from jms_pam import Client
from jms_pam_config import client_options, instance_id
with Client(instance_id=instance_id, **client_options) as client:
account = client.get_account(account_id="<account-id>")
username = account.username
password = account.secret
get_account returns the account directly, including the secret, asset and cache provenance.
Fetch the target account with account_id. Apply and verify the application change, then report success or failed using event_id. A delivery receipt or successful fetch does not mean the application succeeded. Events and reconnect snapshot items include event_id, account_id and account_revision. Verify the account version before applying it. Restart and manual switch commands must first be claimed with running. Make application handlers idempotent; a reconnect may repeat an event.
The original request-object API under jms_pam.credential.v1 remains available for compatibility and emits DeprecationWarning. New integrations use the Client API shown here. Regenerate SDK access configuration when migrating to it.
Manually start a policy cycle
Use Start new cycle in the policy's Basic settings or Event reception. The new cycle's timeline opens automatically:
- Credential subscriptions publish
credential.updatedagain for currently authorized accounts, sharing a newoperation_id. Passwords and revisions stay unchanged, and no secret-change start, success or failure events are generated. SDK clients fetch using the event account ID. The Agent also refetches unchanged revisions without repeating delivery or restarting services. Receipts indicate notification reception. Offline clients obtain the current snapshot when reconnecting. - Account rotation starts a new cycle after the previous cycle has completed or been cancelled. JumpServer verifies the backup account, then publishes the switch. Clients apply and confirm the backup. Applications that recently used the original account through the legacy secret API must also fetch the backup after publication. The original account must have no successful JumpServer secret fetches for the configured period (7 days by default) after publication before its secret can be changed. Another source-account fetch restarts the window. Verification, switching, observation, and secret change share one cycle.
Administrator API: POST /api/v1/accounts/application-credentials/<policy-id>/start-cycle/ requires policy change permission and, for account rotation, account verification permission. It returns credential and cycle_id. Disabled policies and unfinished rotations cannot start another cycle. Subscription accounts must finish any running secret changes before republishing.
Manually send application events
Use More > Send event in the application list or Event processing > Send event in application details. Select the event, connection instances and deadline.
credential.switch.requestedasks an application to apply the currently published account and version. It does not change the policy's active account; use the rotation workflow for that. Fetch the credential, verify the requested account and revision, apply it, callconfirm_event(event_id=...), then report success.application.restart.requestedinvokes an SDK application's own restart handler and health check. The Agent only restarts the systemd service configured for EnvironmentFile delivery with the restart action, then checks that it is active.
The WebSocket receipt means received, not executed. execute_application_command(event, handler) claims the request before calling the handler. Only an accepted: true claim runs it; duplicate delivery never repeats the handler. A normal return reports success; an exception reports failure. Implement application-level idempotency and health checks in the handler. Agent switch requests succeed only after the application confirms the actual account version.
Offline instances receive requests on reconnect before their deadline. API applications can instead poll with AK/SK signatures and a stable instance_id; the first poll registers an instance that administrators can subsequently target:
GET /api/v1/accounts/credential-client/commands/?instance_id=<instance-id>returns outstanding requests (list_application_commands()in the SDK). Use the credential client's signed headers and protocol version 1.POST /api/v1/accounts/credential-client/command-result/withinstance_id,command_idandstatus: running. Execute only when the response saysaccepted: true.- Report
status: successorstatus: failedto the same endpoint, optionally including a non-sensitiveerror_code(report_application_command_result()in the SDK).
Expired requests cannot be claimed. If a restart terminates the reporting process, check the application's state before an administrator sends another request. The existing Secret API remains unchanged and does not itself receive manual events.
Choose an integration
| Method | Use when | Application responsibility |
|---|---|---|
| Python SDK | The application can change Python code and reach JumpServer directly | Listen for events, fetch changed credentials, switch connections, and confirm revisions |
| Go Agent | The application should not store JumpServer keys, or needs file, EnvironmentFile, or local Socket delivery | Load and validate Agent-delivered credentials, then confirm the revision actually in use |
Go Agent integration
Linux x86_64 (amd64) · Linux ARM64 · SHA256SUMS
# Run in the directory containing the downloaded Agent and SHA256SUMS.
case "$(uname -m)" in
x86_64) agent_arch=amd64 ;;
aarch64|arm64) agent_arch=arm64 ;;
*) echo "Unsupported CPU architecture"; exit 1 ;;
esac
sha256sum --ignore-missing --check SHA256SUMS && \
sudo install -m 0755 "./jms-pam-agent-linux-${agent_arch}" /usr/local/bin/jms-pam-agent
Download the Agent for your application host CPU architecture from this JumpServer: In Application Management, open the application access wizard, select Agent, and download the configuration. Follow the deployment commands generated by the wizard using a stable, unique instance ID. For Linux systemd installation, use a host with systemd and administrator privileges. After startup, verify that the instance is online in the wizard.
For macOS, non-root Linux or Windows foreground use, select JSON or Socket delivery in the wizard and follow its init-local and run --local --config commands. Initialize only once, then reuse the generated local configuration on restart. Foreground mode uses the current user and does not perform systemd actions; Windows files use private ACLs instead of POSIX mode bits.
/etc/jms-pam-agent/agent.json: 0600; state_file, event_file, delivery.delivery_root, delivery.socket_path.
- JSON:
/opt/jumpserver-pam/credentials/<credential-key>.json - EnvironmentFile:
/opt/jumpserver-pam/credentials/<credential-key>.env - Unix Socket:
/run/jms-pam-agent/agent.sock
Choose JSON for files, EnvironmentFile for a pinned systemd service, or Unix Socket for local API access. The Agent records delivered revisions after delivery succeeds; the application validates and applies credentials before recording an applied revision. The socket belongs to the configured application user with mode 0600; make local requests as that user.
Local rules configure target files, JSON/EnvironmentFile rendering or trusted templates, and an optional systemd reload/restart or fixed executable. Scripts receive credential JSON on stdin, use fixed arguments, have a bounded timeout and must validate their application before returning success. Core cannot add script paths or expand local capabilities. Restart the Agent after editing its private configuration.
The downloaded bootstrap contains Agent identity and delivery settings. Edit rules to declare the account IDs used by the business, update its configuration, activate the change and verify the running connection. An account selector with allow_account_switch also follows A/B rotation in either direction. Optional credential_check validates the new login before file changes. The Agent supplies default state, event and socket paths and a 300-second reconciliation interval. Empty rules write one default file per delivered credential.
{
"endpoint": "https://jumpserver.example.com",
"app_id": "<application-id>",
"app_secret": "<application-secret>",
"org_id": "<org-id>",
"instance_id": "orders-node-1",
"delivery": {
"delivery_mode": "json",
"delivery_root": "/opt/jumpserver-pam/credentials",
"app_user": "orders"
},
"rules": []
}
rules:
[
{
"accounts": [
{
"account_id": "<primary-account-id>",
"allow_account_switch": true
}
],
"config_update": {
"file": "/etc/order-service/config.yml",
"fields_map": {
"DB_USER": "username",
"DB_PASSWORD": "secret"
}
},
"service_action": {
"unit": "order-service.service",
"operation": "restart"
},
"application_check": {
"path": "/usr/local/libexec/jms-pam/check-running-db",
"confirm_on_success": true
}
}
]
jms-pam-agent get_accounts
jms-pam-agent get_secret '<account-id>'
sudo jms-pam-agent check-config
sudo systemctl restart jms-pam-agent
Local API and confirmation
curl --fail --silent --show-error \
--unix-socket '/run/jms-pam-agent/agent.sock' \
http://localhost/v1/health
curl --fail --silent --show-error \
--unix-socket '/run/jms-pam-agent/agent.sock' \
'http://localhost/v1/credentials/<credential-key>'
For alternating rotation, validate a real connection, switch the application connection pool and release old connections before reporting success using the event ID. A failed connection check must prevent confirmation.
/usr/local/bin/jms-pam-agent confirm '<event-id>' \
--socket '/run/jms-pam-agent/agent.sock'
Use the event ID to report application results. A local confirmation is persisted first; status confirmed means Core accepted it, while pending means it will be retried. Do not confirm merely because a file was written or a service restarted.
Troubleshooting
sudo systemctl start jms-pam-agent
sudo systemctl status jms-pam-agent --no-pager
sudo journalctl -u jms-pam-agent -n 100 --no-pager
sudo systemctl restart jms-pam-agent
The Agent reconciles on startup, on relevant events and every 300 seconds. Network failures retain the latest authorized credentials. Identity or authorization rejection blocks socket retrieval; successful signed synchronization restores it. Previously written files remain. SIGINT/SIGTERM closes the server, connections and reader thread.
Python SDK integration
Requires Python 3.9+. Install jms-pam from PyPI or your internal mirror using the application Python or virtual environment, then download the application identity configuration from the access wizard.
python3 -m pip install jms-pam
Place jms_pam_config.py next to the application. Its client_options contain application identity material: do not commit or log it. Use one stable, unique instance_id per replica.
from jms_pam import Client
from jms_pam_config import client_options, instance_id
with Client(instance_id=instance_id, **client_options) as client:
account = client.get_account(account_id="<account-id>")
username = account.username
password = account.secret
Events and credential application
Fetch the target account with account_id. Apply and verify the application change, then report success or failed using event_id. A delivery receipt or successful fetch does not mean the application succeeded. Events and reconnect snapshot items include event_id, account_id and account_revision. Verify the account version before applying it. Restart and manual switch commands must first be claimed with running. Make application handlers idempotent; a reconnect may repeat an event.
from jms_pam import Client
from jms_pam_config import client_options, instance_id
def apply_account(account):
# Validate a new connection, switch the pool, then release old connections.
# Never log account.secret or authentication headers.
raise NotImplementedError("Implement the application's account update first")
def restart_application():
raise NotImplementedError("Implement application restart and health check first")
class ApplicationClient(Client):
def apply_event(self, event):
if event.get("event") == "application.restart.requested":
restart_application()
return
account = self.get_account(
account_id=event["account_id"], allow_local_fallback=False,
)
if account.revision != event["account_revision"]:
raise ValueError("The event account version is superseded")
apply_account(account)
def handle_event(self, event):
event_id = event["event_id"]
if event.get("command_id"):
claim = self.report_application_command_result(
command_id=event["command_id"], status="running",
)
if not claim.accepted:
return
try:
self.apply_event(event)
except Exception:
self.confirm_event(
event_id=event_id, status="failed", error_code="application_failed",
)
raise
# A fetch or delivery receipt never confirms application success.
self.confirm_event(event_id=event_id)
def run(self):
for event in self.watch_credential_events():
if event.get("command_id"):
updates = [event]
elif event.get("event") == "snapshot":
updates = event.get("credentials", [])
# Release application connections absent from the new scope.
elif event.get("event") == "credential.updated":
updates = [event]
elif event.get("event") == "credential.revoked":
# Release connections for event["account_id"].
continue
else:
continue
for update in updates:
try:
self.handle_event(update)
except Exception as error:
self.on_event_error(error, update)
with ApplicationClient(instance_id=instance_id, **client_options) as client:
client.run()
Common methods
get_account(account_id=..., allow_local_fallback=True)account.username/account.secret/account.asset/account.from_localconfirm_event(event_id=..., status="success" | "failed", error_code=...)watch_credential_events(stop_event=...)list_application_commands()report_application_command_result(command_id=..., status="running")clone()/close()
get_credential and key-based confirmation remain available for older integrations. New integrations use get_account and confirm_event. The event-result workflow requires the corresponding Core update; SDK 1.0.2 alone cannot add this server capability.
Metadata
Release files for jms-pam 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| jms_pam-1.0.2.tar.gz | 62.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jms_pam-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 106.7 kB
Release files / jms_pam-1.0.2.tar.gz
| Download URL | jms_pam-1.0.2.tar.gz |
|---|---|
| Size | 62.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d986ed6d05aefca60ea83bffd6718c34f0cc33b20d7dd84408ef7e89f33946cc
|
|
BLAKE2b-256 checksum How to use checksums |
33a3d8b21c3877503a73ae1db9bfd8c02127d8acea56e7aee0d96178228afefc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / jms_pam-1.0.2-py3-none-any.whl
| Download URL | jms_pam-1.0.2-py3-none-any.whl |
|---|---|
| Size | 44.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
203ed76bd7619f30e2f95c2f53e21bcf19223b04ea4cdbdffc4d4a6288b6cac5
|
|
BLAKE2b-256 checksum How to use checksums |
5d2598a39cc30b39499154f000268aac768aee1ceb988450f9efcd65a2da1746
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logSecurity for jms-pam 1.0.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for jms_pam-1.0.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.