Snippets
A snippet is the smallest unit of configuration in NetDefense. Each snippet contains a piece of JSON configuration that maps to a specific feature on the firewall device — a rule, an alias, a DNS override, and so on.
Snippets are reusable building blocks: you create them once at the organization level, then compose them into templates. The same snippet can appear in multiple templates, which means a single change to a snippet automatically propagates to every template (and therefore every device) that uses it.
Snippet Types
Section titled “Snippet Types”Each snippet has a type that maps it to a specific area of the underlying OPNsense configuration — firewall rules and aliases, user and group definitions, DNS records, and so on. The set of supported types grows over time as more of OPNsense’s surface area is brought under NetDefense’s control. Run ndcli snippet list to see the types currently in use in your organization, and check the snippet reference for the full set supported by your installed version.
Priority
Section titled “Priority”Each snippet has a priority value between 1 and 60,000 (default: 1,000). Priority controls the order in which snippets appear in the final device configuration — lower numbers are placed first. This matters for firewall rules because OPNsense evaluates them top-to-bottom and, for a rule with quick on (the default), stops at the first match — see Quick rules.
For example, suppose you have a rule that blocks traffic from known bad sources (priority 100) and another that allows general LAN traffic (priority 500). Because the block rule has a lower priority number, it appears higher in the list and is evaluated first — so malicious traffic is dropped before the allow rule ever gets a chance to match it. If the priorities were reversed, the allow rule would match first and let the traffic through.
Priority orders rules inside one of OPNsense’s rule sections. A rule’s interfaces decide its section, and OPNsense evaluates the sections in a fixed order — see Where rules land on the device.
Priority only affects ordering for snippet types where order matters (rules). For types like aliases and users, the priority value is stored but has no effect on behavior.
List Snippets
Section titled “List Snippets”ndcli snippet list╭──────────────────────┬──────────┬───────┬──────────────────╮│ Name │ Priority │ Type │ Updated │├──────────────────────┼──────────┼───────┼──────────────────┤│ drop-invalid-state │ 10 │ RULE │ 2026-02-20 19:18 ││ rate-limit-icmp │ 20 │ RULE │ 2026-02-20 19:18 ││ anti-spoofing │ 30 │ RULE │ 2026-02-20 19:18 ││ block-bogon-ranges │ 1000 │ ALIAS │ 2026-02-20 19:18 ││ log-and-drop-default │ 50 │ RULE │ 2026-02-20 19:18 ││ allow-established │ 100 │ RULE │ 2026-02-20 19:18 ││ trusted-networks │ 1000 │ ALIAS │ 2026-02-20 19:18 ││ dns-servers │ 1000 │ ALIAS │ 2026-02-20 19:18 ││ allow-dns-ntp │ 200 │ RULE │ 2026-02-20 19:18 ││ allow-ldap-internal │ 210 │ RULE │ 2026-02-20 19:18 ││ guest-internet-only │ 300 │ RULE │ 2026-02-20 19:18 ││ block-internal-nets │ 310 │ RULE │ 2026-02-20 19:18 ││ guest-rate-limit │ 320 │ RULE │ 2026-02-20 19:18 ││ geoip-filter │ 500 │ RULE │ 2026-02-20 19:18 ││ port-scan-detect │ 510 │ RULE │ 2026-02-20 19:18 ││ geoip-blocklist │ 1000 │ ALIAS │ 2026-02-20 19:18 ││ log-accepted-traffic │ 900 │ RULE │ 2026-02-20 19:18 ││ log-dropped-traffic │ 910 │ RULE │ 2026-02-20 19:18 │╰──────────────────────┴──────────┴───────┴──────────────────╯Describe a Snippet
Section titled “Describe a Snippet”ndcli snippet describe allow-dns-ntp╭───────────────┬──────────┬──────┬──────────────────╮│ Name │ Priority │ Type │ Updated │├───────────────┼──────────┼──────┼──────────────────┤│ allow-dns-ntp │ 200 │ RULE │ 2026-02-20 19:18 │╰───────────────┴──────────┴──────┴──────────────────╯
Content:{ "action": "pass", "description": "Allow DNS & NTP", "destination_net": "any", "destination_port": "DNS_NTP", "direction": "in", "enabled": "1", "interface": "lan", "ipprotocol": "inet", "log": "1", "protocol": "TCP/UDP", "source_net": "trusted_networks", "uuid": "221f3268-f2a5-49f5-bf6b-f8a6e5d23014"}This snippet was pulled from a device, so its content is what a pull produces: the fields that say what the rule does, plus every other field that differs from OPNsense’s default (here destination_port and log).
Content Format
Section titled “Content Format”Snippet content is JSON that the NetDefense agent turns into OPNsense API calls. Each snippet type maps to a different section of the device configuration. Below are examples for the two most common types.
RULE snippet — defines a firewall filter rule with action, direction, protocol, source/destination matching, and logging:
{ "enabled": true, "action": "pass", "interface": "lan", "direction": "in", "ipprotocol": "inet", "protocol": "TCP/UDP", "source_net": "trusted_networks", "destination_net": "dns_servers", "destination_port": "53", "log": "1", "description": "Allow DNS queries to internal resolvers"}log is one of the fields only agent 1.23.0 or later applies: a device on an older agent that gets this snippet fails its build with SNIPPET_AGENT_TOO_OLD — see Agent and OPNsense versions.
ALIAS snippet — defines a named group of addresses, networks, or ports that rules can reference:
{ "enabled": true, "name": "trusted_networks", "type": "network", "content": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"], "description": "RFC1918 private address ranges"}Notable fields:
- source_net / destination_net — Can reference an alias by name (e.g.,
"trusted_networks") or use literal values ("any","192.168.1.0/24"). The name is resolved on each device, so the same snippet works on every device that has an alias of that name. - name (aliases) — The alias’s name on the device. OPNsense allows letters, digits and underscores, starting with a letter or a single underscore, up to 31 characters, and refuses protocol and service names such as
sshand OPNsense’s reserved keywords such asany,log,grouportable(26.7.4 and later reserve more of them). It can differ from the snippet’s own name, which may also contain hyphens and dots. A name with a hyphen or another character OPNsense doesn’t allow is saved without complaint, and the device refuses it at sync (ALIAS_REJECTED_BY_DEVICE). - content (aliases) — Accepts an array of values or a single newline-separated string.
- addptr (Unbound host overrides) —
"0"stops OPNsense from adding the reverse (PTR) record it creates for a host override by default, and"1"turns it back on. Left out, the device keeps its current setting, and a new override gets the record. Needs agent 1.23.0 or later — see Agent and OPNsense versions. - uuid — The managed identity. Leave it out: it is generated for you, and no snippet type requires it. See The managed uuid.
TRUST_CAandTRUST_CERTgo further and refuse one supplied on create — see Certificates. - password (users) — The account’s plaintext password, never a hash. See USER snippets and passwords.
Each type has a small set of fields it cannot do without — an ALIAS needs a name and a type, for example. Creating a snippet without them is refused, naming the type and the missing field, so you find out while authoring rather than when a device tries to apply it. The full list is in the snippet reference. A RULE needs an action — see RULE and ALIAS fields.
Field values
Section titled “Field values”RULE, ALIAS and UNBOUND_* values are JSON strings in OPNsense’s own form, the form a pulled rule or alias comes back in: write a number as "443", on and off as "1" and "0", and several values as one comma-separated string, "lan,wan". A few fields also take another form: enabled, and a domain forward’s forward_tcp_upstream and forward_first, may be true or false, and an alias’s content and an ACL’s networks may be a list of strings. Any other value is refused when you save the snippet, and the message names the field and the form to write:
RULE snippet content invalid: 'log' must be a string, not a boolean: write "1" or "0"For OPNsense’s default, leave the field out: null is refused too. A snippet saved before this check still applies on agent 1.23.0 or later, which converts numbers and lists itself. A rule or alias takes true or false only in an on/off field such as log, quick or source_not, and is refused at sync with one anywhere else. An UNBOUND_* snippet with true, false or an object in a text field such as ttl fails the whole sync, naming the field. Saving such a snippet again needs strings.
RULE and ALIAS fields
Section titled “RULE and ALIAS fields”A RULE snippet can set any field of an OPNsense firewall rule, and an ALIAS snippet any field of an alias, under the field’s name in OPNsense’s API: log, quick, statetype or gateway on a rule, and proto, updatefreq or interface on an alias, for example. Which fields exist depends on the OPNsense release each device runs. Pulling a rule or alias you set up by hand is the quickest way to see the names and values.
-
Options take OPNsense’s key, not the label its web interface shows:
"ipprotocol": "inet", not"IPv4". A rule’scategoriesandoverloadtable, and an alias’scategories, can also be given by name.""selects no option — on a rule, aninterfaceof""makes a floating rule on every interface — and a value of only blanks or commas, such as",", is refused. -
A managed rule or alias is exactly its snippet. Any field the snippet leaves out is set to OPNsense’s default at every sync that reaches the device: removing
"log": "1"turns logging off, and a change made on the device to a managed rule or alias is undone. -
A rule needs an
action. OPNsense’s default is pass, so saving a rule that leavesactionout, or sets it to"", is refused instead of letting traffic through:content must include a non-empty 'action'. -
uuidandsequencebelong to NetDefense. Theuuidis the object’s identity — see The managed uuid. A rule’ssequencefollows from its template’s position and its priority, so asequencein the content is ignored. So are the fields a pulled snippet carries only for display, such as the keys that start with%. -
A field the device doesn’t have is refused at sync. That rule or alias isn’t written, and the device keeps the one it had; the rest of the configuration still applies, and the task ends
FAILED. The message names the field, suggests the closest field when one is within two edits of it, and gives the device’s OPNsense version:Rule "Allow DNS queries to internal resolvers" (snippet "allow-dns"): field "lgo" (did you mean "log"?) is not in this device's rule model (OPNsense 26.7)
A rule or alias the device already holds exactly as described isn’t written again. ndcli task describe, or the task’s page in the web app, shows a refused rule or alias with one of these codes:
| Code | Meaning | Fix |
|---|---|---|
RULE_FIELD_UNKNOWN, ALIAS_FIELD_UNKNOWN | A field isn’t in the device’s rule or alias model: a typo, or a field the device’s OPNsense release doesn’t have. | Correct the name, or see Agent and OPNsense versions. |
RULE_VALUE_INVALID, ALIAS_VALUE_INVALID | A value has the wrong form or names an option, a category or an overload table the device doesn’t have. For an option, the message lists what the device offers. | Use one of the listed values, or create what’s missing on the device first. |
INTERFACE_NOT_FOUND | The rule’s interface names an interface or interface group the device doesn’t have. The message lists the ones it has. | Use one of those, or keep the snippet off that device. |
RULE_REJECTED_BY_DEVICE, ALIAS_REJECTED_BY_DEVICE | OPNsense refused the write, with a reason per field — a port on a rule whose protocol isn’t TCP or UDP, or an alias in a source, destination or port field that the device doesn’t have, for example. | Fix the field it names, or create the alias on the device first. |
RULE_MODEL_UNAVAILABLE, ALIAS_MODEL_UNAVAILABLE | The agent couldn’t read the device’s rule model (or alias model), so it wrote no rules (or aliases) in that sync. | Sync again. |
Where rules land, and the warnings a sync gives about it, are in Policy Chain.
Agent and OPNsense versions
Section titled “Agent and OPNsense versions”Setting any field, and placing rules as Policy Chain describes, need the NetDefense agent 1.23.0 or later, and are verified on OPNsense 26.7. On OPNsense 26.1 the same field contract applies, and so does the older-agent refusal below. Updating covers upgrading the agent.
-
A device on an older agent fails its build. An older agent applies only some fields of a rule, an alias or a host override and drops the rest, so it would build a different object: a rule that loses its
source_notmatches the source it was meant to exclude. When aRULE,ALIASorUNBOUND_HOST_OVERRIDEsnippet that reaches such a device holds something the agent would drop — a field it ignores, a value it can’t read, or a key that isn’t a field at all — NetDefense doesn’t build that device’s configuration. The device is listed under Errors withSNIPPET_AGENT_TOO_OLD, and no configuration of any kind reaches it until the agent is upgraded or the snippet edited. The message names each snippet and what the agent would miss:Errors:• fw-branch-01: [SNIPPET_AGENT_TOO_OLD] This device's NetDefense agent (1.22.1) applies these snippets only in part; upgrade the agent to 1.23.0 or later, or edit what is listed: allow-https (RULE: fields it ignores: log, source_not; unknown keys: 'lgo' (did you mean 'log'?))Upgrade the agent, or remove what’s listed from the snippet. A field set to OPNsense’s default doesn’t count, so a pulled snippet fails only for the fields its source had changed from the default. A device whose agent version can’t be read is treated as older.
-
OPNsense point releases differ. OPNsense adds fields within a release line: a rule has
received-onfrom 26.7.3 on, but 26.7 doesn’t. A snippet that sets it is refused withRULE_FIELD_UNKNOWNon a device running an earlier 26.7 release, and the message names that device’s OPNsense version. Update those devices, or leave the field out of the snippet. -
The first sync on 1.23.0 can reorder rules even if no template changed. Older agents put PREPEND rules at sequence 100 and up, which on OPNsense 26.7 is after the default LAN allow rules at 1 and 11. The first sync that reaches the device after the upgrade moves them ahead of the device’s own rules in their section, raising those rules’ sequence numbers where needed: each change is a separate configuration revision on the device, and each is listed in the sync result. The same sync resets what was set by hand on managed aliases and rules, as the next item explains, and refuses fields the device’s model doesn’t have.
-
Settings made by hand on a managed alias reset at the first sync from 1.23.0. An older agent applied only an alias’s
enabled,name,type,contentanddescription, so other settings may have been set on the device by hand: a GeoIP alias’s address families (proto), a URL table’s refresh (updatefreq) and authentication,expire,categories. Before you upgrade — for a device installed from the NetDefense repository, before its next OPNsense update, which upgrades the agent too — pull those aliases and copy the fields you need into their snippets, with categories by name and a password in a secret variable. Until the device runs 1.23.0, its build is then refused withSNIPPET_AGENT_TOO_OLD, so nothing is reset in between. Managed rules work the same way: an older agent didn’t apply fields such aslog,quickorgateway, so one set by hand resets unless the snippet carries it. -
A snippet pulled with an older agent holds every field of its source, at the values it had on that device — including ones the older agent then ignored, such as
logor agateway. From agent 1.23.0 they are applied. Check such snippets before you upgrade, and remove what you don’t want; a reference that only the source device has, such as a gateway or a category, is refused on the others.
The managed uuid
Section titled “The managed uuid”ALIAS, RULE, and the UNBOUND_* types (host override, domain forward, host alias, ACL) own their object on the firewall by a uuid. NetDefense generates it when the snippet is created, and an edit that leaves it out keeps it.
- Leave
uuidout when you create one of these snippets. - Drop it when you reuse another snippet’s content.
ndcli snippet describe,ndcli snippet pulland the web app’s editor show theuuid, and two snippets with oneuuidwould be a single object on the firewall. The web app’s Clone drops it for you. - An update may leave
uuidout or send the snippet’s own back. It keeps its identity either way.
NetDefense checks the uuid in three places:
| Check | When | Fix |
|---|---|---|
SNIPPET_UUID_IN_USE (HTTP 409) | A create, or an update that changes the uuid, supplies one that another snippet of the organization already holds. The message names that snippet and says to omit the uuid. | Omit uuid. A create gets a new one; an update keeps its own. |
| HTTP 422, no code | The uuid isn’t a valid NetDefense uuid. The message shows the accepted shape. | Omit uuid. |
SNIPPET_UUID_CONFLICT | At sync, two snippets that reach one device still share a uuid. The device’s build fails, and the message names the uuid, the snippets, and the templates. | Edit each extra snippet and give it a new managed uuid; its templates and priority stay as they are. |
The first two come back when you save a snippet: ndcli prints the first as Error: [SNIPPET_UUID_IN_USE] …, and the web app shows the message of either. SNIPPET_UUID_CONFLICT is a build failure: the device gets no task until it’s fixed. Certificates and CAs have their own uuid rules and codes — see Certificates.
A managed uuid looks like 221f3268-xxxx-4xxx-yxxx-xxxxxxxxxxxx, in lowercase hex with y one of 8, 9, a or b. This makes one:
uuidgen | tr 'A-Z' 'a-z' | sed 's/^........-/221f3268-/'# or, without uuidgenpython3 -c "import uuid; print('221f3268' + str(uuid.uuid4())[8:])"The uuid has to come from a random (version 4) UUID. uuidgen makes one on macOS and Linux; where its default is version 1, as on FreeBSD, use the python3 line.
Then open the snippet with ndcli snippet edit (or in the web app’s editor), replace its uuid with the result, and save. The edited snippet becomes a new object on the firewall, because the uuid is the object’s identity; the one you leave keeps the existing object. Don’t delete the snippet to fix this: deleting it removes it from its templates, and a recreated one starts at the default priority.
USER snippets and passwords
Section titled “USER snippets and passwords”A USER snippet defines a local account on the firewall. Its password is the account’s plaintext password — never a hash. OPNsense hashes whatever password it receives, so a hash pasted into the snippet would be hashed a second time: the account’s password would become the hash text itself, and the password you meant to set would not work.
{ "name": "svc-monitoring", "descr": "Monitoring service account", "password": "${svc_monitoring_password}"}- Keep the password in a secret variable and reference it as
${name}, as above. Create the variable once at the organization scope —ndcli variable org create svc_monitoring_password --secret --value-stdin < ./password.txt, or + Create Variable with Secret turned on in the web app — and the password never sits in the snippet’s content. A literal password also works, but it is then stored and shown exactly as written. - A new account needs a password. Applying a
USERsnippet for an account that doesn’t exist on the device yet fails without one. - Omit
passwordto keep an existing account’s password. When the account is already on the device, a snippet withoutpasswordleaves its current password alone. - A pulled snippet has no password. From ndagent 1.20.1, the PULL workflow doesn’t copy an account’s password off the device; an older agent copies the account’s stored password hash, which you must remove or replace with the plaintext. Add a
passwordbefore you apply the snippet to a device where the account doesn’t exist yet. - A hash is refused. Saving a
USERsnippet whosepasswordhas the shape of a password hash fails, with an error saying'password' must be the plaintext to set, not a hash. A snippet saved before that check existed is refused on the device instead, as below.
From ndagent 1.20.1, a device that receives a password with the shape of a hash leaves that account untouched, applies the rest of the configuration, and fails the task with the code USER_PASSWORD_IS_HASH:
rejected: user snippet "svc-monitoring" (index 2) for user "svc-monitoring" carries a password with the shape of a password hash. OPNsense hashes whatever it is sent, so a hash would become the password itself and lock the intended one out; put the plaintext password in a secret variable (${NAME}) and sync againThe one exception is a hash identical to the one the device already stores for that account: the device then keeps the current password and applies the rest of the snippet. To fix the snippet for every device, replace the hash with the plaintext password, kept in a secret variable as above.
How NDAgent Identifies Managed Configuration
Section titled “How NDAgent Identifies Managed Configuration”A device running OPNsense can have both locally-created configuration (rules added by hand, aliases created in the web UI) and configuration managed by NetDefense. The NetDefense agent needs a reliable way to tell them apart. During a sync, it only creates, updates, or deletes objects it recognizes as its own — everything else is left untouched, with one exception: to keep PREPEND rules ahead of the device’s own firewall rules, a sync may raise those rules’ sequence numbers, keeping their order. See The device’s own rules can be renumbered.
Because the OPNsense API does not provide a single uniform mechanism for tagging managed objects, the agent uses different identification strategies depending on what each part of the API allows:
| Object Type | Identification Method | Marker |
|---|---|---|
| Aliases, Rules, DNS records, certificates and CAs | UUID prefix | UUID starts with 221f3268- |
| Users, Groups | Description tag | Description contains [nd-template:...] |
| WireGuard tunnels | Name prefix | Name starts with nd-vpn__ |
Authentication servers (AUTH_SERVER) | Marker element | A hidden element on the server’s entry, holding the device’s identity |
Login-order policy (AUTH_ORDER), per facility | Marker element | A hidden value recording the device’s identity together with a fingerprint of the value NetDefense wrote |
Authentication servers and the login order have no OPNsense REST API at all, so they can’t carry a UUID prefix or a description tag the way everything else in this table does — see Authentication Servers for how their markers behave on collision and decommission, and for hand-made servers with no marker at all.
Portable Snippets and the PULL Workflow
Section titled “Portable Snippets and the PULL Workflow”Snippet content is designed to be portable — the same JSON can be applied to any device in the organization. References are by name and are resolved on each device: an alias, a gateway or a schedule by its name, and a rule’s categories and overload table by their names too. Interfaces are OPNsense’s interface keys (lan, wan, opt1), so a rule reaches the same network only on devices where the key means the same thing. Traffic shaper pipes and queues (shaper1, shaper2) are referenced by an ID that exists on one device only, so a rule that sets them applies only there.
The OPNsense API JSON format can be nuanced and is not always exhaustively documented. Building snippet content from scratch requires knowledge of the exact field names, value formats, and constraints that the API expects. Rather than guessing at the correct structure, use the PULL workflow to produce a known-good starting point:
-
Configure the rule or alias you want by hand, through the OPNsense web interface. Most people do this on a device kept for testing and validation — one that isn’t synced against a template.
-
Run
ndcli snippet pullto retrieve that configuration as portable JSON. -
Use the result as the content of a new snippet, editing it as needed, and assign it to the templates that should deliver it.
From agent 1.23.0, a pulled RULE or ALIAS comes back ready to use as snippet content: the fields that say what it does and every other field that differs from OPNsense’s default, all as strings, with categories and overload tables given by name and the [nd-template:…] tags NetDefense adds removed from the description. Rules OPNsense generates itself can’t be pulled, and neither can a legacy rule — one OPNsense hasn’t migrated to its current rule format — until you migrate it in OPNsense, under Firewall > Migration assistant (shown while legacy rules exist).
Pull is an authoring aid. It gives you a correct example to base new configuration on — it does not bring the object you pulled from under NetDefense management. The snippet you create is a new managed resource with its own identity, and it keeps no link back to the object it was copied from. That is what makes the content portable: the same snippet can go to every device in the organization, not just the one you authored on.
Pulling from a device you also sync to
Section titled “Pulling from a device you also sync to”If you pull an object from a device and later sync a template containing that snippet back to the same device, you end up with two objects: the original one you created by hand, which NetDefense does not manage, and a new managed one created by the sync. This is expected. The snippet was never attached to the original object, so the sync has nothing to update and creates its own.
For most object types the two simply coexist. For aliases it surfaces as an error, because OPNsense requires alias names to be unique on the device: a managed alias cannot be created while a hand-made one holds the same name. The sync says so directly — that an unmanaged alias of that name already exists on the device, and that you should either delete it there or rename the snippet.
Both of those are real choices. Delete the alias on the device if you want the managed one to take its place; rename the snippet if you want the two to be separate aliases.
If you want the original object to be managed, delete it on the device first, then sync. The sync creates the managed object in its place.
This is another reason the workflow above suggests authoring on a device that no template targets: there is nothing to collide with.
Snippets that grant administrator rights
Section titled “Snippets that grant administrator rights”Some snippet content can give an account on the firewall administrator rights, or let the device run commands. NetDefense treats that content as elevated: it needs Superuser clearance, which only a Superuser’s save gives, on the snippet and on every variable it uses.
What counts as elevated
Section titled “What counts as elevated”A privilege is administrator-equivalent when it gives full administrative control of the firewall, or a short path to it: page-all and the other all-pages privileges, and privileges such as user, group and privilege management, configuration restore, services that run as root, and the authentication setup. A privilege NetDefense doesn’t recognize counts as administrator-equivalent too.
USER— content that grants the account an administrator-equivalent privilege, puts it in a protected group (adminsornetdefense-readonly), gives it the system scope, an interactive shell, or SSH authorized keys. On the device, also aUSERthat joins a group that is administrator-equivalent there — a group created by hand included — or that changes an account that already has administrator rights.GROUP— content that grants its members an administrator-equivalent privilege, or takes its members from a directory (external_members, see Authentication Servers). On the device, also aGROUPthat changes a group that is already administrator-equivalent there. The protected groups themselves can’t be managed by a snippet at all.ZABBIX_USERPARAMETERandZABBIX_SETTINGS— a UserParametercommand, and settings that turn on remote commands (enable_remote_commands) orsudo(sudo_root). When one of these fields takes its value from a variable, the variable needs a Superuser too.- Combinations within one device’s configuration — a
USERwithout Superuser clearance that joins aGROUPwith an administrator-equivalent privilege delivered to the same device, that such a group lists as a member, or that shares its name with a Superuser-savedUSERorGROUP.
AUTH_SERVER and AUTH_ORDER snippets always need a Superuser — see Who can attach an authentication policy. So do TRUST_CA and TRUST_CERT — see Who can change certificates.
Who can save it
Section titled “Who can save it”Only a Superuser signed in interactively — with ndcli auth login or in the web app — gives content Superuser clearance, and only a Superuser can create elevated content, change it, or pull it from a device into a snippet. The exception is what only the device can recognize — a group created by hand there, or an account that’s already an administrator there. The control plane can’t see it, so a Read-Write member can save it; from ndagent 1.20.1 the device refuses it unless a Superuser saved the snippet.
- A Read-Write member gets
Superuser access required for organization '<org>'. - A personal access token never carries Superuser clearance, whatever the role of the account that created it. The same save through
NDCLI_TOKENis refused even for a Superuser — use an interactive session. - Once a snippet holds elevated content — and once a Superuser has saved a
USERorGROUPsnippet, elevated or not — only a Superuser can change its content. Anyone else getsINSUFFICIENT_ROLE:Snippet '<name>' carries Superuser-level content or was last saved by a Superuser; changing it needs org:su(org:suis the Superuser role).
Attaching is a lower bar than authoring. Adding a snippet a Superuser already saved to a template, or that template to an OU, only needs Read-Write — so treat templates that carry elevated snippets as high-impact when you decide who gets Read-Write.
Variables are checked too
Section titled “Variables are checked too”Every variable value records whether a Superuser saved it, separately at each scope. When NetDefense builds a device’s configuration:
- A
USERorGROUPsnippet with elevated content is built only if a Superuser saved the snippet and the value of every variable it uses — the value that wins for that device, so an OU, template, or device override counts as well as the organization default. - A Zabbix snippet is judged by the variables that can decide its command fields: each needs a value a Superuser saved.
- A value can never add elevated content its snippet doesn’t already carry, whoever saved it. A
USERsnippet with"scope": "${account_scope}"builds while the variable holdsuser, and fails withVARIABLE_ELEVATES_SNIPPETonce it’s set tosystem. - Once a Superuser saves a secret variable, every snippet that uses it — of any type — needs Superuser clearance too, or the build fails with
SECRET_VARIABLE_CLEARANCE.
Variables that need a Superuser shows how to re-save a value.
When clearance is missing
Section titled “When clearance is missing”NetDefense refuses to build the configuration. The device gets no task: ndcli sync apply lists it under Errors with the reason, ndcli sync status shows it as ERROR, its drift status turns ERROR, and scheduled syncs skip it until the cause is fixed. The reason names snippets, types, and variables, never a value; the error’s code leads it:
Errors: • fw-branch-01: [SNIPPET_CLEARANCE_INSUFFICIENT] Elevated snippets need Superuser clearance: svc-backup (USER: groups:protected; saved without Superuser clearance)| Code | Message starts with | Fix |
|---|---|---|
SNIPPET_CLEARANCE_INSUFFICIENT | Elevated snippets need Superuser clearance: | A Superuser saves the snippet again. When the reason is uses variables saved without Superuser clearance:, a Superuser saves the variables it names. |
VARIABLE_ELEVATES_SNIPPET | Variable substitution raises snippet clearance: | Change the variable’s value, or have a Superuser write the elevated content into the snippet itself. |
SECRET_VARIABLE_CLEARANCE | Secret variables saved by a Superuser need a snippet with Superuser clearance: | A Superuser saves the snippet, and any other variable it uses, again. |
The words after the snippet’s type say what made it elevated:
| In the message | Meaning |
|---|---|
priv:page-all | Grants page-all or another all-pages privilege |
priv:admin-equivalent | Grants another administrator-equivalent privilege, or one NetDefense doesn’t recognize |
groups:protected | Puts the account in admins or netdefense-readonly |
scope:system | Gives the account the system scope |
shell | Gives the account an interactive shell |
authorizedkeys | Installs SSH authorized keys |
group:external | Takes the group’s members from a directory |
command, enable_remote_commands, sudo_root | A Zabbix command field |
If the reason reads cannot be saved again unchanged (its JSON repeats a key or holds NaN or Infinity): edit it or delete it, a re-save can’t help: fix the content, or delete the snippet.
The device refuses the element. From ndagent 1.20.1, the device runs its own check against what only it can see — its accounts and groups, ones created by hand included. A USER or GROUP without Superuser clearance that would make an account administrator-equivalent, or change one that already is, is refused with the code ADMIN_EQUIVALENT_REQUIRES_SUPERUSER. The rest of the configuration is applied, and the task ends FAILED. ndcli task describe shows the refusal:
rejected (Superuser clearance required): user snippet "svc-backup" (index 4) for user "svc-backup" would add membership in administrator-equivalent group "noc-admins". It carries no Superuser clearance, so a Superuser must save the snippet (and any variable it uses) again; turning on "Allow All Snippet Content" (reject_dangerous_snippets=false) does not lift thisTurning Allow All Snippet Content on doesn’t lift this check. Devices on an older agent don’t run it; the build check above applies to every device. See Device-Side Protection for the device’s side.
Clearance doesn’t override the device’s own policy. Clearance records whether a Superuser saved the content; the device’s Allow All Snippet Content setting says whether it accepts privileged content at all. With that setting off — the default on new installations — the device still refuses a Superuser-saved snippet that, for example, puts a user in admins or installs SSH keys, until the device’s owner turns it on. From ndagent 1.20.1 that policy also refuses a user in a group that is administrator-equivalent on the device, such as one created by hand, and every administrator-equivalent privilege rather than only blanket ones such as page-all, so content like that which applied on an older agent stops applying after the upgrade, whoever saved it.
Giving existing snippets Superuser clearance
Section titled “Giving existing snippets Superuser clearance”Clearance is recorded when a snippet or a variable is saved, so content saved before NetDefense recorded it has none. That means:
- A
USERorGROUPsnippet with elevated content fails its device builds until a Superuser saves it again, together with every variable it uses. - A
USERwithout Superuser clearance that joins, or is listed as a member of, aGROUPwith an administrator-equivalent privilege going to the same device, or that shares its name with a Superuser-savedUSERorGROUP, also fails that device’s build until a Superuser saves it. - A Zabbix snippet whose command fields are written out exactly keeps building, whoever saved it. One whose command field takes its value from a variable fails until a Superuser saves that variable again. One that spells a command field’s name in a different case, such as
Command, fails until a Superuser saves the snippet and its variables again. One whose JSON repeats a key or holdsNaNorInfinitycan’t be saved again unchanged: edit it or delete it. - On devices running ndagent 1.20.1 or later, a
USERorGROUPsnippet the device sees as elevated — one that joins a hand-made administrator-equivalent group, or manages an existing administrator account — is refused there until a Superuser saves it again. - On those devices, while Allow All Snippet Content is off, the stricter local policy also refuses a snippet that puts a user in
admins,netdefense-readonly, or a hand-made administrator-equivalent group, or grants an administrator-equivalent privilege beyond the blanket ones, even after a Superuser saves it, until the device’s owner turns that setting on.
A GROUP that takes its members from a directory, and carries nothing else elevated, keeps working without a re-save, as long as any variable it uses was saved by a Superuser.
To give a snippet Superuser clearance, a Superuser signed in interactively saves it again. The same content is fine:
-
Find what’s affected:
ndcli sync statusshows devices whose build fails asERROR,ndcli sync applynames the snippets and variables, andndcli task describe <task>shows what a device refused. -
Save each snippet again. From the command line, save the content
ndcli snippet describe <name>prints under Content to a file, then:Terminal window ndcli snippet update-content svc-backup ./svc-backup.jsonUse
update-content:ndcli snippet editsends nothing when the content is unchanged. In the web app, Save Changes stays disabled until the text differs from what’s stored, so make a whitespace-only edit — a line break after the closing brace, for example — and then save. -
Save each variable value the error names again — see Variables that need a Superuser.
-
Sync the affected devices.
A USER snippet whose password holds a password hash can’t be saved again as it is — the save is refused. Remove or replace the hash in the same save.
Pulling elevated content
Section titled “Pulling elevated content”ndcli snippet pull with --auto-create or --overwrite saves what it reads as a snippet, so the same rule applies: elevated content needs a Superuser. For a Read-Write member or a token, the pull task fails, nothing is saved, and the message says why:
PULL_SUPERUSER_REQUIRED: Cannot save the pulled ZABBIX_USERPARAMETER as a snippet: it carries Superuser-level content (command). Only a Superuser account can store this; personal access tokens never qualify. Run the pull from a Superuser account, or omit --auto-create/--overwrite to preview it without saving.A pull without --auto-create or --overwrite only previews the content and isn’t affected. The full list of pull refusals is in the snippet reference.