Utility functions commonly used in Jamf deployment scripts.
Project description
pymdm
A Python utility package for MDM deployment scripts, providing common functionality for Jamf Pro policy scripts and system automation.
Designed for use with MacAdmins Python (#!/usr/local/bin/managed_python3), which comes pre-shipped with requests and other useful packages.
Features
- MdmLogger: Structured logging with file output, rotation, and multiple log levels
- ParamParser: Safe parsing of Jamf Pro script parameters (4-11)
- CommandRunner: Secure subprocess execution with credential sanitization
- SystemInfo: System information helpers (serial number, console user, hostname)
- WebhookSender: Send logs and metadata to webhooks
- Dialog: swiftDialog integration for user-facing dialogs and notifications
Installation
From Source
uv pip install -e .
Development
make install-dev # Install with dev dependencies
make test # Run tests
make format # Format code with black and ruff
Quick Start
Logging
from pymdm import MdmLogger
logger = MdmLogger(
debug=True,
output_path="/var/log/my_script.log"
)
logger.info("Script started")
logger.debug("Detailed information")
logger.warn("Warning message")
logger.error("Error occurred", exit_code=1)
Jamf Parameters
from pymdm import ParamParser
# Get string parameter
webhook_url = ParamParser.get(4) # $4 in Jamf policy
# Get boolean parameter
debug_mode = ParamParser.get_bool(5) # "true", "1", "yes" → True
# Get integer parameter
timeout = ParamParser.get_int(6, default=30)
Command Execution
from pymdm import CommandRunner
runner = CommandRunner(logger=logger)
# Safe execution (list form)
output = runner.run(["/usr/bin/id", "-u", username])
# Shell execution (for pipes, etc.)
output = runner.run("ps aux | grep python", timeout=10)
System Information
from pymdm import SystemInfo
# Get serial number
serial = SystemInfo.get_serial_number()
# Get console user info
user_info = SystemInfo.get_console_user()
if user_info:
username, uid, home_path = user_info
# Get hostname
hostname = SystemInfo.get_hostname()
# Get full name
full_name = SystemInfo.get_user_full_name("jsmith")
Webhook Integration
from pymdm import WebhookSender, MdmLogger
logger = MdmLogger(output_path="/var/log/script.log")
webhook = WebhookSender(
url="https://hooks.tray.io/...",
logger=logger
)
# Send log with metadata
webhook.send(
hostname=SystemInfo.get_hostname(),
serial=SystemInfo.get_serial_number(),
script_name="my_deployment_script",
status="success"
)
Complete Example
#!/usr/local/bin/managed_python3
"""Example Jamf Pro policy script."""
from pymdm import (
MdmLogger,
ParamParser,
CommandRunner,
SystemInfo,
WebhookSender,
)
# Setup
logger = MdmLogger(
debug=ParamParser.get_bool(4),
output_path="/var/log/my_script.log"
)
runner = CommandRunner(logger=logger)
logger.log_startup("my_script", version="1.0.0")
try:
# Get system info
serial = SystemInfo.get_serial_number()
hostname = SystemInfo.get_hostname()
logger.info(f"Running on {hostname} ({serial})")
# Execute command
output = runner.run(["/usr/bin/sw_vers", "-productVersion"])
logger.info(f"macOS version: {output}")
# Send results
webhook = WebhookSender(
url=ParamParser.get(5),
logger=logger
)
webhook.send(
hostname=hostname,
serial=serial,
status="success"
)
except Exception as e:
logger.log_exception("Script failed", e, exit_code=1)
Requirements
- Python 3.12+
requests(included with MacAdmins Python)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pymdm-0.3.0.tar.gz.
File metadata
- Download URL: pymdm-0.3.0.tar.gz
- Upload date:
- Size: 29.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a96ee40695b081e2bae33448b87e32eded5e716428a2e1fc6f627fb75cd5c5ca
|
|
| MD5 |
592068ce05cc115b22092eedb3aebe93
|
|
| BLAKE2b-256 |
e8be0ee8463fc55b7f66143107e67af79022346a79cb66943602a53a114f0d27
|
Provenance
The following attestation bundles were made for pymdm-0.3.0.tar.gz:
Publisher:
build-release.yml on liquidz00/pymdm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymdm-0.3.0.tar.gz -
Subject digest:
a96ee40695b081e2bae33448b87e32eded5e716428a2e1fc6f627fb75cd5c5ca - Sigstore transparency entry: 811992864
- Sigstore integration time:
-
Permalink:
liquidz00/pymdm@4698a7105d4f4b0ae93719c4fbd9bf79e594e50f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/liquidz00
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-release.yml@4698a7105d4f4b0ae93719c4fbd9bf79e594e50f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pymdm-0.3.0-py3-none-any.whl.
File metadata
- Download URL: pymdm-0.3.0-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b97754171c2867ebba24a878768ea512190f3c1a487b26ea17b340ba40d468a
|
|
| MD5 |
48f35b6269e80260e368b3bfef0f0133
|
|
| BLAKE2b-256 |
a00e573ae7f12c359d8fa6d18cda71b4609ecf83269cf688a3901002df1ab5b5
|
Provenance
The following attestation bundles were made for pymdm-0.3.0-py3-none-any.whl:
Publisher:
build-release.yml on liquidz00/pymdm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymdm-0.3.0-py3-none-any.whl -
Subject digest:
5b97754171c2867ebba24a878768ea512190f3c1a487b26ea17b340ba40d468a - Sigstore transparency entry: 811992868
- Sigstore integration time:
-
Permalink:
liquidz00/pymdm@4698a7105d4f4b0ae93719c4fbd9bf79e594e50f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/liquidz00
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-release.yml@4698a7105d4f4b0ae93719c4fbd9bf79e594e50f -
Trigger Event:
workflow_dispatch
-
Statement type: