Skip to content

Security

Comprehensive security guide for Accessibility Project Management.


Overview

Security is paramount in APM, especially when handling sensitive student data and accessibility materials. This guide covers all aspects of securing your APM instance, from authentication and authorization to data protection and audit compliance.


Security Architecture

APM employs a multi-layered security approach:

graph TD
    A[Client] -->|HTTPS| B[Reverse Proxy]
    B -->|HTTP| C[APM Application]
    C --> D[Authentication Layer]
    D --> E[Authorization Layer]
    E --> F[Data Access Layer]
    F --> G[Data Storage: SQLite]
    G --> H[File Storage]

    D --> I[Session Management]
    D --> J[Password Hashing: PBKDF2]
    E --> K[Role-Based Access Control]
    F --> L[Data Encryption: Fernet]
    G --> M[SQLite Encryption]
    H --> N[File System Permissions]

    O[.secrets] --> C
    P[tools.ini] --> C
    Q[Audit Logs] --> F

Authentication

Password Security

APM uses PBKDF2-HMAC-SHA-256 for password hashing with:

  • 260,000 iterations (computationally intensive to prevent brute force)
  • Random 16-byte salt (unique for each password)
  • 32-byte derived key (256 bits of security)
  • Base64 encoding (salt + derived key stored together)

Password Hash Generation

Generate a secure password hash:

python -c "
import hashlib, os, base64
password = b'your_secure_password_here'
salt = os.urandom(16)
dk = hashlib.pbkdf2_hmac('sha256', password, salt, 260000)
print('ACCESSMAN_PASSWORD_HASH=' + base64.b64encode(salt + dk).decode())
"

** Security Note**:

  • Never use simple or dictionary passwords
  • Never reuse passwords across systems
  • Generate a new hash for each deployment
  • Store the .secrets file securely

Legacy SHA-256 Support

For backward compatibility, APM still accepts 64-character hex SHA-256 hashes, but this triggers a deprecation warning. Use PBKDF2 for all new deployments.

Legacy hash generation (not recommended):

python -c "import hashlib; print(hashlib.sha256(b'your_password'.encode()).hexdigest())"

Session Management

APM uses NiceGUI's session system with:

  • STORAGE_SECRET: Encrypts session data (must be strong and unique)
  • Session Timeout: Configurable inactivity timeout (default: 30 minutes)
  • Session Isolation: Each user has isolated session data

Generating STORAGE_SECRET

python -c "import secrets; print('STORAGE_SECRET=' + secrets.token_urlsafe(32))"

Requirements:

  • At least 32 characters
  • Cryptographically random
  • Unique for each deployment
  • Never committed to version control

Login Process

  1. User submits username and password
  2. APM:
  3. Validates input (rejects empty passwords)
  4. Looks up password hash from configuration
  5. Verifies password using PBKDF2 with stored salt
  6. Checks for account lockout
  7. Creates session on success
  8. Session stored in:
  9. Server-side: Encrypted session data
  10. Client-side: Session cookie (HttpOnly, Secure if HTTPS)

Failed Login Handling

  • Max Attempts: Configurable (default: 5)
  • Lockout Duration: Configurable (default: 15 minutes)
  • IP Tracking: Tracks failed attempts by IP
  • Account Lockout: Temporarily disables account after max attempts
  • IP Blocking: Optionally block IPs with too many failed attempts

Two-Factor Authentication (2FA)

APM supports Time-based One-Time Password (TOTP) 2FA:

Enabling 2FA

  1. Navigate to Admin → Settings → Security
  2. Enable Two-Factor Authentication
  3. Configure:
  4. 2FA Method: TOTP (default)
  5. Enforcement: Optional or Required
  6. Issuer: Organization name for authenticator apps
  7. Users must configure 2FA on next login

User 2FA Setup

  1. User logs in with password
  2. If 2FA is enabled and not configured:
  3. User is prompted to set up 2FA
  4. User scans QR code with authenticator app (Google Authenticator, Authy, etc.)
  5. User enters verification code
  6. 2FA is now required for all future logins

Recovery Codes

  • Users receive 10 recovery codes during setup
  • Each code can be used once to bypass 2FA
  • Codes are single-use and not regenerated automatically
  • Admins can generate new recovery codes for users

Secret Management

Environment Variables

APM loads sensitive configuration from .secrets file:

# .secrets - NEVER COMMIT TO VERSION CONTROL

# Authentication
STORAGE_SECRET=your_storage_secret_here
ACCESSMAN_PASSWORD_HASH=your_pbkdf2_password_hash_here
ACCESSMAN_VAULT_KEY=your_fernet_key_here

# API
ACCESSMAN_API_AUTH_REQUIRED=1
ACCESSMAN_API_KEY=your_api_key_here

# Database
ACCESSMAN_DB_PATH=/var/lib/accessibility_mgr/database.db

# Development only (DANGER)
ACCESSMAN_UNPROTECTED=0

** Critical**:

  • .secrets must be in the repository root (not inside accessibility_mgr/)
  • File permissions should be 600 (owner read/write only)
  • Never commit .secrets to version control
  • Exclude from backups if they contain sensitive data

Authorization

Role-Based Access Control (RBAC)

APM uses a flexible RBAC system to control user access.

Default Roles

Role Description Permissions
Administrator Full system access All permissions
Operator Production operations Create/edit jobs, run pipelines, view all data
Reviewer Quality review View jobs, review QA results, approve deliveries

Permission Categories

Category Description Example Permissions
Jobs Job management Create, Read, Update, Delete, Assign
Pipelines Pipeline execution Create, Run, View status, Cancel
QA Quality assurance Run tools, View results, Create profiles
Reports Reporting View, Create, Export
Users User management View, Create, Edit, Deactivate
Settings System configuration View, Edit
API API access Access, Create tokens, Manage keys
Admin Administration Manage roles, View logs, System maintenance

Custom Roles

Create roles tailored to your organization:

  1. Navigate to Admin → Roles & Permissions
  2. Click Create Role
  3. Define permissions for each category
  4. Assign to users as needed

Permission Inheritance

Permissions can be inherited from other roles:

  • Create a base role with common permissions
  • Create specialized roles