👋 Welcome to the runZero Custom Integration library!
runZero is a total attack surface and exposure management platform that combines active scanning, passive discovery, and API integrations to deliver complete visibility into managed and unmanaged assets across IT, OT, IoT, cloud, mobile, and remote environments. runZero can be used as a hosted service (SaaS) or managed on-premise. The runZero stack consists of one more Consoles, linked Explorers that run as light-weight services on network points-of-presence, and a command-line tool that can be used for offline data collection. runZero can be managed through the web interface, via API, or for self-hosted customers, on the command line.
If you are not a runZero user today, sign up for a trial that can be converted to our free Community Edition.
This repository includes custom integrations that run in the context of a runZero Explorer. These integrations are written in Starlark, a language similar to Python.
To create a custom integration within runZero, you will need a user account with superuser privileges.
You can find detailed documentation about Starlark-based integrations on the runZero help portal.
If you need help setting up a custom integration, you can create an issue on this GitHub repo, and our team will work with you. If you have a Customer Success Engineer, you can also work with them directly.
- Akamai Guardicore Centra
- Automox
- Bitsight
- Carbon Black
- Cisco ISE
- Cortex XDR
- Cyberint
- Device42
- Digital Ocean
- Drata
- Extreme Networks CloudIQ
- Ghost Security
- Halcyon
- Ivanti Neurons
- JAMF
- Kandji
- Kubernetes
- LimaCharlie
- Linux via SSH
- ManageEngine Endpoint Central
- Microsoft SQL Server databases
- Mosyle
- Netskope
- Nexthink
- NinjaOne
- pfSense
- Proxmox
- runZero Task Sync
- Scale Computing
- Snipe-IT
- Snow License Manager
- SolarWinds Information Service
- Stairwell
- Tailscale
- Tanium
- Ubiquiti UniFi Network
- Wazuh
- Windows SMB shares
- Windows WMI
- Sample README.md for contributing
- Sample script that shows how to use all of the supported libraries
- Embedded
CONFIGmetadata in each script that gives context on the integration for automations to reference
This repository includes the /create-custom-integration skill. Invoke it with
a vendor documentation link and a short statement of the data to import:
/create-custom-integration https://vendor.example/api/docs -- import managed devices, network interfaces, OS details, and installed software
The workflow blocks implementation until it identifies whether the vendor's foreign ID is stable, unique in a documented scope, and one-to-one with the asset being imported. It does not permit random ID fallbacks that would create duplicate assets on later polls.
Asset reconciliation is configurable per imported record. runZero does not
automatically choose or rewrite a custom integration's identity policy; the
script author selects matchBehavior when the default is not appropriate.
Every ImportAsset you return needs an id value. runZero uses that
foreign id as the primary key when correlating subsequent runs of the
same integration with the asset graph, so the value you choose has a
direct impact on whether records merge cleanly, fork into duplicates,
or collapse two unrelated devices into one.
A good foreign id is:
- Stable across runs. The same physical asset should produce the same id every time the script runs. Tomorrow's poll must agree with today's poll, even across reboots, IP changes, agent reinstalls, hostname renames, etc.
- Unique across the dataset. Two distinct assets must never share
the same id. If the upstream API recycles ids when devices are
decommissioned, namespace them (e.g.
vendor-{tenant}-{id}). - Opaque. Prefer vendor-issued UUIDs, serial numbers, or hardware ids over derived values like hostnames or IPs (those drift).
If the upstream source does not expose anything that meets both
criteria, that is the signal to relax matching (see below) — do
not invent a random id with new_uuid() per run, because the
same device will appear as a new asset on every poll.
ImportAsset accepts an optional matchBehavior string. The default
behavior matches and breaks on all four dimensions (id, MAC, IP, name)
which is correct when the integration owns a strong id. When the id
is weak or absent, use one of the knobs below to tell the cruncher
which dimensions are unreliable for matching (finding the right
existing asset to merge into) and which are unreliable for
breaking (refusing a merge that would otherwise happen because
one dimension conflicts).
Flags:
| Flag | Effect |
|---|---|
no-id-match |
Do not use the foreign id to find candidate assets to merge with. |
no-id-break |
Allow a merge even when the foreign id differs from the existing asset. |
no-mac-match |
Do not use MAC addresses to find merge candidates. |
no-mac-break |
Allow a merge even when MAC addresses conflict. |
no-ip-match |
Do not use IP addresses to find merge candidates. |
no-ip-break |
Allow a merge even when IP addresses conflict. |
no-name-match |
Do not use hostnames to find merge candidates. |
no-name-break |
Allow a merge even when hostnames conflict. |
Combine flags with spaces. Recommended presets:
-
Strong, stable foreign id (most cloud / EDR / MDM APIs): leave
matchBehaviorunset. The default uses every signal. -
Strong id, but the source also reports churny MAC/IP/hostnames (e.g. ephemeral cloud workloads, VPN clients):
matchBehavior="no-mac-break no-ip-break no-name-break"
Keeps id-based merging authoritative, but stops drift in the other dimensions from blocking a legitimate merge.
-
No stable id at all (the source only emits per-run / ephemeral ids):
matchBehavior="no-id-match no-id-break"
Falls back to MAC / IP / name matching. Pair this with
id=new_uuid()orid="vendor-" + hashlib.sha256(stable_attrs)so the row still has a unique key but the cruncher ignores it for correlation. -
Two-stage enrichment where one integration owns "identity" and another only contributes attributes: use
no-id-match no-id-breakon the enrichment-only integration so it always merges into the primary asset by MAC/IP/name rather than creating a parallel record.
A short rule of thumb: if the upstream id is not both stable and
unique, you must relax id matching. If MAC / IP / hostname are
known to be unreliable for this data source, relax the corresponding
-break flags so a conflict on those fields doesn't fragment one
real asset into many.
We welcome contributions to this repository! Whether you're fixing a bug, adding a new feature, or improving documentation, your efforts make a difference. To ensure a smooth process, please follow these guidelines:
-
Fork the Repository: Start by forking this repository to your GitHub account.
-
Create a Branch: Create a feature branch for your changes. Use a descriptive name like
feature/new-integrationorfix/bug-description. -
Make Your Changes: Implement your changes and test thoroughly. Ensure your code adheres to our coding standards and is well-documented.
-
Commit Your Changes: Write clear and concise commit messages that describe what you changed and why.
-
Open a Pull Request (PR):
- Go to the original repository and open a pull request from your fork.
- Provide a detailed description of your changes, including the problem your contribution solves and how it was tested.
-
Code Review: Collaborate with the maintainers during the review process. Be open to feedback and iterate on your changes if necessary.
-
Merge: Once approved, your PR will be merged by a maintainer.
External tools such as Gemini CLI, OpenAI Codex, and Claude Code can help draft integrations. runZero does not run an LLM in the Console, Explorer, or integration sandbox. These tools produce source that must pass the same review and validation as hand-written .star files.
There is an AGENTS.md file to give your LLM of choice best practices and guidance will building the integrations.
Existing v1 integrations remain supported. See the v1 to v2 migration guide when moving metadata into CONFIG, adopting standard helpers, streaming assets, or tuning match behavior.
This repository is licensed under the MIT License. By contributing to this project, you agree that your contributions will be licensed under the same terms.