Permission System - Certificate Request & Signing Separation

Overview

The PKI-as-a-Service application implements a granular permission system that enforces separation of duties between certificate requesters and certificate approvers. This prevents users from self-approving their own certificate requests, a critical security requirement for enterprise PKI deployments.

Permission Architecture

Two-Layer Permission Model

The system uses two complementary permission layers:

  1. Spatie Laravel Permission (Global): Application-wide permissions managed through roles
  2. CA Group Permissions (Per-CA): Fine-grained permissions specific to individual Certificate Authorities

Key Principles

  • Separation of Duties: Requesters cannot approve their own certificates
  • Least Privilege: Users receive only the minimum permissions required for their role
  • Audit Trail: All permission changes and usage are logged for compliance

Certificate Permissions (New Model)

request-certificates

Purpose: Submit certificate signing requests (CSR) to a Certificate Authority

Allows: - Submit new certificate requests via web UI or API - Upload CSR files for processing - Request certificates through ACME protocol - View status of own certificate requests

Does NOT Allow: - Approve or sign certificate requests - Issue certificates without approval (unless CA policy allows automatic approval)

Typical Roles: - acme-client (ACME automated requests) - Requesters in approval-based workflows


sign-certificates

Purpose: Validate, approve, and sign certificate requests

Allows: - Review pending certificate requests - Approve or reject certificate requests - Sign CSRs to issue certificates - Configure CA approval policies

Does NOT Allow: - Submit certificate requests (must have request-certificates separately)

Typical Roles: - pki-manager (PKI administrators) - certificate-operator (Certificate validators)


Combined Permissions

Some roles require both permissions to operate normally:

Example: PKI Manager

// Has BOTH permissions
'request-certificates'  // Can submit requests
'sign-certificates'     // Can approve and sign

This enables PKI managers to perform all certificate operations while still maintaining separation when strict approval workflows are required.


Protocol-Specific Permissions (OpenVPN, Windows 802.1x)

create-openvpn-certificates

Purpose: Generate OpenVPN client certificates for a specific Certificate Authority

Allows: - Generate OpenVPN client certificates with .ovpn configuration files - Access OpenVPN template editor for the CA - Download .ovpn profiles for existing certificates - Configure OpenVPN-specific certificate extensions (clientAuth)

Does NOT Allow: - Generate certificates for other CAs without explicit permission - Create OpenVPN server certificates (requires sign-certificates) - Modify CA settings or templates without additional permissions

Security Model: - CA-specific: Permission is granted per Certificate Authority via CA Groups - Defense in depth: Multi-tenant isolation prevents cross-CA access even without permission - Audit trail: All OpenVPN certificate generation is logged with user ID and IP

Typical Use Case: VPN administrators who need to issue client certificates for their organization's VPN infrastructure without full PKI management rights.

Example Configuration:

// CA Group: "Company VPN Team"
// Permission: 'create-openvpn-certificates'
// Members: vpn-admin@company.com

// This user can ONLY generate OpenVPN certificates for THIS CA
// They cannot access other CAs or perform other certificate operations

create-windows-certificates

Purpose: Generate Windows 802.1x EAP-TLS certificates for network authentication

Allows: - Generate EAP-TLS client certificates for Windows workstations - Export certificates in PKCS#12 format with password protection - Generate WiFi XML profiles for automatic deployment - Create mobile configuration profiles for iOS/macOS

Does NOT Allow: - Generate certificates for other CAs without explicit permission - Modify certificate templates or CA settings

Security Model: - CA-specific: Permission is granted per Certificate Authority via CA Groups - Enterprise isolation: Ensures IT teams can only manage their own organization's devices - Compliance: Supports BYOD policies with proper access segregation

Typical Use Case: Enterprise IT administrators managing network authentication certificates for corporate devices.


Multi-Tenant OpenVPN Scenario

Problem: Multiple companies share the PKI infrastructure, each needs isolated VPN certificate management.

Solution: CA Groups with protocol-specific permissions

CA Organization CA Group Permission Users
CA-VPN-A Company A "VPN Team A" create-openvpn-certificates alice@companya.com
CA-VPN-B Company B "VPN Team B" create-openvpn-certificates bob@companyb.com
CA-WEB Shared "Web Admins" request-certificates only charlie@shared.com

Result: - ✅ Alice can generate OpenVPN certificates only for CA-VPN-A - ✅ Bob can generate OpenVPN certificates only for CA-VPN-B - ❌ Charlie cannot generate OpenVPN certificates (wrong permission) - ✅ Complete isolation between organizations (defense in depth)

Code Implementation:

// OpenVpnController::storeClient() - Line 63-71
$user = auth()->user();
$caGroup = $ca->groups()
    ->whereHas('users', fn($q) => $q->where('user_id', $user->id))
    ->first();

if (!$caGroup || !$caGroup->hasPermission('create-openvpn-certificates')) {
    abort(403, 'You do not have permission to create OpenVPN certificates for this CA');
}

Migration from Legacy create-certificates Permission

What Changed?

Before (v0.1): - Single permission: create-certificates - No separation of duties - Users could approve their own certificates

After (v0.2-alpha): - Two permissions: request-certificates + sign-certificates - Enforced separation of duties - Approval workflows properly segregated

Automatic Migration

When upgrading to v0.2-alpha, the migration automatically:

  1. Creates new permissions: request-certificates and sign-certificates
  2. Updates existing roles: Users with create-certificates receive BOTH new permissions
  3. Updates CA Groups: Replaces create-certificates with both new permissions
  4. Preserves access: No users lose access during migration

Migration SQL Logic:

-- Users with create-certificates get BOTH new permissions
UPDATE user_permissions
SET permissions = ['request-certificates', 'sign-certificates']
WHERE permissions CONTAINS 'create-certificates';

Rollback Support

The migration is fully reversible:

# Rollback to legacy permission model
php artisan migrate:rollback

This restores create-certificates and removes the split permissions.


Permission Matrix

Permission Requester Validator VPN Admin PKI Manager Admin ACME Client
request-certificates
sign-certificates
create-openvpn-certificates
create-windows-certificates
view-certificates
revoke-certificates
download-certificates

CA Group Permissions (Per-CA Granularity)

CA Groups allow even finer control by restricting permissions to specific Certificate Authorities.

Available CA Group Permissions

'view-ca' => 'View CA details'
'view-certificates' => 'View certificates from this CA'
'request-certificates' => 'Submit certificate requests (CSR)'
'sign-certificates' => 'Validate and sign certificates'
'create-openvpn-certificates' => 'Generate OpenVPN client certificates'
'create-windows-certificates' => 'Generate Windows 802.1x certificates'
'revoke-certificates' => 'Revoke certificates from this CA'
'download-certificates' => 'Download certificates from this CA'
'view-crl' => 'View and download CRLs from this CA'
'manage-ca-settings' => 'Modify CA settings'

Example: Multi-Tenant Scenario

Company A - Internal CA: - Group: "Company A Requesters" - Permission: request-certificates - Members: Company A employees

  • Group: "Company A Validators"
  • Permission: sign-certificates
  • Members: Company A security team

Company B - External CA: - Group: "Company B Partners" - Permission: request-certificates only - Members: External partners - Approval: Manual approval required


Approval Workflows

Automatic Approval

  • Requires: request-certificates permission
  • CA Policy: approval_mode=automatic
  • Use Case: ACME automated issuance, low-risk certificates

Manual Approval

  • Requester: request-certificates permission
  • Approver: sign-certificates permission
  • CA Policy: approval_mode=manual
  • Use Case: High-security certificates, external partners

Policy-Based Approval

  • Requester: request-certificates permission
  • System: Evaluates CA Access Policies
  • Approver: sign-certificates permission (if required)
  • CA Policy: approval_mode=policy
  • Use Case: Complex rules (IP restrictions, OAuth groups, time-based)

Implementation Details

Permission Checks in Controllers

Certificate Request Submission:

// Check permission before accepting CSR
if (! $user->can('request-certificates')) {
    abort(403, 'You do not have permission to request certificates');
}

Certificate Signing:

// Check permission before signing
if (! $user->can('sign-certificates')) {
    abort(403, 'You do not have permission to sign certificates');
}

CA Group Permission Check:

// Check CA-specific permission
$caGroup = $ca->groups()->whereHas('users', fn($q) => $q->where('user_id', $user->id))->first();

if (! $caGroup || ! $caGroup->hasPermission('sign-certificates')) {
    abort(403, 'You do not have sign permission for this CA');
}

Audit Logging

All permission-related events are logged:

  • Permission grant/revoke
  • Certificate request submissions
  • Certificate approvals/rejections
  • Permission check failures (403 errors)

Example Audit Log:

{
  "event": "certificate.requested",
  "user_id": 42,
  "ca_id": 5,
  "permission_used": "request-certificates",
  "approval_required": true,
  "ip_address": "192.168.1.100",
  "timestamp": "2025-10-15T08:00:00Z"
}

Best Practices

1. Separate Roles for Separation of Duties

Avoid: Giving both request and sign to all users ✅ Recommended: Create separate "Requester" and "Validator" roles

2. Use CA Groups for Multi-Tenant Isolation

Avoid: Global sign-certificates permission for all CAs ✅ Recommended: CA Group permissions per tenant/department

3. Automatic Approval for Low-Risk Scenarios Only

Avoid: Automatic approval for high-security CAs ✅ Recommended: Manual or policy-based approval for sensitive certificates

4. Regular Permission Audits

Recommended: Quarterly review of user permissions ✅ Recommended: Automated alerts for permission changes ✅ Recommended: Compliance reports for separation of duties


Compliance & Standards

This permission model aligns with:

  • SOC 2 Type II: Separation of duties controls
  • ISO 27001: Access control requirements (A.9)
  • NIST 800-53: AC-5 (Separation of Duties)
  • PCI DSS: Requirement 7.1 (Least Privilege)
  • WebTrust for CAs: Baseline Requirements Section 5.2

Troubleshooting

"Permission Denied" When Submitting Certificate Request

Cause: User lacks request-certificates permission

Solution:

# Check user permissions
php artisan permission:show {user_email}

# Grant permission via role
php artisan permission:assign {user_email} request-certificates

"Cannot Approve Own Certificate Request"

Expected Behavior: Separation of duties prevents self-approval

Solution: Assign a different user with sign-certificates to approve

Migration Issues

Problem: Permissions not migrated correctly

Diagnosis:

# Check migration status
php artisan migrate:status

# Verify permissions in database
SELECT * FROM permissions WHERE name IN ('request-certificates', 'sign-certificates');

Fix:

# Re-run migration
php artisan migrate:refresh --path=database/migrations/2025_10_15_074114_split_create_certificates_permission.php


Version History

Version Date Changes
v0.2-alpha 2025-10-15 Introduced request-certificates + sign-certificates split
Added protocol-specific permissions: create-openvpn-certificates, create-windows-certificates
Implemented CA-specific permission enforcement for OpenVPN
v0.1 2025-09-28 Legacy create-certificates permission

Vous n'avez pas envie de la manager ?

Découvrir notre offre PKI As A Service