Skip to content

API Key Lifecycle Management

Overview

API keys authenticate edge collectors to the central server. This document defines the complete lifecycle: generation, provisioning, rotation, revocation, and compromise recovery.

Key Format

alpr_<32-byte-random-base64url>

Example: alpr_7Kx9mPqR2vNwYzA1bCdEfGhIjKlMnOpQ3rStUvWx

Property Value
Prefix alpr_ (identifies key type)
Random portion 32 bytes (256 bits)
Encoding Base64URL (URL-safe)
Total length ~49 characters
Entropy 256 bits (cryptographically secure)

Key Generation

Keys are generated exclusively on the central server using cryptographically secure randomness.

Design Decisions: - 256 bits of entropy (immune to brute force) - Base64URL encoding (URL-safe, no special characters) - alpr_ prefix for identification - SHA-256 hashing for storage (fast lookup, no brute force risk due to high entropy)

Why SHA-256 instead of bcrypt/argon2? - API keys have 256 bits of entropy (not low-entropy passwords) - Need fast validation on every request (~1ms not ~100ms) - No salt needed (key itself is random)

Implementation Details: See API Key PRP for generation functions, hashing patterns, and format validation.

Schema

CREATE TABLE api_keys (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    collector_id UUID NOT NULL REFERENCES collectors(id),
    key_hash CHAR(64) NOT NULL,           -- SHA-256 hash
    key_prefix VARCHAR(10) NOT NULL,       -- First 10 chars for identification
    name VARCHAR(100),                     -- Optional label
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    created_by UUID NOT NULL,
    expires_at TIMESTAMPTZ,                -- NULL = no expiration
    last_used_at TIMESTAMPTZ,
    last_used_ip VARCHAR(45),
    revoked_at TIMESTAMPTZ,
    revoked_by UUID,
    revoke_reason TEXT
);

CREATE INDEX idx_api_keys_hash ON api_keys (key_hash) WHERE is_active = true;
CREATE INDEX idx_api_keys_collector ON api_keys (collector_id);

Key Provisioning

New Collector Registration

  1. Admin creates collector in UI
  2. System generates API key
  3. Key displayed once to admin
  4. Admin securely transfers key to edge collector
  5. Only hash stored in database

Admin UI Flow

[Create Collector] → [Generate Key] → [Display Key Once] → [Confirm Copied]
                              "This key will not be shown again.
                               Copy it now and store securely."

Secure Delivery Options

Method Security Convenience
Manual entry High Low
Encrypted email Medium Medium
Provisioning token High High

For automated edge setup:

CREATE TABLE provisioning_tokens (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    collector_id UUID NOT NULL REFERENCES collectors(id),
    token_hash CHAR(64) NOT NULL,
    expires_at TIMESTAMPTZ NOT NULL,
    used_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    created_by UUID NOT NULL
);

Flow: 1. Admin generates one-time provisioning token (valid 1 hour) 2. Token sent to person setting up edge collector 3. Edge calls POST /api/v1/provision with token 4. Server returns API key (used only once) 5. Edge stores API key locally

POST /api/v1/collectors/provision
{
    "provisioning_token": "prov_xyz..."
}

Response:
{
    "collector_id": "col_abc123",
    "api_key": "alpr_7Kx9mP...",  // Only time key is transmitted
    "central_url": "https://alpr.example.com"
}

Key Storage

Central Server

Data Storage
Full key Never stored
Key hash api_keys.key_hash
Key prefix api_keys.key_prefix (for UI identification)

Edge Collector

Options (in order of preference):

  1. Environment variable

    ALPR_API_KEY=alpr_7Kx9mP...
    

  2. Encrypted config file

    # /etc/alpr/config.yaml (chmod 600)
    api_key: alpr_7Kx9mP...
    

  3. System keyring (if available on Pi)

Never: - Commit to git - Log in plaintext - Transmit unencrypted


Key Validation

Every edge-to-central request requires API key validation via the X-API-Key header.

Validation Checks

  1. Key format is valid (alpr_ prefix, correct length)
  2. Key hash exists in database
  3. Key is active (is_active = true)
  4. Key not expired (expires_at is null or future)
  5. Associated collector is active

Usage Tracking

On successful validation: - last_used_at timestamp updated - last_used_ip address recorded - Enables stale key detection and audit

Revoked Key Detection

Attempts to use revoked keys are logged and can trigger alerts for security monitoring.

Implementation Details: See API Key PRP for validation middleware, FastAPI dependency injection, and revoked key handling.


Key Rotation

When to Rotate

Trigger Action
Scheduled (annual) Proactive rotation
Personnel change Rotate keys they had access to
Suspected compromise Immediate rotation
Edge device replacement New key for new device

Rotation Process

  1. Generate new key for collector
  2. Grace period begins - both old and new keys valid
  3. Update edge collector with new key
  4. Verify new key works - edge sends heartbeat
  5. Deactivate old key after confirmation

Grace Period

Default: 24 hours (configurable)

-- During rotation, collector has two active keys
SELECT * FROM api_keys
WHERE collector_id = 'col_abc123'
  AND is_active = true;

-- Returns both old and new key records

API Endpoints

POST /api/v1/collectors/{id}/rotate-key
{
    "grace_period_hours": 24
}

Response:
{
    "new_key": "alpr_newKey...",
    "old_key_expires_at": "2025-01-16T12:00:00Z",
    "message": "Update edge collector within 24 hours"
}

Edge Update Methods

  1. Manual - Admin updates edge config, restarts service
  2. Command polling - Central sends config_update command via heartbeat
  3. Provisioning endpoint - Edge re-provisions with token

Key Revocation

When to Revoke

  • Suspected key compromise
  • Collector decommissioning
  • Lost/stolen edge device
  • Personnel changes (if key was exposed)

Effects of Revocation

  1. All requests with revoked key return 401 Unauthorized
  2. Edge collector cannot upload events (buffered locally)
  3. Edge collector cannot send heartbeat
  4. Revocation is immediate (no grace period)

Monitoring

Attempts to use revoked keys are: - Logged with full context (key prefix, collector ID, source IP) - Can trigger security alerts - Tracked for incident investigation

Implementation Details: See API Key PRP for revocation functions and monitoring patterns.


Compromise Recovery

Detection Indicators

Indicator Severity
Key used from unexpected IP Medium
Key used from unexpected geography High
Unusual request volume Medium
Requests outside normal hours Low
Multiple collectors using same key Critical

Response Procedure

Immediate (< 15 minutes):

  1. Revoke compromised key
  2. Alert security team
  3. Note timestamp of revocation

Short-term (< 1 hour):

  1. Generate new key for collector
  2. Provision new key to edge (if device not compromised)
  3. Verify new key works

Investigation (< 24 hours):

  1. Identify compromise window (first suspicious activity → revocation)
  2. Audit all requests during window:
    SELECT * FROM request_log
    WHERE api_key_id = 'compromised_key_id'
      AND timestamp BETWEEN 'window_start' AND 'window_end';
    
  3. Check for data exfiltration or manipulation
  4. Review how key was compromised

Documentation:

  1. Create incident report
  2. Update procedures if gap identified
  3. Notify stakeholders if required

Incident Report Template

## API Key Compromise Incident

**Date:** 2025-01-15
**Key ID:** key_xyz (prefix: alpr_7Kx9)
**Collector:** col_abc123 (Main Street Camera)

### Timeline
- HH:MM - First suspicious activity detected
- HH:MM - Key revoked
- HH:MM - New key provisioned
- HH:MM - Normal operations restored

### Impact
- Events during window: X
- Requests from unauthorized IP: Y
- Data integrity: [Verified/Compromised]

### Root Cause
[How was the key compromised?]

### Remediation
[What was done to fix and prevent recurrence?]

Monitoring

Metrics

Metric Description
api_key_requests_total Requests per key
api_key_auth_failures_total Failed auth attempts
api_key_revoked_usage_total Attempts with revoked keys
api_key_last_used_age_seconds Time since key last used

Alerts

Alert Condition Severity
Revoked key usage Any attempt High
Unknown IP for key New IP not in allowlist Medium
Key unused 7+ days Active collector silent Medium
Auth failure spike >10 failures in 5 min High
Key expires soon <7 days until expiration Low

Dashboard Panels

  • Active keys by collector
  • Key age distribution
  • Last used times
  • Failed authentication attempts
  • Revoked key usage attempts

Admin UI Features

Key Management Page

Collector: Main Street Camera (col_abc123)

API Keys:
┌─────────────────┬────────────┬──────────────────┬──────────┐
│ Key Prefix      │ Status     │ Last Used        │ Actions  │
├─────────────────┼────────────┼──────────────────┼──────────┤
│ alpr_7Kx9...    │ Active     │ 2 minutes ago    │ [Revoke] │
│ alpr_mNop...    │ Revoked    │ 3 days ago       │ [View]   │
└─────────────────┴────────────┴──────────────────┴──────────┘

[+ Generate New Key]  [Rotate Key]

Key Generation Modal

┌────────────────────────────────────────────────┐
│ New API Key Generated                          │
├────────────────────────────────────────────────┤
│                                                │
│ alpr_7Kx9mPqR2vNwYzA1bCdEfGhIjKlMnOpQ3rStUvWx │
│                                                │
│ ⚠️  This key will not be shown again.          │
│     Copy it now and store securely.           │
│                                                │
│ [Copy to Clipboard]                            │
│                                                │
│ [ ] I have copied and saved this key          │
│                                                │
│ [Close]                                        │
└────────────────────────────────────────────────┘

Security Checklist

Before deploying:

  • [ ] Keys generated with cryptographically secure random
  • [ ] Keys stored as SHA-256 hash only
  • [ ] Keys never logged in plaintext
  • [ ] Keys transmitted only over TLS
  • [ ] Revocation takes effect immediately
  • [ ] Failed auth attempts are logged
  • [ ] Revoked key usage triggers alert
  • [ ] Key rotation procedure tested
  • [ ] Compromise response procedure documented
  • [ ] Admin UI requires MFA for key operations

Decision Date: 2025-12-29 Status: Approved Rationale: Comprehensive key lifecycle management essential for edge-to-central security