Skip to content

Commit

Permalink
Merge pull request #17 from macadmins/send-mdm-command-docs
Browse files Browse the repository at this point in the history
Documenting Pro API MDM commands.
  • Loading branch information
brysontyrrell committed Oct 19, 2023
2 parents edc89e3 + 510a615 commit db8e7ff
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 1 deletion.
3 changes: 3 additions & 0 deletions docs/reference/models_pro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ JCDS2
File
DownloadUrl

.. _MDM Command Models:

MDM Commands
------------

Expand All @@ -71,6 +73,7 @@ MDM Commands
EraseDeviceCommand
EraseDeviceCommandObliterationBehavior
EraseDeviceCommandReturnToService
LogOutUserCommand
RestartDeviceCommand
ShutDownDeviceCommand
SendMdmCommandResponse
Expand Down
57 changes: 56 additions & 1 deletion docs/user/pro_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,59 @@ Here is an example of a paginated request using the SDK with the sorting and fil
... sort_expression=SortField("id").asc(),
... filter_expression=FilterField("operatingSystem.version").lt("13.")
... )
>>>
>>>
MDM Commands
------------
The SDK provides MDM commands in the form of models that are passed to the :meth:`~jamf_pro_sdk.clients.pro_api.ProApi.send_mdm_command_preview` method.
.. code-block:: python
>>> from jamf_pro_sdk import JamfProClient, BasicAuthProvider
>>> from jamf_pro_sdk.models.pro.mdm import LogOutUserCommand
>>> client = JamfProClient("dummy.jamfcloud.com", BasicAuthProvider("demo", "tryitout"))
>>> response client.pro_api.send_mdm_command_preview(
... management_ids=["4eecc1fb-f52d-48c5-9560-c246b23601d3"],
... command=LogOutUserCommand()
... )
The ``response`` will contain an array of :class:`~jamf_pro_sdk.models.pro.mdm.SendMdmCommandResponse` objects that have the IDs of the commands sent. Those IDs can be used with the ``uuid`` filter of :meth:`~jamf_pro_sdk.clients.pro_api.ProApi.get_mdm_commands_v2` to get the command's status.
Basic MDM commands with no additional properties can be passed as instantiated objects as shown above with the ``LogOutUserCommand`` command. For other commands the additional properties can be set after instantiation, or a dictionary of values can be unpacked.
.. code-block:: python
>>> from jamf_pro_sdk.models.pro.mdm import EraseDeviceCommand
>>> command = EraseDeviceCommand()
>>> command.pin = "123456"
>>> command = EraseDeviceCommand(**{"pin": "123456"})
Commands with required properties must have those values passed at instantiation.
.. code-block:: python
>>> from jamf_pro_sdk.models.pro.mdm import EnableLostModeCommand
>>> command = EnableLostModeCommand()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pydantic/main.py", line 341, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 3 validation errors for EnableLostModeCommand
lostModeMessage
field required (type=value_error.missing)
lostModePhone
field required (type=value_error.missing)
lostModeFootnote
field required (type=value_error.missing)
>>> command = EnableLostModeCommand(
... lostModeMessage="Please return me to my owner.",
... lostModePhone="123-456-7890",
... lostModeFootnote="No reward."
... )
>>>
Read the documentation for :ref:`MDM Command Models` for all support MDM commands and their properties.
18 changes: 18 additions & 0 deletions src/jamf_pro_sdk/clients/pro_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,24 @@ def send_mdm_command_preview(
This API is labeled as a **Preview** by Jamf. It may change or become deprecated in
favor of another API in a future release.
Example usage:
.. code-block:: python
from jamf_pro_sdk.models.pro.mdm import LogOutUserCommand
client.pro_api.send_mdm_command_preview(
management_ids=["4eecc1fb-f52d-48c5-9560-c246b23601d3"],
command=LogOutUserCommand()
)
Read the documentation for :ref:`MDM Command Models` to view all the options for the
supported MDM commands . The management IDs can be obtained from computer inventory records
at ``computer.general.managementId``.
This value is only available through the Pro API. See
:class:`~jamf_pro_sdk.models.pro.computers.ComputerGeneral` for more details.
:param management_ids: A list of device management IDs to issue the MDM command to.
:type management_ids: List[Union[str, UUID]],
Expand Down
1 change: 1 addition & 0 deletions src/jamf_pro_sdk/models/pro/computers.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class ComputerGeneral(BaseModel, extra=Extra.allow):
userApprovedMdm: Optional[bool]
declarativeDeviceManagementEnabled: Optional[bool]
extensionAttributes: Optional[List[ComputerExtensionAttribute]]
managementId: Optional[str]


# Computer Disk Encryption Models
Expand Down
109 changes: 109 additions & 0 deletions src/jamf_pro_sdk/models/pro/mdm.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@


class EnableLostModeCommand(BaseModel):
"""MDM command to enable Lost Mode.
.. code-block:: python
command = EnableLostModeCommand()
command.lostModeMessage = "Please return me to my owner."
command.lostModePhone = "123-456-7890"
command.lostModeFootnote = "No reward."
Alternatively, unpack a dictionary:
.. code-block:: python
command = EnableLostModeCommand(
**{
"lostModeMessage": "Please return me to my owner.",
"lostModePhone": "123-456-7890",
"lostModeFootnote": "No reward."
}
)
"""

commandType: Literal["ENABLE_LOST_MODE"] = "ENABLE_LOST_MODE"
lostModeMessage: str
lostModePhone: str
Expand All @@ -27,19 +50,48 @@ class EnableLostModeCommand(BaseModel):


class EraseDeviceCommandObliterationBehavior(str, Enum):
"""Define the fallback behavior for erasing a device."""

Default = "Default"
DoNotObliterate = "DoNotObliterate"
ObliterateWithWarning = "ObliterateWithWarning"
Always = "Always"


class EraseDeviceCommandReturnToService(BaseModel):
"""Configuration settings for Return to Service.
The ``mdmProfileData`` and `w`ifiProfileData`` values must e base64 encoded strings.
"""

enabled: Literal[True]
# TODO: Add automatic conversion to base64 encoded profile if the provided data is a dictionary.
mdmProfileData: str
wifiProfileData: str


class EraseDeviceCommand(BaseModel):
"""MDM command to remotely wipe a device. Optionally, set the ``returnToService`` property to
automatically connect to a wireless network at Setup Assistant.
.. code-block:: python
command = EraseDeviceCommand()
command.pin = "123456"
command.obliterationBehavior = EraseDeviceCommandObliterationBehavior.ObliterateWithWarning
Alternatively, unpack a dictionary:
.. code-block:: python
command = EraseDeviceCommand(
**{
"pin": "Please return me to my owner.",
"obliterationBehavior": "ObliterateWithWarning"
}
)
"""

commandType: Literal["ERASE_DEVICE"] = "ERASE_DEVICE"
preserveDataPlan: Optional[bool]
disallowProximitySetup: Optional[bool]
Expand All @@ -52,13 +104,41 @@ class EraseDeviceCommand(BaseModel):


class LogOutUserCommand(BaseModel):
"""MDM command to log a user out of the device.
.. code-block:: python
command = LogOutUserCommand()
"""

commandType: Literal["LOG_OUT_USER"] = "LOG_OUT_USER"


# Restart Device


class RestartDeviceCommand(BaseModel):
"""MDM command to restart a device.
``kextPaths`` is only used if ``rebuildKernelCache`` is ``true``.
.. code-block:: python
command = RestartDeviceCommand()
command.notifyUser = True
Alternatively, unpack a dictionary:
.. code-block:: python
command = RestartDeviceCommand(
**{
"notifyUser": True
}
)
"""

commandType: Literal["RESTART_DEVICE"] = "RESTART_DEVICE"
rebuildKernelCache: Optional[bool]
kextPaths: Optional[List[str]]
Expand All @@ -69,6 +149,27 @@ class RestartDeviceCommand(BaseModel):


class SetRecoveryLockCommand(BaseModel):
"""MDM command to set Recovery Lock on a device.
Set ``newPassword`` to an empty string to clear the Recovery Lock password.
.. code-block:: python
command = SetRecoveryLockCommand()
command.newPassword = "jamf1234"
Alternatively, unpack a dictionary:
.. code-block:: python
command = SetRecoveryLockCommand(
**{
"newPassword": "jamf1234"
}
)
"""

commandType: Literal["SET_RECOVERY_LOCK"] = "SET_RECOVERY_LOCK"
newPassword: str

Expand All @@ -77,6 +178,14 @@ class SetRecoveryLockCommand(BaseModel):


class ShutDownDeviceCommand(BaseModel):
"""MDM command to shut down a device.
.. code-block:: python
command = ShutDownDeviceCommand()
"""

commandType: Literal["SHUT_DOWN_DEVICE"] = "SHUT_DOWN_DEVICE"


Expand Down

0 comments on commit db8e7ff

Please sign in to comment.