Network Access Control
Overview
Section titled “Overview”Arrow implements automated VPN user access control to restrict device access to specific consultants. This ensures that only authorized personnel can connect to sensitive ARROW devices through the VPN, enhancing security and compliance.
The access control system operates at two levels:
- Organization-level defaults - Global setting applied to all devices unless overridden
- Device-level overrides - Per-device settings that take precedence over organization defaults
When consultants are assigned to devices in Arrow, the system automatically synchronizes these permissions to Netbird, creating appropriate groups and access policies.
Access Control Architecture
Section titled “Access Control Architecture”Setting Resolution Flow
Section titled “Setting Resolution Flow”The access control system resolves settings through a hierarchical inheritance model:
graph TD
A[Organization] -->|has setting| B[user_access_control_default]
C[Device Settings] -->|has setting| D[user_access_control]
D -->|values| E{Setting Value}
E -->|enabled| F[Access Control ON]
E -->|disabled| G[Access Control OFF]
E -->|inherit/empty| H[Use Org Default]
F -->|creates| I[NetBird Group]
I -->|members| J[Consultants Field]
J -->|sync via hook| K[device_user_access.go]
B -->|change triggers| L[org_access_control.go]
L -->|syncs all devices| M[Inheriting Devices]
D -->|change triggers| N[device_access_control.go]
N -->|enables/disables| I
DeviceAccessControlManager
Section titled “DeviceAccessControlManager”The DeviceAccessControlManager class (backend/api/netbird/device_groups.go) orchestrates all access control operations between Arrow and Netbird.
classDiagram
class DeviceAccessControlManager {
+IsAccessControlEnabled(deviceID) bool
+GetOrgAccessControlDefault(orgID) bool
+SyncDeviceUserAccess(deviceID, oldConsultants, newConsultants)
+EnableAccessControlForDevice(deviceID)
+DisableAccessControlForDevice(deviceID)
+SyncAllOrgDevices(orgID)
}
class NetBirdClient {
+GetUser(email) User
+UpdateUser(userID, autoGroups)
+CreateGroup(name) Group
+GetGroup(id) Group
+CreatePolicy(request) Policy
+DeletePolicy(id)
}
class PocketBase {
+device_requests
+device_settings
+system_integrations
}
DeviceAccessControlManager --> NetBirdClient : uses
DeviceAccessControlManager --> PocketBase : reads/writes
Key Methods
Section titled “Key Methods”| Method | Description |
|---|---|
IsAccessControlEnabled | Resolves effective access control state by checking device override, then falling back to organization default |
GetOrgAccessControlDefault | Retrieves the organization-level default from system_integrations.user_access_control_default |
SyncDeviceUserAccess | Synchronizes consultant assignments to Netbird groups when the consultants field changes |
EnableAccessControlForDevice | Creates device group, consultant group, and one-way access policy |
DisableAccessControlForDevice | Removes access restrictions, allowing all users to access the device |
SyncAllOrgDevices | Updates all devices inheriting organization default when the default changes |
Group Structure
Section titled “Group Structure”Arrow creates two types of groups for each device with access control enabled:
| Group Type | Naming Pattern | Contents |
|---|---|---|
| Device Group | device-{identifier} | Contains only the device peer |
| Consultant Group | consultants-{identifier} | Contains Netbird users (not peers) assigned to the device |
One-Way Policy Model
Section titled “One-Way Policy Model”Access control policies are configured as one-way (bidirectional=false):
- Consultants can connect TO devices - Allows SSH, VNC, and other management access
- Devices cannot connect back to consultants - Prevents lateral movement from compromised devices
This model ensures that even if a device is compromised, it cannot be used to attack consultant workstations.
Automatic Synchronization
Section titled “Automatic Synchronization”Arrow uses PocketBase hooks to automatically enforce access control when data changes. Three hooks work together to maintain synchronization:
Device User Access Hook
Section titled “Device User Access Hook”File: backend/hooks/device_user_access.go
Trigger: Updates to the consultants field in device_requests collection
Behavior:
- Detects changes to the consultants array
- Checks if access control is enabled for the device
- Calls
SyncDeviceUserAccessto update Netbird user auto_groups - Only syncs if access control is enabled
sequenceDiagram
participant User
participant Arrow
participant Hook
participant Manager
participant Netbird
User->>Arrow: Update consultants on device_request
Arrow->>Hook: Trigger device_user_access hook
Hook->>Manager: Check IsAccessControlEnabled()
Manager-->>Hook: true
Hook->>Manager: SyncDeviceUserAccess(old, new)
Manager->>Manager: EnsureDeviceGroup()
Manager->>Manager: EnsureConsultantGroup()
Manager->>Netbird: Get NetBird user by email
Netbird-->>Manager: User object
Manager->>Netbird: Update user auto_groups
Netbird-->>Manager: Success
Manager->>Manager: EnsureOneWayAccessPolicy()
Manager->>Netbird: Create/Update policy
Netbird-->>Manager: Policy created
Manager-->>Hook: Sync complete
Hook-->>Arrow: Success
Device Access Control Hook
Section titled “Device Access Control Hook”File: backend/hooks/device_access_control.go
Trigger: Updates to the user_access_control field in device_settings collection
Behavior:
- Detects changes to access control setting (enabled/disabled/inherit)
- Resolves effective state based on device setting and organization default
- Calls
EnableAccessControlForDeviceorDisableAccessControlForDeviceas appropriate - Creates or removes groups and policies accordingly
Setting Values:
enabled- Access control is explicitly enabled for this devicedisabled- Access control is explicitly disabled for this deviceinherit- Use organization default setting
Organization Access Control Hook
Section titled “Organization Access Control Hook”File: backend/hooks/org_access_control.go
Trigger: Updates to user_access_control_default field in system_integrations collection (type=“netbird”)
Behavior:
- Detects changes to organization default setting
- Calls
SyncAllOrgDevicesto update all devices - Skips devices with explicit overrides (enabled/disabled)
- Only updates devices set to
inherit
Group and Policy Management
Section titled “Group and Policy Management”EnsureDeviceGroup
Section titled “EnsureDeviceGroup”Creates a device group if it doesn’t exist:
func (m *DeviceAccessControlManager) EnsureDeviceGroup(deviceIdentifier string) (*Group, error)- Group name:
device-{identifier} - Contains: Only the device peer
- Created: When access control is first enabled for a device
EnsureConsultantGroup
Section titled “EnsureConsultantGroup”Creates a consultant group for user assignments:
func (m *DeviceAccessControlManager) EnsureConsultantGroup(deviceIdentifier string) (*Group, error)- Group name:
consultants-{identifier} - Contains: Netbird users assigned to the device
- Updated: When consultants are added/removed from the device
EnsureOneWayAccessPolicy
Section titled “EnsureOneWayAccessPolicy”Creates or updates the access policy:
func (m *DeviceAccessControlManager) EnsureOneWayAccessPolicy(deviceIdentifier string) (*Policy, error)Policy Configuration:
| Property | Value |
|---|---|
| Name | access-{identifier} |
| Source | Consultant group |
| Destination | Device group |
| Bidirectional | false (one-way only) |
| Protocol | All |
| Ports | All |
CleanupDeviceGroup
Section titled “CleanupDeviceGroup”Removes groups and policies when a device is deleted:
func (m *DeviceAccessControlManager) CleanupDeviceGroup(deviceIdentifier string) error- Deletes the device group
- Deletes the consultant group
- Removes the access policy
- Updates user auto_groups to remove references
Configuration
Section titled “Configuration”Organization-Level Setting
Section titled “Organization-Level Setting”Stored in system_integrations collection where type = "netbird":
{ "type": "netbird", "user_access_control_default": true}| Value | Behavior |
|---|---|
true | Access control enabled by default for all devices |
false | Access control disabled by default |
Device-Level Setting
Section titled “Device-Level Setting”Stored in device_settings collection:
{ "device": "device_id", "user_access_control": "enabled", "netbird_group_id": "group-abc123", "netbird_consultant_group_id": "group-def456"}| Setting | Behavior |
|---|---|
enabled | Access control explicitly enabled |
disabled | Access control explicitly disabled |
inherit | Use organization default |
Resolution Logic
Section titled “Resolution Logic”When determining if access control is enabled for a device:
- Check
device_settings.user_access_control - If
enabledordisabled, use that value - If
inherit(or not set), checksystem_integrations.user_access_control_default - Default to
falseif no setting found
Stored Group IDs
Section titled “Stored Group IDs”The device_settings collection stores Netbird group IDs for reference:
| Field | Description |
|---|---|
netbird_group_id | ID of the device group in Netbird |
netbird_consultant_group_id | ID of the consultant group in Netbird |
These IDs are used for efficient lookups and cleanup operations.
Best Practices
Section titled “Best Practices”Enable Access Control at Organization Level
Section titled “Enable Access Control at Organization Level”For security, enable access control at the organization level:
- Navigate to VPN settings in Arrow
- Enable “User Access Control Default”
- All devices will inherit this setting unless explicitly overridden
When to Use Device-Level Overrides
Section titled “When to Use Device-Level Overrides”Use device-level overrides in specific scenarios:
| Scenario | Recommended Setting |
|---|---|
| Shared lab devices | disabled - Allow all consultants |
| Testing/development devices | disabled - Allow team access |
| High-security devices | enabled - Restrict to specific consultants |
| Client-sensitive devices | enabled - Limit access to assigned team |
Consultant Requirements
Section titled “Consultant Requirements”For access control to work correctly:
- Consultants must have Netbird user accounts
- Email addresses must match between Arrow and Netbird
- Users are matched by email during sync operations
Rate Limiting Considerations
Section titled “Rate Limiting Considerations”When making bulk changes (e.g., enabling access control for many devices):
- Certificate generation has a 30-second delay between operations
- This prevents Let’s Encrypt rate limit errors
- Bulk operations may take several minutes to complete
Implementation Reference
Section titled “Implementation Reference”Key Source Files
Section titled “Key Source Files”| File | Purpose |
|---|---|
backend/api/netbird/device_groups.go | DeviceAccessControlManager implementation |
backend/api/netbird/client.go | NetBirdClient API wrapper |
backend/hooks/device_user_access.go | Consultant sync hook |
backend/hooks/device_access_control.go | Device-level toggle hook |
backend/hooks/org_access_control.go | Organization-level toggle hook |
Related Collections
Section titled “Related Collections”| Collection | Relevant Fields |
|---|---|
device_requests | consultants - Array of assigned consultant IDs |
device_settings | user_access_control, netbird_group_id, netbird_consultant_group_id |
system_integrations | type, user_access_control_default, management_url, api_key |
VM-Specific Access Control
Section titled “VM-Specific Access Control”Virtual machines provisioned through ARROW have specialized access control handling:
Automatic Group Creation
Section titled “Automatic Group Creation”When VMs are provisioned with access control enabled:
- Device Group:
device-{vm-identifier}created containing only the VM peer - Consultant Group:
consultants-{vm-identifier}created for assigned users - Access Policy: One-way policy allowing consultants to reach the VM
VM Access Policy Model
Section titled “VM Access Policy Model”VM access policies follow the same one-way model as physical devices:
| Property | Value |
|---|---|
| Source | Consultant group |
| Destination | VM device group |
| Bidirectional | false |
| Protocol | All |
This prevents compromised VMs from being used to attack consultant workstations.
VM Completion Cleanup
Section titled “VM Completion Cleanup”When VMs are completed, access control resources are automatically cleaned up:
flowchart TD
A[VM Completion Triggered] --> B[Get Device Settings]
B --> C[Retrieve NetBird Client]
C --> D[Delete VM Peer]
D --> E[Delete Device Group]
E --> F[Delete Consultant Group]
F --> G[Remove Access Policy]
G --> H[Clear Group IDs from Settings]
H --> I[Cleanup Complete]
Cleanup Operations
Section titled “Cleanup Operations”The completion process removes:
- NetBird Peer: The VM’s VPN peer registration
- Device Group: The
device-{id}group - Consultant Group: The
consultants-{id}group - Access Policy: The
access-{id}policy - User References: Consultant auto_group assignments
Related VM Documentation
Section titled “Related VM Documentation”- ARROW Virtual Machines - VM system overview
- VM Requests - VM request workflow
- VPN Management - VPN configuration and peer management