A service that automatically synchronizes device information from Kandji to Cloudflare Zero Trust lists, enabling device-based access controls through Cloudflare Gateway and WARP.
flowchart LR
Kandji["Kandji MDM"]
CFSource1["Cloudflare Source List 1"]
CFSource2["Cloudflare Source List 2"]
CFSourceN["Cloudflare Source List N"]
Merge["Device Syncer"]
TargetList["Cloudflare Target<br>Device List"]
Policy["Zero Trust Policy<br/>(Gateway/WARP)"]
Kandji -- Device Data --> Merge
CFSource1 -- Serial Numbers --> Merge
CFSource2 -- Serial Numbers --> Merge
CFSourceN -- Serial Numbers --> Merge
Merge -- Merged & filtered lists --> TargetList
TargetList -- Used by --> Policy
classDef source fill:#e3f2fd,stroke:#2196f3,stroke-width:2px;
classDef process fill:#fffde7,stroke:#fbc02d,stroke-width:2px;
classDef target fill:#e8f5e9,stroke:#43a047,stroke-width:2px;
classDef policy fill:#fce4ec,stroke:#d81b60,stroke-width:2px;
Device serial numbers are synced from Kandji and multiple Cloudflare source lists, merged and filtered, then pushed to the target Cloudflare Device List for Zero Trust policies.
This syncer pulls device serial numbers from your Kandji MDM and maintains them in a Cloudflare list that can be used for Zero Trust policies. This enables you to:
- Automatically whitelist managed devices in Cloudflare Gateway
- Create device-based access policies using WARP
- Maintain an up-to-date inventory of corporate devices for network access control
- Ensure only Kandji-managed devices can access your resources through Cloudflare
- Automated Sync: Continuously synchronizes device data between Kandji and Cloudflare
- Device Filtering: Filter devices by platform, ownership, and custom tags
- Batch Processing: Efficient bulk operations for large device inventories
- Rate Limiting: Respects API rate limits for both Kandji and Cloudflare
- Missing Device Handling: Configurable actions for devices removed from Kandji
- Zero Trust Integration: Direct integration with Cloudflare's Zero Trust platform
- Comprehensive Logging: Structured JSON logging with configurable levels
- Kandji MDM instance with API access
- Cloudflare account with Zero Trust subscription
- Go 1.23+ (for building from source)
git clone <repository-url>
cd kandji-cloudflare-device-syncer
go build -o kandji-cloudflare-syncer .- Copy the example configuration:
cp config.example.yaml config.yaml- Edit
config.yamlwith your settings or use environment variables (recommended):
export KANDJI_API_URL="https://your-tenant.api.kandji.io"
export KANDJI_API_TOKEN="your-kandji-api-token"
export CLOUDFLARE_API_TOKEN="your-cloudflare-api-token"
export CLOUDFLARE_ACCOUNT_ID="your-cloudflare-account-id"
export CLOUDFLARE_LIST_ID="your-cloudflare-list-id"
export LOG_LEVEL="info" # optional, defaults to "info"- Go to Cloudflare Dashboard > My Profile > API Tokens
- Click "Create Token"
- Use "Custom token" template
- Set permissions:
- Account:
Zone:Read,Account:Read - Zone Resources: Include
All zones - Account Resources: Include
All accounts - Specific permissions:
List:Edit
- Account:
- Go to Zero Trust Dashboard > Lists
- Click "Create list"
- Choose SERIAL list type (not "Generic") for device serial numbers
- Name it (e.g., "Kandji Managed Devices")
- Copy the List ID for your configuration
- Go to Zero Trust > Gateway > Firewall policies
- Create new policy
- Set condition: "Device Serial Number is in [Your List Name]"
- Set action: "Allow"
- This will automatically allow devices synced from Kandji
sync_interval: How often to run the sync (e.g.,5m,1h)on_missing: Action for devices in Cloudflare but not in Kandji (ignore,delete,alert)sync_devices_without_owners: Include devices without assigned users
Use these settings to control which Kandji devices are synced:
include_tags/exclude_tags: Only sync devices with specific tags or skip those with excluded tagssync_devices_without_owners: Include devices that have no assigned ownersync_mobile_devices: Sync mobile devices (defaults tofalseto only sync computers)blueprints_include/blueprints_exclude: Filter devices by blueprint IDs or names
Example configuration:
kandji:
include_tags: ["corp-managed"]
exclude_tags: ["do-not-sync"]
sync_devices_without_owners: true
sync_mobile_devices: false
blueprints_include:
blueprint_ids: ["abcd-1234"]
blueprint_names: ["Production"]
blueprints_exclude:
blueprint_ids: []
blueprint_names: ["Test"]rate_limits: Configure API request ratesbatch.size: Number of devices per batch operationsync_interval: How often to run the sync process (e.g., 5m, 1h, 30s)
./kandji-cloudflare-syncer- By default, the app loads
config.yamlfrom the current directory. - You can override config file location with
-configflag.
./kandji-cloudflare-syncer -config custom-config.yaml./kandji-cloudflare-syncer -version- Fetch Devices: Retrieves devices from both Kandji and Cloudflare list
- Apply Filters:
- Removes iPhone/iPad devices
- Applies ownership filters
- Applies tag-based include/exclude filters
- Calculate Differences: Identifies new devices and missing devices
- Sync Changes:
- Adds new devices to Cloudflare list
- Handles missing devices per configuration
- Log Results: Reports sync statistics
Use the synced device list in Cloudflare Gateway policies:
# Example Gateway rule
name: "Allow Managed Devices"
conditions:
- device_serial_number in managed_devices_list
action: allowWhen combined with WARP clients:
- WARP identifies device by serial number
- Gateway checks if serial is in the Kandji-synced list
- Access granted/denied based on management status
debug: Detailed operation logsinfo: General operational informationwarn: Non-fatal issueserror: Error conditions
The log level can be set via the LOG_LEVEL environment variable and defaults to "info".
The syncer logs important metrics each cycle:
- Total devices in Kandji
- Devices after filtering
- New devices added
- Devices removed
- API errors and rate limiting
{
"time": "2025-01-15T10:30:00Z",
"level": "INFO",
"msg": "Sync cycle complete",
"kandji_devices_total": 1250,
"eligible_devices": 1180,
"new_devices_found": 5,
"successfully_added": 5,
"deleted_devices": 2
}Authentication Errors
- Verify API tokens have correct permissions
- Check token expiration dates
- Ensure account/list IDs are correct
Rate Limiting
- Reduce
requests_per_secondvalues - Increase
sync_intervalfor less frequent runs - Monitor API usage in respective dashboards
Missing Devices
- Check device filtering configuration
- Verify devices have serial numbers in Kandji
- Review include/exclude tag filters
Enable debug logging for detailed troubleshooting:
log:
level: "debug"- Use environment variables for tokens
- Restrict token permissions to minimum required
- Rotate tokens regularly
- Monitor token usage
- Set restrictive file permissions:
chmod 600 config.yaml - Store configuration in secure locations
- Avoid committing secrets to version control
- Run syncer in secure environment
- Use TLS for all API communications
- Consider VPN/private network deployment
For small deployments (< 500 devices):
sync_interval: 5m
batch.size: 50
rate_limits.cloudflare_requests_per_second: 4For large deployments (> 2000 devices):
sync_interval: 15m
batch.size: 100
rate_limits.cloudflare_requests_per_second: 2- Kandji: 10 requests/second (default)
- Cloudflare: 4 requests/second (recommended for stability)
- Fork the repository
- Create feature branch
- Make changes with tests
- Submit pull request
See LICENSE for details.
- Check logs for error details
- Review Cloudflare and Kandji API documentation
- Open GitHub issues for bugs or feature requests