Skip to main content
The approval workflow enables non-admin users to request network resources while maintaining administrative control over what gets added to the VPN. This ensures security and governance for your network access.

How It Works

The approval workflow creates a multi-stage process for resource provisioning:

User Permissions

NetBird Selfservice distinguishes between two types of users:

Admin Users

  • Create resources immediately
  • No approval required
  • Can approve/deny requests from others
  • Full access to all resources

Non-Admin Users

  • Submit requests for approval
  • Cannot create resources directly
  • Manage only their own resources
  • Track request status

Submitting a Request

When a non-admin user wants to add a network resource, they follow this process:
1

Fill Out Resource Form

Enter the resource details:
  • Name: Descriptive name for the resource
  • Address: IP, CIDR, or domain to access
  • Description: Why you need this resource
  • Enabled: Whether it should be active when approved
2

Submit Request

Click submit to create a pending resource request with status pending.
3

Wait for Admin Review

Your request is now queued for administrative review. The admin team receives an email notification.
4

Receive Decision Notification

You’ll get an email when the admin approves or denies your request.

Request Implementation

When a request is submitted, the RequestResourceAction creates a pending resource:
// From RequestResourceAction.php:26-35
$pendingResource = PendingResource::create([
    'name' => $name,
    'address' => $address,
    'description' => $description,
    'enabled' => $enabled,
    'user_id' => $user->id,
    'requested_by' => $user->name,
    'requested_email' => $user->email,
    'status' => 'pending',
]);
All requests are logged with action type requested in the activity log for complete audit trails.

Admin Notifications

Administrators receive email notifications for new requests via the ResourceApprovalRequest mailable:

Email Contents

The approval request email includes:
  • Resource name and address
  • Requester name and email
  • Resource description (if provided)
  • Direct action links:
    • Approve button (7-day signed URL)
    • Deny button (7-day signed URL)
// From ResourceApprovalRequest.php:25-35
$this->approveUrl = URL::temporarySignedRoute(
    'resources.approve',
    now()->addDays(7),
    ['pendingResource' => $pendingResource->id]
);

$this->denyUrl = URL::temporarySignedRoute(
    'resources.deny',
    now()->addDays(7),
    ['pendingResource' => $pendingResource->id]
);
Signed URLs expire after 7 days for security. If the links expire, admins can still approve/deny from the admin panel.

Admin Email Configuration

The admin email is configured in the environment:
NETBIRD_ADMIN_EMAIL=[email protected]

Approving Requests

When an admin approves a request:
1

Review Request Details

The admin examines the requested resource, including name, address, and justification.
2

Click Approve

Either from the email link or the admin dashboard, the admin clicks approve.
3

Resource Created

The ApproveResourceAction executes:
  • Creates the resource in NetBird
  • Updates pending request status to approved
  • Sets decided_at timestamp
  • Logs the approval action
4

User Notified

The requester receives a ResourceDecisionNotification email confirming approval.

Approval Logic

// From ApproveResourceAction.php:27-46
public function execute(PendingResource $pending, string $groupId, User $admin): array
{
    // Create resource in NetBird
    $result = $this->netbirdService->createResource(
        name: $pending->name,
        address: $pending->address,
        description: $pending->description,
        enabled: $pending->enabled,
        groups: [$groupId]
    );

    // Save resource record
    Resource::create([
        'netbird_id' => $result['id'],
        'user_id' => $pending->user_id,
        'created_by' => $pending->requested_by,
    ]);

    // Update pending request
    $pending->update([
        'status' => 'approved',
        'decided_at' => now(),
    ]);
}

Denying Requests

When an admin denies a request:
1

Review Request

The admin determines the request should not be approved (security concerns, policy violations, etc.).
2

Click Deny

From the email or admin dashboard, the admin denies the request.
3

Request Updated

The DenyResourceAction executes:
  • Updates status to denied
  • Sets decided_at timestamp
  • Logs the denial action
  • Does NOT create a resource
4

User Notified

The requester receives an email indicating their request was denied.

Denial Logic

// From DenyResourceAction.php:19-32
public function execute(PendingResource $pending, User $admin): void
{
    $pending->update([
        'status' => 'denied',
        'decided_at' => now(),
    ]);

    ResourceLog::logAction(
        action: ResourceAction::Denied->value,
        resourceName: $pending->name,
        resourceAddress: $pending->address,
        performedBy: $admin->name,
        changes: $pending->toLogChanges()
    );
}

Email Notifications

ResourceApprovalRequest

Sent to admins when a new request is submitted:
  • Subject: “New Resource for Approval: [Resource Name]”
  • Template: emails.resource-approval-request
  • Includes: Approve/Deny action buttons

ResourceDecisionNotification

Sent to requesters when their request is decided:
  • Subject:
    • “Resource approved: [Resource Name]”
    • “Resource rejected: [Resource Name]”
  • Template: emails.resource-decision-notification
  • Includes: Decision outcome and next steps
// From ResourceDecisionNotification.php:24-29
$status = $this->approved ? 'approved' : 'rejected';

return new Envelope(
    subject: "Resource {$status}: {$this->pendingResource->name}",
);

Status Tracking

Pending resources have the following possible statuses:
StatusDescriptionCan Transition To
pendingAwaiting admin reviewapproved, denied
approvedRequest approved, resource created(terminal state)
deniedRequest rejected(terminal state)

Checking Status

The PendingResource model provides a helper method:
// From PendingResource.php:41-44
public function isPending(): bool
{
    return $this->status === 'pending';
}

Canceling Requests

Users can cancel their own pending requests before an admin makes a decision:
// From CancelResourceRequestAction.php:17-27
public function execute(PendingResource $pending, User $user): void
{
    ResourceLog::logAction(
        action: ResourceAction::Cancelled->value,
        resourceName: $pending->name,
        resourceAddress: $pending->address,
        performedBy: $user->name,
        changes: $pending->toLogChanges()
    );

    $pending->delete();
}
Once a request is approved or denied, it cannot be canceled. Only pending requests can be canceled.

Activity Logging

All approval workflow actions are logged for audit purposes:
ActionWhen LoggedPerformed By
requestedUser submits requestRequester
approvedAdmin approves requestAdmin
deniedAdmin denies requestAdmin
cancelledUser cancels requestRequester
See the Activity Logging page for more details on viewing and using these logs.

Best Practices

Provide Context

When requesting resources, include a detailed description explaining why you need access

Review Promptly

Admins should review requests promptly to avoid blocking user productivity

Set Clear Policies

Establish guidelines for what types of resources are auto-approved vs require review

Monitor Trends

Track request patterns to identify common needs and optimize your approval process

Ownership After Approval

When a request is approved:
  • The resource is assigned to the original requester (user_id from pending resource)
  • The created_by field records the requester’s name
  • The resource appears in the requester’s resource list
  • The requester can manage (update, disable, delete) their resource
This ensures that users maintain ownership of resources they requested, even though an admin performed the approval.

Build docs developers (and LLMs) love