-
Notifications
You must be signed in to change notification settings - Fork 6
DN Rallypoint Group Restrictions
Rallypoints can control which Engage groups may register—and, with extended restrictions, which client certificates may register for a given group. Together, groupRestrictions and extendedGroupRestrictions let operators run a shared Rallypoint without opening every group to every authenticated client.
For general Rallypoint configuration, meshing, and reflection, see Engage Rallypoints. For mutual TLS and certificate stores, see Engage Security and Using ecstool. If you are also using multiple TLS server identities (additionalIdentities and sni) on the same Rallypoint—for example in multi-domain or load-balanced deployments—see Rallypoint Additional Identities and SNI.
Restrictions are evaluated when an Engage Engine (or peer Rallypoint acting on behalf of downstream clients) registers a stream/group on the Rallypoint TLS link—not at TCP connect time.
Typical registration flow:
- Client completes mutual TLS authentication.
- Client sends a group registration for a stream ID (Engage group ID).
- Rallypoint normalizes the group ID to uppercase and checks
maxSecurityLevel. - Rallypoint evaluates basic group policy via
groupRestrictionAccessPolicyTypeandgroupRestrictions. - If configured and supported in your build, Rallypoint evaluates extended rules in
extendedGroupRestrictionsagainst the client's X.509 certificate. - On success, the group is wired into the Rallypoint routing table; on failure, registration is denied and the Engine receives a disconnect reason (for example
NotAllowed,NotOnWhitelist, orOnBlacklist).
Mesh peers exchange basic groupRestrictions during the peer hello handshake. When subscribing to streams across the mesh, each Rallypoint skips groups that are disallowed locally or on the far-end peer, reducing unwanted traffic early.
| Key | Purpose |
|---|---|
groupRestrictionAccessPolicyType |
Default policy: permissive (0) or strict (1) |
groupRestrictions |
Allow/deny group IDs (exact match) |
extendedGroupRestrictions |
Per-group certificate rules (tags, Subject, Issuer, serial, fingerprint) |
All three live in rallypointd_conf.json at the root of the Rallypoint server object.
Group restrictions and additionalIdentities solve different problems and are often deployed together:
| Layer | Configuration | When it applies |
|---|---|---|
| TLS identity |
additionalIdentities + outbound sni
|
TLS handshake—selects which server certificate the Rallypoint presents |
| Group access |
groupRestrictions / extendedGroupRestrictions
|
Stream registration—controls which groups may register and which client certs qualify per group |
A client may connect successfully (correct sni, valid mutual TLS) and still be denied registration on a specific group if group restrictions block it. Conversely, permissive group policy does not bypass TLS—clients must still authenticate.
Multi-domain deployments commonly combine both: additionalIdentities let France and Germany clients trust different server CAs on the same host:port, while groupRestrictions and extendedGroupRestrictions control which talkgroups each certificate may join once connected. See Rallypoint Additional Identities and SNI for server, Engine, and peering examples.
Controls the default before groupRestrictions is applied.
| Value | Name | Behavior |
|---|---|---|
0 |
Permissive (default) | Groups are allowed unless groupRestrictions says otherwise |
1 |
Strict | Groups are denied unless explicitly whitelisted in groupRestrictions
|
{
"groupRestrictionAccessPolicyType": 0,
"groupRestrictions": {
"type": 0,
"elements": []
}
}Any authenticated client may register any group (subject to maxSecurityLevel and extended rules if configured).
{
"groupRestrictionAccessPolicyType": 1,
"groupRestrictions": {
"type": 1,
"elements": [
"{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}",
"{B7694A4F-9724-44A6-AE57-C63232AD1F57}"
]
}
}Only those two group IDs may register. Everything else is denied with reason NotAllowed.
Strict mode note: With
groupRestrictionAccessPolicyType1, a blacklist (type2) ingroupRestrictionsdenies all groups—the strict default wins. Use strict mode with a whitelist.
Basic group ID filtering. Applies to clients and peer Rallypoints.
"groupRestrictions": {
"type": 1,
"elements": [
"{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}",
"OPS-ALPHA-01"
]
}-
type— restriction mode:-
0(rtUndefined) — no basic group list active -
1(rtWhitelist) — only listed group IDs may register -
2(rtBlacklist) — listed group IDs are denied; all others allowed (in permissive mode)
-
-
elements— array of group ID strings (exact match after uppercase normalization) -
elementsType— may appear in sample JSON; ignored by basicgroupRestrictions. Always use literal group IDs here.
At startup the Rallypoint uppercases every entry in groupRestrictions.elements. Incoming registrations also uppercase the stream ID before comparison. These are equivalent:
"{58e3e468-c0e1-4ad8-86d2-9931251e6ea0}"
"{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}"
"ops-alpha-01"Allow only known operational groups; deny everything else:
{
"groupRestrictionAccessPolicyType": 0,
"groupRestrictions": {
"type": 1,
"elements": [
"{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}",
"{B2C3D4E5-F6A7-8901-BCDE-F23456789012}",
"INCIDENT-COMMAND-01"
]
}
}Allow all groups except a deny list:
{
"groupRestrictionAccessPolicyType": 0,
"groupRestrictions": {
"type": 2,
"elements": [
"{DEADBEEF-0000-4000-8000-000000000001}",
"LAB-EXPERIMENTAL-99"
]
}
}Clients may register any group except those two.
If you use staticReflectors, include each reflector's group ID in groupRestrictions (or ensure it is not blacklisted). Example from an internal demo configuration:
{
"groupRestrictions": {
"type": 1,
"elements": [ "DS-DEMO-01" ]
},
"staticReflectors": [
{
"id": "DS-DEMO-01",
"rx": { "address": "172.16.50.10", "port": 13000 },
"tx": { "address": "234.5.6.7", "port": 15000 }
}
]
}Also align multicastRestrictions with reflector multicast address/port pairs—see Engage Rallypoints — Multicast Restrictions.
| Configuration | Result |
|---|---|
type 1 (whitelist) with empty elements
|
Rallypoint aborts at startup (nothing to route) |
type 0 with non-empty elements
|
Rallypoint aborts (list without a type) |
Invalid type value |
Rallypoint aborts |
Fine-grained control per group ID, based on the connecting client's X.509 certificate presented during mutual TLS.
"extendedGroupRestrictions": [
{
"id": "{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}",
"restrictions": [
{
"type": 1,
"elementsType": 2,
"elements": [ "-educators\\b", "-teachers\\b" ]
}
]
}
]-
id— group ID this rule set applies to (case-insensitive match after registration normalization) -
restrictions— array ofStringRestrictionListobjects, each with:-
type—1whitelist or2blacklist -
elementsType— how to interpretelements(see table below) -
elements— strings (literal or PCRE2 regex patterns depending onelementsType)
-
Extended rules only run after the group passes groupRestrictions. In practice:
- Put the group on a permissive whitelist, or
- Use strict mode and include the group in
groupRestrictions.elements, or - Leave basic policy open (permissive +
type0)
Extended restrictions refine who may use an already-permitted group—they do not by themselves add a group to a strict whitelist.
For a registration on group G:
- Find the
extendedGroupRestrictionsentry whoseidmatchesG(case-insensitive). If none, extended checks are skipped. -
Blacklist pass: For each restriction object with
type2, testelementsagainst the client certificate. If any element matches, registration is denied (OnBlacklist). -
Whitelist pass: For each restriction object with
type1, testelements. If at least one whitelist object exists and no whitelist element matched across all whitelist objects, registration is denied (NotOnWhitelist). - Otherwise registration proceeds.
Within a single restriction object, elements are OR'd—matching any one element satisfies that object (for whitelist) or triggers denial (for blacklist).
Across multiple whitelist objects, the implementation treats them as OR as well—matching any whitelist object is sufficient. Use blacklist objects to express exclusions (for example "must have educator tag and must not be in WA/ID").
| Value | Enum | Matches against |
|---|---|---|
0 |
retGroupId |
Not used in extended restrictions (ignored) |
1 |
retGroupIdPattern |
Not used in extended restrictions (ignored) |
2 |
retGenericAccessTagPattern |
RTS access-tag field in certificate Subject (OID 1.3.6.1.4.1.58217.1) |
3 |
retCertificateSerialNumberPattern |
Client certificate serial number |
4 |
retCertificateFingerprintPattern |
Client certificate SHA-256 fingerprint |
5 |
retCertificateSubjectPattern |
Full client certificate Subject DN string |
6 |
retCertificateIssuerPattern |
Client certificate Issuer DN string |
Except for types 0/1 in this context, patterns use PCRE2. In JSON, escape backslashes: write \\b to express \b word boundaries.
Platform note: Extended restriction regex validation and matching require PCRE2. On Windows builds, extended regex features may be unavailable—validate on your target platform before relying on extended rules in production.
Build note: Extended group restriction enforcement is compiled into builds that define
RTS_PRIVATE_CODE. The configuration is always parsed; confirm behavior on your specificrallypointdpackage.
Goal: Group {58E3E468-C0E1-4AD8-86D2-9931251E6EA0} is for educators. Allow certificates tagged as educators/teachers/instructors, but exclude Washington and Idaho subjects.
{
"groupRestrictionAccessPolicyType": 0,
"groupRestrictions": {
"type": 1,
"elements": [
"{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}",
"{B7694A4F-9724-44A6-AE57-C63232AD1F57}"
]
},
"extendedGroupRestrictions": [
{
"id": "{58e3e468-c0e1-4ad8-86d2-9931251e6ea0}",
"restrictions": [
{
"type": 1,
"elementsType": 2,
"elements": [
"-educators\\b",
"-teachers\\b",
"-instructors\\b"
]
},
{
"type": 2,
"elementsType": 5,
"elements": [
"(ST=WA)|(ST=ID)"
]
}
]
}
]
}Certificate access tags are embedded in the client certificate Subject under OID 1.3.6.1.4.1.58217.1. Tags are typically hyphen-prefixed strings such as -educators, -teachers. Your PKI / provisioning process must place them there—see Engage Security for certificate structure background.
Use \\b word boundaries so -educators does not also match -educatorsInPhysics.
Goal: Group {B7694A4F-9724-44A6-AE57-C63232AD1F57} accepts only clients issued by a specific organization CA.
"extendedGroupRestrictions": [
{
"id": "{B7694A4F-9724-44A6-AE57-C63232AD1F57}",
"restrictions": [
{
"type": 1,
"elementsType": 6,
"elements": [
"O=My Fictional Issuing Organization"
]
}
]
}
]elementsType 6 matches against the Issuer DN. Useful when multiple CAs issue client certificates but only one CA is authorized for a sensitive group.
Goal: Restrict OPS-ALPHA-01 to clients whose Subject contains OU=Operations.
"extendedGroupRestrictions": [
{
"id": "OPS-ALPHA-01",
"restrictions": [
{
"type": 1,
"elementsType": 5,
"elements": [
"OU=Operations"
]
}
]
}
]Goal: Allow either operations tag or operations OU for the same group.
"extendedGroupRestrictions": [
{
"id": "OPS-ALPHA-01",
"restrictions": [
{
"type": 1,
"elementsType": 2,
"elements": [ "-operations\\b" ]
},
{
"type": 1,
"elementsType": 5,
"elements": [ "OU=Operations" ]
}
]
}
]Because multiple whitelist objects are OR'd, a client matching either rule is admitted.
Goal: Allow group {C1111111-2222-3333-4444-555555555555} for everyone except two known-compromised devices.
"extendedGroupRestrictions": [
{
"id": "{C1111111-2222-3333-4444-555555555555}",
"restrictions": [
{
"type": 2,
"elementsType": 4,
"elements": [
"AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF",
"11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88"
]
}
]
}
]Fingerprint and serial patterns (types 3/4) are best for break-glass allow/deny lists—not day-to-day role management.
Goal: Only one known serial may register on a maintenance group.
"extendedGroupRestrictions": [
{
"id": "MAINT-HANDSET-ONLY",
"restrictions": [
{
"type": 1,
"elementsType": 3,
"elements": [
"04:A1:B2:C3:D4:E5:F6:07"
]
}
]
}
]Goal: Hospital Rallypoint denies all groups by default; each approved group has its own certificate tag rule.
{
"groupRestrictionAccessPolicyType": 1,
"groupRestrictions": {
"type": 1,
"elements": [
"EMERGENCY-ED",
"SECURITY-DISPATCH",
"FACILITIES-MAINT"
]
},
"extendedGroupRestrictions": [
{
"id": "EMERGENCY-ED",
"restrictions": [
{
"type": 1,
"elementsType": 2,
"elements": [ "-emergency\\b", "-ed-clinical\\b" ]
}
]
},
{
"id": "SECURITY-DISPATCH",
"restrictions": [
{
"type": 1,
"elementsType": 2,
"elements": [ "-security\\b", "-dispatch\\b" ]
}
]
},
{
"id": "FACILITIES-MAINT",
"restrictions": [
{
"type": 1,
"elementsType": 2,
"elements": [ "-facilities\\b", "-maintenance\\b" ]
}
]
}
]
}Combined basic + extended rules, static reflector, and permissive policy—similar to a fully locked-down operational RP:
{
"id": "ops-rp-01",
"listenPort": 7443,
"groupRestrictionAccessPolicyType": 0,
"groupRestrictions": {
"type": 1,
"elements": [
"{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}",
"{B7694A4F-9724-44A6-AE57-C63232AD1F57}"
]
},
"extendedGroupRestrictions": [
{
"id": "{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}",
"restrictions": [
{
"type": 1,
"elementsType": 2,
"elements": [ "-educators\\b", "-teachers\\b", "-instructors\\b" ]
},
{
"type": 2,
"elementsType": 5,
"elements": [ "ST=WA", "ST=ID" ]
}
]
},
{
"id": "{B7694A4F-9724-44A6-AE57-C63232AD1F57}",
"restrictions": [
{
"type": 1,
"elementsType": 6,
"elements": [ "O=My Fictional Issuing Organization" ]
}
]
}
],
"staticReflectors": [
{
"id": "{58E3E468-C0E1-4AD8-86D2-9931251E6EA0}",
"rx": { "address": "234.1.2.3", "port": 25000 },
"tx": { "address": "234.1.2.3", "port": 25000 }
}
]
}When Rallypoints peer, they exchange groupRestrictions in the hello handshake. Each side stores the far-end peer's list and uses it when deciding whether to subscribe to streams toward that peer.
Example: Core RP allows groups A and B; Leaf RP allows only group A. When the core learns of group B from a local client, it will not register for group B toward the leaf—the leaf's exchanged whitelist does not include B.
Configure peer groupRestrictions on each Rallypoint independently. Extended certificate rules are local—they are not exchanged on the peer link; each RP enforces its own extendedGroupRestrictions for registrations arriving on its client and peer connections.
Engage Engine-powered applications do not configure groupRestrictions—that is Rallypoint-side only. When registration is denied, the Engine receives a group disconnect reason. Common values:
| Reason | Typical cause |
|---|---|
NotAllowed |
Failed basic groupRestrictions / strict policy |
NotOnWhitelist |
Failed extended whitelist rule |
OnBlacklist |
Matched extended blacklist rule |
SecurityClassificationLevelTooHigh |
Group security level exceeds maxSecurityLevel
|
Check Rallypoint logs for lines such as:
onRegisterStream will NOT allow {58E3E468-C0E1-4AD8-86D2-9931251E6EA0}
onRegisterStream denying registration of ... - far-end does not meet group restriction requirements (WL)
onRegisterStream denying registration of ... - far-end does not meet group restriction requirements (BL)
-
JSON escaping: PCRE escapes need doubling in JSON—
\\b,\\d+,(ST=WA)|(ST=ID). -
Word boundaries: Prefer
-tagname\\bover bare-tagnamefor access tags. -
Subject DN matching: Type
5searches the full Subject string—patterns likeOU=Operationsmatch anywhere in the DN. Anchor if you need precision:^CN=device01,OU=Operations,O=Example$(adjust for your CA's DN ordering). -
Validate at startup: Invalid regex in
extendedGroupRestrictionscauses the Rallypoint to abort during startup validation. -
Test before production: Use known-good and known-bad certificates; enable debug logging to see
regexContentSearchoutput in debug builds.
| Symptom | Things to check |
|---|---|
| RP aborts at startup | Empty whitelist; list with type 0; invalid regex in extended rules |
| All groups denied |
groupRestrictionAccessPolicyType 1 without whitelist; empty peer whitelist exchanged |
| One group denied for all users | Group missing from groupRestrictions whitelist; extended whitelist too narrow |
| One user denied, others fine | Access tags missing from certificate; Subject/Issuer pattern mismatch; typo in regex |
| Worked on Linux, not Windows | Extended regex (PCRE2) may be unavailable on Windows builds |
| Static reflector silent | Group ID not in groupRestrictions whitelist; multicast also restricted |
| Peer mesh missing audio | Far-end peer's exchanged groupRestrictions excludes the group—check both sides' configs |
-
Rallypoint Additional Identities and SNI —
additionalIdentities,sni, and multi-domain TLS server certificate selection - Engage Rallypoints — full RP schema, meshing, multicast restrictions
- Engage Security — mutual TLS, certificate structure
- Using ecstool — certificate store management and tagging