Skip to content

Authorize with Nautobot policies

Standalone, l2trace decides 802.1X access from its own MAC-authority view plus the operator approvals in its local store (see Stand up 802.1X in monitor mode). Integrated mode hands the authorization policy to Nautobot: which identity is allowed, onto which VLAN, with which complete RADIUS response (Filter-Id, downloadable ACL, Session-Timeout, SGT, verbatim AV-pairs). Reach for it when:

  • policy is authored and reviewed by a network team in Nautobot, not per-device in l2trace, and you want one source of truth for intent;
  • a device’s authorization depends on identity (a user credential, or a device MAC), a category (printer vs workstation vs medical-device), a time-of-day window, or a required auth method, not just its MAC;
  • you want the full RADIUS profile, not only a VLAN.

It stays optional and off by default. With the engine off, l2trace does 802.1X exactly as before.

On every authentication, with the engine on, l2trace:

  1. Evaluates Nautobot’s ordered policy locally. A periodic sync pulls the active policy set into l2trace; the auth decision reads that local cache, never a live Nautobot call, so a switch never waits on Nautobot. Policies are first-match by ascending weight; a policy matches when every condition it sets matches the request (a condition it leaves blank is “don’t care”).
  2. Renders the matched profile. A permit becomes an Access-Accept carrying the profile’s full attribute set. A policy’s downgrade gate (required_auth_method) or an explicit reject-decision profile becomes an Access-Reject under enforcement.
  3. Falls back when no policy matches. l2trace uses its existing local decision (MAC Authentication Bypass + operator approvals). No match is never a denial.
  4. Applies monitor-first LAST. In monitor mode the reply is always Access-Accept with no attributes; l2trace only records the profile it would have assigned. A policy can never change the network in monitor mode.

That ordering is deliberate: the network-changing decision is computed, then the monitor-first gate nulls it, so no policy path can route around the safety check.

  • Standalone 802.1X working first (monitor-mode how-to). Prove the pipeline before adding Nautobot.
  • The l2trace SSoT app deployed on your Nautobot, exposing the authorization models (AuthorizationProfile, AuthorizationPolicy, TimeSchedule, DeviceCategory) under /api/plugins/ssot-l2trace/. l2trace reads these; it never writes them.

l2trace reuses the same Nautobot connection as the rest of its Nautobot integration:

Env varMeaning
NAUTOBOT_URLBase URL of your Nautobot (e.g. https://nautobot.example.net)
NAUTOBOT_TOKENAn API token with read access to the SSoT plugin endpoints
NAUTOBOT_VERIFY_TLStrue in production

The token is read-only intent-consumption; l2trace has no write scope on these models.

Env varDefaultMeaning
RADIUS_POLICY_ENGINE_ENABLEDfalseMaster switch for integrated mode
RADIUS_POLICY_REFRESH_SECONDS300How often the local policy cache is refreshed from Nautobot

Set RADIUS_POLICY_ENGINE_ENABLED=true and restart the RADIUS service. On start it does one initial load, then refreshes on the interval. Until the first load succeeds the engine is inert and l2trace uses its local decision, so a slow or unreachable Nautobot at boot never blocks authentication.

Each request is turned into a runtime context and matched against the policy conditions:

Context factSource
usernamethe EAP/MAB identity
macthe supplicant MAC (Calling-Station-Id)
auth_methodmab on the MAB path, peap on the PEAP path
machine_authbest-effort from the inner identity (an AD computer account)
device_categorythe endpoint’s Nautobot role, folded to a canonical slug
time-of-dayevaluated against a policy’s TimeSchedule in that schedule’s timezone

required_auth_method is a downgrade gate: on a matched policy, if the presented method is not the required one, l2trace denies (under enforcement) regardless of any permit, which stops a device that must do 802.1X from slipping in via MAB.

Five of those conditions have an opt-in regex twin, for when an exact value won’t do — an OUI prefix, a naming convention, a family of identity groups:

Equality conditionRegex twin
usernameusername_regex
mac_addressmac_regex
identity_groupidentity_group_regex
device_categorydevice_category_regex
auth_methodauth_method_regex

Each is left unset by default (unset = “don’t care”), so adding the fields is fully back-compatible — a policy that sets none behaves exactly as before. A few things about how they match:

  • Full-match, not search. ^b8:57:d6:.* matches a MAC in that OUI; a bare b8:57:d6 matches nothing, because the whole value must match. Anchor with .* deliberately.
  • Case-sensitive by default. The equality path folds case; the regex path does not. Write (?i) at the front of the pattern when you want case-insensitivity.
  • mac_regex sees the canonical MAC. Both sides are normalized to lowercase colon form first, so you write the pattern against b8:57:d6:... regardless of how the switch put the MAC on the wire.
  • It’s an AND, like every other condition. A _regex twin is an independent condition, not an alternative to its equality sibling — set both and both must pass. Express OR by authoring two policies.

The patterns are compiled with RE2 (google-re2), the same engine the TACACS+ command sets use, for the same reason: RE2 matches in guaranteed linear time, so an operator’s pattern can never catastrophically backtrack and stall the 802.1X auth loop. A pattern RE2 won’t accept — it rejects backreferences and lookaround — is treated as un-evaluatable, i.e. a non-match, and logged. That fails in the safe direction: a broken pattern under-permits (the policy simply doesn’t match, and evaluation falls through to the next policy or the local store), it never silently permits.

4. Keep monitor mode on while you validate

Section titled “4. Keep monitor mode on while you validate”

The engine respects the exact same safety model as the rest of 802.1X. Leave RADIUS_MONITOR_MODE=true while you watch what the policies would do:

Terminal window
curl -s "https://l2trace.example.net/api/auth-events" | jq '.[]
| {mac, result, monitor_mode, discrepancy, reason}'

In monitor mode every reason reads like monitor mode; would <apply profile X> (no change). Nothing on the wire changes. This is your before-you-enforce worklist: the devices whose Nautobot policy disagrees with where they are today.

Enforcement is unchanged and still takes all three independent switches: RADIUS_MONITOR_MODE=false and RADIUS_ENFORCEMENT_PERMITTED=true and the individual switch’s device_collector.extras.radius_enforce=true. Only then does a matched permit assign its VLAN/profile and a gate-deny become a real Access-Reject. Prove it on lab switches first.

The fail-safes (why turning this on is low-risk)

Section titled “The fail-safes (why turning this on is low-risk)”
  • Nautobot outage: the policy cache serves the last good set indefinitely; a failed refresh keeps the prior beliefs and never reads as “deny everyone.”
  • No matching policy: falls back to the local MAB/approval decision, never a denial.
  • Any error in the policy path (a DB blip, an unresolvable endpoint): fails open to Access-Accept with no change, and never drops the reply.
  • Engine off: byte-for-byte the standalone behavior.

The deeper “what happens when Nautobot is down” reasoning, and the posture-required exception, live in 802.1X with Nautobot, and what happens when Nautobot is down.