NIST SP 800-53 Architecture Mapping

On this page

This page maps NIST SP 800-53 Rev. 5 security controls to CRAIG’s concrete implementation. Each control is linked to the specific code, configuration, or infrastructure component that satisfies the requirement. This mapping supports the Authority to Operate (ATO) process for deploying agencies.

CRAIG tracks NIST control implementation status programmatically via the nist_controls table on craig-security. Use GET /v1/security/nist to query current control status, or the CLI: craig security nist list.

Access Control (AC)

Control Requirement CRAIG Implementation

AC-2

Account Management

Keycloak OIDC manages the full account lifecycle (creation, modification, disabling, removal). Nine RBAC roles defined (the realm also carries the service:* service-identity roles): the six operational roles (admin, supervisor, caseworker, eligibility_worker, icpc_coordinator, readonly) plus the three ADR-054 office-authority roles (county_director, regional_director, state_office). Account provisioning and de-provisioning are performed in the Keycloak admin console. JWT claims carry role assignments to every API request.

AC-3

Access Enforcement

Every protected API handler extracts claims via the Extension<Claims> Axum middleware and routes its access decision through the data-driven authz engine (authz.check for single rows, authz.auto_scope_list for lists) evaluating the per-resource {jurisdiction}-authz-{resource} JDM policies — roles are inputs to decision tables rather than hardcoded checks (ADR-023/ADR-024; the single recorded exception is the scope-gated JWS replay-check dedup endpoint, #489). The BFF (craig-web) validates the session token on every request before proxying to backend services. Unauthorized requests receive RFC 9457 Problem Details responses.

AC-6

Least Privilege

Nine granular roles enforce least privilege through the jurisdiction-swappable authz rulesets. Caseworkers cannot access admin functions (user management, archive, NIST controls). The readonly role provides auditors with read-only access to all data without modification capability. Public intake endpoints require no authentication (appropriate for anonymous child abuse reporting). Partner API keys grant access only to intake submission endpoints.

AC-7

Unsuccessful Logon Attempts

Keycloak enforces account lockout policies: configurable failed attempt threshold, lockout duration, and permanent lockout after repeated failures. Lockout events are logged in the Keycloak event log. CRAIG’s audit subscriber captures authentication failure events published by the Keycloak integration.

Audit and Accountability (AU)

Control Requirement CRAIG Implementation

AU-2

Event Logging

A wildcard RabbitMQ subscriber on craig-security captures all 23+ event types published across all services. Events are recorded in the audit_log table with: timestamp, user ID (claims.sub), service name, action, resource type, resource ID, and success/failure status. Every CREATE, UPDATE, and DELETE operation publishes an event.

AU-6

Audit Review, Analysis, and Reporting

GET /v1/security/audit provides paginated, filterable, searchable access to the audit log. Biennial security reviews are managed via security_reviews table with a scheduled/completed workflow. The CLI (craig security audit list) and web UI provide multiple access paths for audit review. Breach detection is implemented as the detection_rules + security_alerts tables plus eight admin endpoints; six default rules ship seeded (failed auth, bulk access, after-hours access, privilege escalation, data export, account lockout), with webhook notification on critical alerts.

Configuration Management (CM)

Control Requirement CRAIG Implementation

CM-2

Baseline Configuration

All service containers are built from rust:1.94-alpine using multi-stage Docker builds. Cargo.lock pins every dependency to an exact version. Infrastructure is defined as code via docker-compose.yml (devstack) and Dockerfiles (production). Container images are immutable — configuration is injected via environment variables, never baked in.

CM-6

Configuration Settings

All configuration uses the CRAIG_<SERVICE>* environment variable namespace (loaded by the config crate). configuration-reference.adoc documents every setting with defaults. Security-critical settings include: CRAIG_WEBSESSION_SECRET (AES-GCM master key, ≥64 bytes, enforced at startup per ADR-013), SESSION_SECURE (cookie Secure flag), CORS_ORIGINS (comma-separated allowed origins), CRAIG_INTAKEPUBLIC_RATE_LIMIT (per-hour rate limit), CRAIG_INTAKECAPTCHA_SECRET (Cloudflare Turnstile secret; literal disabled only for internal/dev). No configuration file parsing — environment variables only, preventing file injection attacks.

Identification and Authentication (IA)

Control Requirement CRAIG Implementation

IA-2

Identification and Authentication (Organizational Users)

Keycloak provides OIDC authentication. The web UI uses Authorization Code flow with PKCE (no client secret exposed to the browser). The CLI and integration tests use Resource Owner Password Credentials (ROPC) grant. All tokens are JWT with RS256 signing. JWKS endpoint is used for key retrieval with rotation support. Token expiry is enforced on every request.

IA-5

Authenticator Management

Keycloak manages all password policies: minimum length, complexity requirements, password history, expiration. No passwords are stored in CRAIG’s databases. API keys for partner intake integration are hashed with SHA-256 before storage — only the hash is persisted; the plaintext key is returned exactly once at creation time.

System and Communications Protection (SC)

Control Requirement CRAIG Implementation

SC-7

Boundary Protection

CORS middleware enforces an explicit origin allowlist (not wildcard in production) with specific method enumeration (GET, POST, PUT, DELETE, OPTIONS). Public intake endpoints are rate-limited (configurable per-hour via governor crate). CAPTCHA (Cloudflare Turnstile) protects the public intake form from automated abuse. The BFF pattern ensures no direct browser-to-database communication — craig-web mediates all requests.

SC-8

Transmission Confidentiality

TLS is enforced via Keycloak redirect URI validation (HTTPS-only in production). Session cookies are set with Secure flag (configurable via SESSION_SECURE), HttpOnly, and SameSite=Strict; CSRF on state-changing requests is enforced by the verify_csrf middleware (Sec-Fetch-Site / Origin / Referer verification, #763). JWT bearer tokens are transmitted only over HTTPS. S3-compatible object storage (Garage) connections use TLS in production deployments.

SC-13

Cryptographic Protection

JWT tokens use RS256 (RSA 2048-bit + SHA-256) via Keycloak. Intake report integrity verification uses ECDSA P-256 with detached JWS (ES256). API key hashing uses SHA-256. All inter-service communication uses TLS in production. No custom cryptographic implementations — all cryptography uses audited libraries (ring, jsonwebtoken, ecdsa).

System and Information Integrity (SI)

Control Requirement CRAIG Implementation

SI-2

Flaw Remediation

cargo deny enforces license compliance and known vulnerability detection. GitLab CI runs four security scanning templates on every commit: SAST (semgrep), Secret Detection, Dependency Scanning (gemnasium), and Container Scanning. Remediation SLAs define time-to-patch by severity (Critical: 24hr, High: 7d, Medium: 30d, Low: 90d). See Security Operations for full remediation procedures.

SI-10

Information Input Validation

SQLx compile-time query validation prevents SQL injection by verifying all queries against the database schema at build time — no string concatenation of SQL. The ammonia crate sanitizes HTML in public intake form submissions. PostgreSQL CHECK constraints enforce valid enum values on all status and type columns. The craig-reference crate provides compile-time validated domain enums (48 unit tests). File upload validation enforces size limits, MIME type allowlists, and filename sanitization.

Additional Controls

The following controls are tracked in the nist_controls table but are primarily deployment-environment responsibilities:

Control Requirement Deployment Responsibility

CP-9

Information System Backup

Deploying agencies must configure PostgreSQL backup schedules (pg_dump or continuous archiving), RabbitMQ definitions export, Keycloak realm export, and object storage replication. CRAIG’s architecture supports backup by using standard infrastructure components with well-documented backup procedures.

IR-4

Incident Handling

CRAIG provides the detection and audit infrastructure (AU-2, AU-6). Deploying agencies must establish incident response teams, communication plans, and escalation procedures appropriate to their organization. See Incident Response Overview for the recommended framework.

PE-(Physical)

Physical and Environmental Protection

Not applicable to CRAIG as a software system. Physical security is the responsibility of the hosting environment (data center, cloud provider).

PL-(Planning)

Security Planning

Deploying agencies must develop a System Security Plan (SSP) that references this architecture mapping. See ATO Readiness Checklist for guidance.

Coverage Summary

Control Family Controls Mapped Status

Access Control (AC)

AC-2, AC-3, AC-6, AC-7

Fully implemented in application code and Keycloak

Audit and Accountability (AU)

AU-2, AU-6

Fully implemented via wildcard audit subscriber

Configuration Management (CM)

CM-2, CM-6

Fully implemented via Docker + env var architecture

Identification and Authentication (IA)

IA-2, IA-5

Fully implemented via Keycloak OIDC

System and Communications Protection (SC)

SC-7, SC-8, SC-13

Fully implemented in application middleware

System and Information Integrity (SI)

SI-2, SI-10

Fully implemented via CI scanning + compile-time validation

Contingency Planning (CP)

CP-9

Architecture supports; deployment-specific configuration required

Incident Response (IR)

IR-4

Detection infrastructure provided; response procedures are organizational

Physical (PE)

PE-*

Not applicable (software system)

Planning (PL)

PL-*

SSP template guidance provided

Edit this page · latest