Jamf Compliance Bridge

Complete
Author July 2026

Overview

Identity providers make the access decisions, but Jamf is what knows whether a Mac is healthy. This bridge connects the two. It reads compliant devices out of a Jamf smart group, resolves them to users, and reconciles the membership of a target Okta or Entra ID group so access policies follow live device posture.

Problem

A Conditional Access policy can only gate on what the identity provider knows. Jamf holds the real compliance signal (FileVault state, OS version, last check-in) and that signal stops at the Jamf console. Jamf’s native connectors cover the common cases. They do not help when you need one compliance signal spanning multiple IdPs, gating on custom smart group logic, or running somewhere that is not using the Intune connector.

Approach

A provider-agnostic reconciler that runs in three phases: read the Jamf smart group and map each device to its assigned user’s email from inventory, pull the current membership of the target IdP group, then compute and apply the adds and removes needed to make them match. A mapping file ties Jamf groups to IdP groups, so one Jamf group can drive an Okta group and an Entra group at once.

Architecture

sync.py drives the run against a mapping file. The bridge/ package holds a provider interface with Okta and Entra implementations behind it, so adding another IdP means adding one adapter and leaving the reconciliation logic alone. Reconciliation is idempotent: running twice changes nothing the second time. The tool is dry-run by default and prints the adds and removes it would make until --apply is passed. Credentials load from environment or a gitignored .env; nothing sensitive lives in code.

Outcome

A scheduled, version-controlled compliance gate that works across both major identity providers, with every decision visible in a diff instead of hidden behind a console toggle.

Lessons Learned

Dry-run by default is what makes a group-membership tool safe to hand to someone else. A reconciler that silently removes the wrong users on its first run never gets a second one. Printing the plan first turns an irreversible action into a reviewable one.