Skip to content

Commit

Permalink
Better MDM commands schedule
Browse files Browse the repository at this point in the history
 - Always send the DeviceConfigured command
 - Send the base inventory commands (Device, Security info) even if
   there are no blueprints.
 - Send the extra inventory commands (Certs, Profiles, Apps) after the
   device is configured.
  • Loading branch information
np5 committed Aug 10, 2023
1 parent 94e68a5 commit 2dbc767
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 70 deletions.
20 changes: 10 additions & 10 deletions tests/mdm/test_certificate_list_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from zentral.contrib.inventory.models import MetaBusinessUnit, MetaMachine
from zentral.contrib.mdm.artifacts import Target
from zentral.contrib.mdm.commands import CertificateList
from zentral.contrib.mdm.commands.scheduling import _update_inventory
from zentral.contrib.mdm.commands.scheduling import _update_extra_inventory
from zentral.contrib.mdm.models import Blueprint, Channel, Platform, RequestStatus
from .utils import force_dep_enrollment_session

Expand Down Expand Up @@ -167,9 +167,9 @@ def test_process_acknowledged_response_do_not_collect_certificates(self):
ms = m.snapshots[0]
self.assertEqual(ms.certificates.count(), 0)

# _update_inventory
# _update_extra_inventory

def test_update_inventory_do_not_collect_certificates_noop(self):
def test_update_extra_inventory_do_not_collect_certificates_noop(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.assertEqual(self.enrolled_device.blueprint.collect_apps,
Expand All @@ -178,13 +178,13 @@ def test_update_inventory_do_not_collect_certificates_noop(self):
self.assertEqual(self.enrolled_device.blueprint.collect_profiles,
Blueprint.InventoryItemCollectionOption.NO)
self.assertIsNone(self.enrolled_device.certificates_updated_at)
self.assertIsNone(_update_inventory(
self.assertIsNone(_update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
))

def test_update_inventory_managed_certificates_updated_at_none(self):
def test_update_extra_inventory_managed_certificates_updated_at_none(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.assertEqual(self.enrolled_device.blueprint.collect_apps,
Expand All @@ -193,7 +193,7 @@ def test_update_inventory_managed_certificates_updated_at_none(self):
self.assertEqual(self.enrolled_device.blueprint.collect_profiles,
Blueprint.InventoryItemCollectionOption.NO)
self.assertIsNone(self.enrolled_device.certificates_updated_at)
cmd = _update_inventory(
cmd = _update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand All @@ -202,7 +202,7 @@ def test_update_inventory_managed_certificates_updated_at_none(self):
self.assertTrue(cmd.managed_only)
self.assertTrue(cmd.update_inventory)

def test_update_inventory_all_certificates_updated_at_old(self):
def test_update_extra_inventory_all_certificates_updated_at_old(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.enrolled_device.blueprint.collect_apps = Blueprint.InventoryItemCollectionOption.ALL
Expand All @@ -211,7 +211,7 @@ def test_update_inventory_all_certificates_updated_at_old(self):
Blueprint.InventoryItemCollectionOption.NO)
self.enrolled_device.apps_updated_at = datetime.utcnow()
self.enrolled_device.certificates_updated_at = datetime(2000, 1, 1)
cmd = _update_inventory(
cmd = _update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand All @@ -220,7 +220,7 @@ def test_update_inventory_all_certificates_updated_at_old(self):
self.assertFalse(cmd.managed_only)
self.assertTrue(cmd.update_inventory)

def test_update_inventory_all_certificates_noop(self):
def test_update_extra_inventory_all_certificates_noop(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.enrolled_device.blueprint.collect_apps = Blueprint.InventoryItemCollectionOption.ALL
Expand All @@ -229,7 +229,7 @@ def test_update_inventory_all_certificates_noop(self):
Blueprint.InventoryItemCollectionOption.NO)
self.enrolled_device.apps_updated_at = datetime.utcnow()
self.enrolled_device.certificates_updated_at = datetime.utcnow()
self.assertIsNone(_update_inventory(
self.assertIsNone(_update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand Down
43 changes: 35 additions & 8 deletions tests/mdm/test_commands_scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from zentral.contrib.mdm.commands import DeviceInformation
from zentral.contrib.mdm.commands.scheduling import (
_get_next_queued_command,
_update_inventory,
_update_base_inventory,
_update_extra_inventory,
)
from zentral.contrib.mdm.models import (
Blueprint,
Expand Down Expand Up @@ -91,29 +92,48 @@ def test_not_now_device_information_rescheduled(self):

# update inventory

def test_update_inventory_not_now_noop(self):
def test_update_base_inventory_not_now_noop(self):
self.assertIsNone(
_update_inventory(
_update_base_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.NOT_NOW,
)
)

def test_update_inventory_user_channel_noop(self):
def test_update_extra_inventory_not_now_noop(self):
self.assertIsNone(
_update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.NOT_NOW,
)
)

def test_update_base_inventory_user_channel_noop(self):
self.assertIsNotNone(self.enrolled_device.blueprint)
self.assertIsNone(
_update_inventory(
_update_base_inventory(
Target(self.enrolled_device, self.enrolled_user),
self.dep_enrollment_session,
RequestStatus.IDLE,
)
)

def test_update_inventory_no_blueprint_noop(self):
def test_update_extra_inventory_user_channel_noop(self):
self.assertIsNotNone(self.enrolled_device.blueprint)
self.assertIsNone(
_update_extra_inventory(
Target(self.enrolled_device, self.enrolled_user),
self.dep_enrollment_session,
RequestStatus.IDLE,
)
)

def test_update_extra_inventory_no_blueprint_noop(self):
self.enrolled_device.blueprint = None
self.assertIsNone(
_update_inventory(
_update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand All @@ -136,7 +156,14 @@ def test_update_inventory_up_to_date(self):
self.enrolled_device.certificates_updated_at = datetime.utcnow()
self.enrolled_device.profiles_updated_at = datetime.utcnow()
self.assertIsNone(
_update_inventory(
_update_base_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
)
)
self.assertIsNone(
_update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand Down
8 changes: 5 additions & 3 deletions tests/mdm/test_device_configured_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,15 @@ def test_device_configured_already_done(self):
RequestStatus.IDLE,
))

def test_device_configured_notnow_noop(self):
def test_device_configured_notnow_ok(self):
self.enrolled_device.awaiting_configuration = True
self.assertIsNone(_finish_dep_enrollment_configuration(
command = _finish_dep_enrollment_configuration(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.NOT_NOW,
))
)
self.assertIsInstance(command, DeviceConfigured)
self.assertEqual(command.channel, Channel.DEVICE)

def test_device_configured(self):
self.enrolled_device.awaiting_configuration = True
Expand Down
16 changes: 8 additions & 8 deletions tests/mdm/test_device_information_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from zentral.contrib.inventory.models import MetaBusinessUnit, MetaMachine
from zentral.contrib.mdm.artifacts import Target
from zentral.contrib.mdm.commands import DeviceInformation, SecurityInfo
from zentral.contrib.mdm.commands.scheduling import _update_inventory
from zentral.contrib.mdm.commands.scheduling import _update_base_inventory
from zentral.contrib.mdm.models import Blueprint, Channel, Platform, RequestStatus
from .utils import force_dep_enrollment_session

Expand Down Expand Up @@ -211,30 +211,30 @@ def test_process_acknowledged_response_rsr(self):
self.assertEqual(enrolled_device.build_version_extra, "22E772610a")
self.assertEqual(enrolled_device.full_os_version, "13.0 (a) (22E772610a)")

# _update_inventory
# _update_base_inventory

def test_update_inventory_device_information_updated_at_none(self):
def test_update_base_inventory_device_information_updated_at_none(self):
self.assertIsNone(self.enrolled_device.device_information_updated_at)
cmd = _update_inventory(
cmd = _update_base_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
)
self.assertIsInstance(cmd, DeviceInformation)

def test_update_inventory_device_information_updated_at_old(self):
def test_update_base_inventory_device_information_updated_at_old(self):
self.enrolled_device.device_information_updated_at = datetime(2000, 1, 1)
cmd = _update_inventory(
cmd = _update_base_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
)
self.assertIsInstance(cmd, DeviceInformation)

def test_update_inventory_device_information_updated_at_ok(self):
def test_update_base_inventory_device_information_updated_at_ok(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.assertIsNone(self.enrolled_device.security_info_updated_at)
cmd = _update_inventory(
cmd = _update_base_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand Down
20 changes: 10 additions & 10 deletions tests/mdm/test_installed_application_list_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from zentral.contrib.inventory.models import MetaBusinessUnit, MetaMachine
from zentral.contrib.mdm.artifacts import Target
from zentral.contrib.mdm.commands import InstalledApplicationList
from zentral.contrib.mdm.commands.scheduling import _update_inventory
from zentral.contrib.mdm.commands.scheduling import _update_extra_inventory
from zentral.contrib.mdm.models import Blueprint, Channel, Platform, RequestStatus
from .utils import force_dep_enrollment_session

Expand Down Expand Up @@ -131,9 +131,9 @@ def test_process_acknowledged_response_do_not_collect_apps(self):
ms = m.snapshots[0]
self.assertEqual(ms.osx_app_instances.count(), 0)

# _update_inventory
# _update_extra_inventory

def test_update_inventory_do_not_collect_apps_noop(self):
def test_update_extra_inventory_do_not_collect_apps_noop(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.enrolled_device.blueprint.collect_apps = Blueprint.InventoryItemCollectionOption.NO
Expand All @@ -142,13 +142,13 @@ def test_update_inventory_do_not_collect_apps_noop(self):
self.assertEqual(self.enrolled_device.blueprint.collect_profiles,
Blueprint.InventoryItemCollectionOption.NO)
self.assertIsNone(self.enrolled_device.apps_updated_at)
self.assertIsNone(_update_inventory(
self.assertIsNone(_update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
))

def test_update_inventory_managed_apps_updated_at_none(self):
def test_update_extra_inventory_managed_apps_updated_at_none(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.enrolled_device.blueprint.collect_apps = Blueprint.InventoryItemCollectionOption.MANAGED_ONLY
Expand All @@ -157,7 +157,7 @@ def test_update_inventory_managed_apps_updated_at_none(self):
self.assertEqual(self.enrolled_device.blueprint.collect_profiles,
Blueprint.InventoryItemCollectionOption.NO)
self.assertIsNone(self.enrolled_device.apps_updated_at)
cmd = _update_inventory(
cmd = _update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand All @@ -166,7 +166,7 @@ def test_update_inventory_managed_apps_updated_at_none(self):
self.assertTrue(cmd.managed_only)
self.assertTrue(cmd.update_inventory)

def test_update_inventory_all_apps_updated_at_old(self):
def test_update_extra_inventory_all_apps_updated_at_old(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.enrolled_device.blueprint.collect_apps = Blueprint.InventoryItemCollectionOption.ALL
Expand All @@ -175,7 +175,7 @@ def test_update_inventory_all_apps_updated_at_old(self):
self.assertEqual(self.enrolled_device.blueprint.collect_profiles,
Blueprint.InventoryItemCollectionOption.NO)
self.enrolled_device.apps_updated_at = datetime(2000, 1, 1)
cmd = _update_inventory(
cmd = _update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand All @@ -184,7 +184,7 @@ def test_update_inventory_all_apps_updated_at_old(self):
self.assertFalse(cmd.managed_only)
self.assertTrue(cmd.update_inventory)

def test_update_inventory_managed_apps_noop(self):
def test_update_extra_inventory_managed_apps_noop(self):
self.enrolled_device.device_information_updated_at = datetime.utcnow()
self.enrolled_device.security_info_updated_at = datetime.utcnow()
self.enrolled_device.blueprint.collect_apps = Blueprint.InventoryItemCollectionOption.MANAGED_ONLY
Expand All @@ -193,7 +193,7 @@ def test_update_inventory_managed_apps_noop(self):
self.assertEqual(self.enrolled_device.blueprint.collect_profiles,
Blueprint.InventoryItemCollectionOption.NO)
self.enrolled_device.apps_updated_at = datetime.utcnow()
self.assertIsNone(_update_inventory(
self.assertIsNone(_update_extra_inventory(
Target(self.enrolled_device),
self.dep_enrollment_session,
RequestStatus.IDLE,
Expand Down
23 changes: 22 additions & 1 deletion tests/mdm/test_mdm_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,10 +750,13 @@ def test_checkout(self, post_event):

# connect

def test_device_channel_connect_idle_no_command(self, post_event):
def test_device_channel_connect_idle_base_inventory_up_to_date_no_command(self, post_event):
session, udid, serial_number = force_dep_enrollment_session(self.mbu, authenticated=True, completed=True)
now = datetime.utcnow()
enrolled_device = EnrolledDevice.objects.get(udid=udid)
enrolled_device.device_information_updated_at = now
enrolled_device.security_info_updated_at = now
enrolled_device.save()
self.assertIsNone(enrolled_device.last_seen_at)
payload = {"UDID": udid, "Status": "Idle"}
response = self._put(reverse("mdm_public:connect"), payload, session)
Expand All @@ -762,6 +765,21 @@ def test_device_channel_connect_idle_no_command(self, post_event):
enrolled_device.refresh_from_db()
self.assertTrue(enrolled_device.last_seen_at > now)

def test_device_channel_connect_idle_base_inventoryup_to_date_no_command(self, post_event):
session, udid, serial_number = force_dep_enrollment_session(self.mbu, authenticated=True, completed=True)
now = datetime.utcnow()
enrolled_device = EnrolledDevice.objects.get(udid=udid)
self.assertIsNone(enrolled_device.device_information_updated_at)
self.assertIsNone(enrolled_device.security_info_updated_at)
self.assertIsNone(enrolled_device.last_seen_at)
payload = {"UDID": udid, "Status": "Idle"}
response = self._put(reverse("mdm_public:connect"), payload, session)
self.assertEqual(response.status_code, 200)
data = plistlib.loads(response.content)
self.assertEqual(data["Command"]["RequestType"], "DeviceInformation")
enrolled_device.refresh_from_db()
self.assertTrue(enrolled_device.last_seen_at > now)

def test_user_channel_connect_idle_no_command(self, post_event):
session, udid, serial_number = force_dep_enrollment_session(self.mbu, authenticated=True, completed=True)
enrolled_user = force_enrolled_user(session.enrolled_device)
Expand All @@ -778,6 +796,9 @@ def test_user_channel_connect_idle_no_command(self, post_event):
def test_device_channel_connect_idle_device_cert_expiry_reenroll(self, post_event):
session, udid, serial_number = force_dep_enrollment_session(self.mbu, authenticated=True, completed=True)
session.enrolled_device.cert_not_valid_after = datetime.utcnow() + timedelta(days=1)
now = datetime.utcnow()
session.enrolled_device.device_information_updated_at = now
session.enrolled_device.security_info_updated_at = now
session.enrolled_device.save()
payload = {"UDID": udid, "Status": "Idle"}
response = self._put(reverse("mdm_public:connect"), payload, session)
Expand Down
Loading

0 comments on commit 2dbc767

Please sign in to comment.