← Security & Compliance

Arkhivio Backup Framework — NIST Compliance Report

Document date: 2026  ·  Frameworks: NIST SP 800-53 Rev. 5 & NIST CSF 2.0  ·  Grounded in source-code review

Scope: This report maps the Arkhivio Backup Framework's technical controls to the NIST Special Publication 800-53 Revision 5 security control catalogue and the NIST Cybersecurity Framework 2.0 (CSF) core functions. Only controls directly evidenced in the codebase and deployment configuration are assessed. Organisational controls (policies, risk assessments, workforce training, incident response plans, supply-chain management) remain the responsibility of the operating organisation. This document does not constitute a formal NIST assessment or FedRAMP authorisation.

Executive Summary

14
Controls satisfied
by design
4
Config required
(env or cloud)
3
Operational gaps
(no code required)
2
Organisational /
external controls
Verdict: Substantially aligned with NIST SP 800-53 Rev. 5 and CSF 2.0. The framework satisfies the core technical control families: identification and authentication (IA), access control (AC), audit and accountability (AU), system and communications protection (SC), integrity (SI), and contingency planning (CP). Three operational gaps — cryptographic key formalisation, log retention, and continuous monitoring pipeline — require no code changes and are closed through configuration and operational procedures. Organisational controls (risk assessment, security planning, incident response) are outside the tool's scope.
Satisfied Implemented in code, active by default
Config required Capability exists; must be enabled via env or cloud settings
Operational gap No code change needed; operator action required
Organisational Outside tool scope; policy or contractual action required
How each gap is closed:
OPS Operational procedure or deployment configuration — no code change
EXT External system, cloud console, or organisational control
CODE Change inside this repository

AC — Access Control

Account Management
AC-2 — manage system accounts including creation, activation, modification, review, disabling, and removal
Satisfied

Two distinct account types — "admin" (full CRUD) and "operator" (read-only) — are provisioned via environment variables or Active Directory group membership (auth.py). AD backend delegates account lifecycle management (creation, disabling, removal) to the directory service. Startup validation in _validate_config() rejects incomplete account configurations before the server accepts connections.

Access Enforcement & Least Privilege
AC-3 / AC-6 — enforce approved authorisations; limit access to least privilege
Satisfied

All API write endpoints are gated by the require_admin() FastAPI dependency (main.py). Operator accounts receive HTTP 403 on any attempt to invoke write operations. Read-only endpoints use require_auth(). Unauthenticated requests return HTTP 401 or redirect to the login page. Bucket credentials (access_key, secret_key) are stripped from all API responses by _serialize_bucket(), preventing privilege escalation through information disclosure.

Session Lock / Inactivity Timeout
AC-11 — initiate a session lock after a period of inactivity
Satisfied

SessionMiddleware configured with max_age=SESSION_TIMEOUT_SECONDS (default 3,600 s). Set SESSION_TIMEOUT_SECONDS=900 in .env for a 15-minute lock consistent with NIST moderate-baseline guidance. The server rejects replayed cookies past max_age; explicit logout clears the session immediately.

IA — Identification and Authentication

Identification and Authentication (Organisational Users)
IA-2 — uniquely identify and authenticate organisational users
Satisfied

Local backend enforces unique usernames per role with timing-safe comparison via secrets.compare_digest() (auth.py:121–130), preventing timing-based credential inference. AD backend binds each user individually via LDAP UPN, providing per-user unique identification backed by the enterprise directory.

Authenticator Management
IA-5 — manage system authenticators including passwords and cryptographic keys
Config required

Session cookies are signed with HMAC-SHA256 via itsdangerous using SESSION_SECRET; the application fails fast at startup if this secret is absent. The Fernet encryption key (BACKUP_SECRET_KEY) is validated at module load time. Key storage hardening is a configuration task: the framework supports 6 secrets-manager backends (AWS Secrets Manager, Azure Key Vault, GCP, IBM, HashiCorp Vault, OpenBao) via the SECRETS_PROVIDER env var.

→ Closed by operational configuration OPS
  • Activate a secrets manager: Set SECRETS_PROVIDER=aws (or azure, gcp, ibm, vault, openbao) in .env. The framework's secrets_manager.py will retrieve BACKUP_SECRET_KEY and MongoDB credentials from the chosen provider at startup, keeping secrets entirely off disk.
  • Credential rotation: Rotate BACKUP_SECRET_KEY, SESSION_SECRET, and MongoDB credentials on a documented schedule (NIST recommends periodic rotation; 90 days is documented in USER_MANUAL.md). No code change required — update the secret in the provider and restart the service.
  • Password complexity: For the local backend, enforce a minimum 20-character password with mixed character classes when setting ADMIN_PASSWORD and OPERATOR_PASSWORD.
Multi-Factor Authentication
IA-2(1) — implement MFA for privileged accounts
Operational gap

The framework authenticates with username + password only. NIST SP 800-63B and the SP 800-53 moderate baseline require MFA for privileged (admin) accounts. The framework does not implement MFA natively, but the deployment architecture allows this to be satisfied externally.

→ Closed by external / operational control EXT
  • AD backend: Configure AD FS or Azure AD Conditional Access to require MFA for the AD_ADMIN_GROUP. The LDAP bind in auth.py will only succeed for users who have satisfied the MFA challenge at the directory level.
  • Local backend or any deployment: Place the dashboard behind a VPN gateway or identity-aware proxy (e.g. Cloudflare Access, Tailscale, AWS Verified Access) that enforces TOTP or hardware-key MFA before allowing connections to port 443.
  • Document the chosen approach as the MFA implementation in your System Security Plan (SSP).

AU — Audit and Accountability

Audit Event Generation
AU-2 / AU-3 — generate audit records containing sufficient detail
Satisfied

Every significant event emits a structured JSON log record via log_event() (logger.py:70–86) containing ts (ISO-8601 UTC), event name, and contextual fields. All 6 privileged write endpoints emit named audit_* events with the acting user identity. Sample:

{"ts": "2026-04-01T09:14:22.317Z", "event": "audit_job_created", "user": "alice", "job": "db-backup"}
{"ts": "2026-04-01T09:30:01.008Z", "event": "audit_bucket_deleted", "user": "bob", "bucket": "old-prod"}
{"ts": "2026-04-01T11:02:44.590Z", "event": "upload_error", "job": "db-backup", "file": "/data/x", "error": "…"}
{"ts": "2026-04-01T11:03:10.221Z", "event": "reconciler_mismatch", "job": "db-backup", "missing": 3}

Events cover the full operation lifecycle: configuration changes, authentication, upload, scan, reconcile, delete, restore, and error conditions. No credentials or key material are ever written to logs.

Audit Log Storage and Protection
AU-9 / AU-11 — protect audit information; retain audit records per policy
Operational gap

Logs are written to stdout and optionally to a rotating file via RotatingFileHandler (logger.py:46–53, default 10 × 50 MB = 500 MB on disk). NIST SP 800-53 AU-11 requires retention aligned with organisational policy; for federal systems this is typically 3 years. The rotation scheme alone does not guarantee this.

→ Closed by operational configuration OPS
  • Log forwarding: Set LOG_FILE=/var/log/backup/backup.log in .env, then configure a log shipper (Filebeat, Fluent Bit, CloudWatch agent) to forward to an immutable log store. Step-by-step guides for ELK, Loki, Splunk, and CloudWatch are in LOG_INTEGRATION.md.
  • Retention: Set CloudWatch Logs retention to ≥ 1,095 days (3 years) for NIST moderate, or ≥ 2,190 days (6 years) if also subject to HIPAA. For S3-backed archives, apply an S3 Lifecycle rule to transition to Glacier after 90 days.
  • Log integrity: Enable AWS CloudWatch Logs log-data integrity validation, or use S3 Object Lock on the archive bucket to prevent tampering (satisfies AU-9 protection requirement).

SC — System and Communications Protection

Cryptographic Protection
SC-8 / SC-28 — cryptographic mechanisms for data in transit and at rest
Config required

In transit: All S3 operations use HTTPS (TLS 1.2+) via boto3. Web dashboard traffic is TLS-terminated by nginx with TLS 1.2+ enforced, ECDHE cipher suites, HSTS (2-year, preload), and HTTP→HTTPS hard redirect. MongoDB TLS is configurable via MONGO_OPTIONS and warned on at startup when absent. At rest: S3 credentials stored in MongoDB are encrypted with Fernet (AES-128-CBC + HMAC-SHA256) via crypto_utils.py. Backup data encryption at rest requires SSE-KMS on the S3 bucket — a cloud-console configuration, not a code change.

→ Closed by external / cloud configuration EXT
  • S3 SSE-KMS: AWS Console → S3 → bucket → Properties → Default encryption → SSE-KMS → select CMK. Or via CLI: aws s3api put-bucket-encryption --bucket <name> --server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"<arn>"},"BucketKeyEnabled":true}]}'
  • Enforce encryption on upload: Add a bucket policy condition "s3:x-amz-server-side-encryption": "aws:kms" to deny unencrypted PutObject requests.
  • MongoDB TLS: Add tls=true&tlsCAFile=/path/to/ca.pem to MONGO_OPTIONS in .env. Atlas enforces TLS by default.
  • Annual key rotation: Enable automatic key rotation in AWS KMS. KMS re-encrypts data keys transparently with no service interruption.
Network Segmentation and Boundary Protection
SC-7 — implement boundary protection; monitor and control communications
Satisfied

The Docker deployment isolates the application on an internal bridge network (docker-compose.yml). The uvicorn process listens on port 8000 but is not exposed to the host; only the nginx container on the same internal network can reach it. External traffic enters only on ports 80 (immediate HTTP→HTTPS redirect) and 443 (HTTPS). Nginx sets server_tokens off, X-Frame-Options: SAMEORIGIN, X-Content-Type-Options: nosniff, and Strict-Transport-Security headers. The container runs as non-root user appuser.

Application Partitioning
SC-2 — separate user functionality from system management functionality
Satisfied

Administrative functions (job CRUD, bucket CRUD, auth configuration page) are guarded by require_admin(). Operator-accessible pages (dashboard, history, monitor) use require_auth(). The CLI pipeline (cli.py, scanner.py, uploader.py) is fully decoupled from the web dashboard and does not share session state, reducing the attack surface of the management interface.

SI — System and Information Integrity

Information Input Validation
SI-10 — check the validity of information inputs
Satisfied

API request bodies are validated via Pydantic BaseModel schemas (JobCreateRequest, BucketCreateRequest, etc.) in main.py. job_manager.py validates directory existence, threshold ordering (warning < critical, all > 0), and exclude-dir containment before writing to MongoDB. Invalid inputs return HTTP 422 with structured error detail.

Information and System Integrity — Backup Verification
SI-7 — detect unauthorised changes to software and information
Satisfied

CRC32 checksums are computed for every file at scan time (scanner.py), stored in MongoDB, and written to S3 object metadata on upload (uploader.py). audit.py provides three independent integrity checks on demand: (1) latest snapshot existence, (2) cross-validation of MongoDB CRC32 vs S3 x-amz-meta-crc32 metadata without downloading, (3) random file download with full CRC re-computation. reconciler.py detects MongoDB/S3 key-set drift and optionally corrects it.

Malicious Code Protection / Dependency Supply Chain
SI-3 / SR-3 — protect against malicious code; manage supply-chain risks
Config required

All production dependencies are pinned to minimum versions in requirements.txt (e.g. cryptography>=40.0.0, pymongo>=4.0.0). The Dockerfile uses a multi-stage build with python:3.12-slim to minimise the installed surface. Automated dependency scanning is a configuration task — no scanner runs in CI by default.

→ Closed by operational configuration OPS
  • Enable GitHub Dependabot: Add .github/dependabot.yml with package-ecosystem: pip to receive automated PRs for vulnerable dependencies.
  • Add pip-audit to CI: Run pip-audit -r requirements.txt in the CI pipeline to block builds with known CVEs.
  • Pin exact versions: For production images, lock all transitive dependencies with pip freeze > requirements.lock and build from the lockfile — reduces supply-chain drift between builds.
  • Container scanning: Scan the built Docker image with Trivy or Grype in CI before pushing to the registry.

CP — Contingency Planning

Information System Backup
CP-9 — conduct backups of user-level and system-level information
Satisfied

Core purpose of the framework. Multi-job, multi-host backup pipeline stores every file as a plain S3 object at {host}/{absolute/path}. CRC32 metadata is stored alongside each object. The files.json.gz inventory is published to S3 after each run. S3 versioning and cross-region replication can be independently enabled on the bucket for additional redundancy.

Information System Recovery and Reconstitution
CP-10 — provide for recovery and reconstitution of the information system
Satisfied

restore.py provides multi-threaded restore with conflict handling, dry-run preview, and original path preservation. restore_onlys3.py provides an independent recovery path requiring only S3 credentials — no framework binary or MongoDB needed. reconciler.py detects and fixes consistency drift between MongoDB and S3 before or after a recovery event.

Contingency Plan Testing
CP-4 — test the contingency plan to determine effectiveness
Satisfied

audit.py automates three-layer backup verification: snapshot catalogue check, S3 metadata CRC cross-validation, and random file download with CRC re-computation. Output is structured JSON suitable as evidence in a contingency plan test report. Documented as a weekly operational practice in USER_MANUAL.md.

RA / CA — Risk Assessment & Continuous Monitoring

Vulnerability Monitoring and Scanning
RA-5 — scan for vulnerabilities in the information system periodically
Config required

No automated vulnerability scanner is included in the project. The codebase does ship with a full test suite (tests/) covering authentication, pipeline, compression, MongoDB, and restore+audit flows. Periodic dependency and container vulnerability scanning is a configuration task.

→ Closed by operational configuration OPS
  • Dependency scanning: Run pip-audit or safety check as part of the CI pipeline on every merge to main.
  • Container scanning: Integrate Trivy or Snyk container scanning into the Docker build step.
  • SAST: Run bandit -r . for Python security anti-patterns as a CI quality gate.
  • Schedule: Run the full scan suite at minimum weekly in a scheduled CI job to catch newly published CVEs against pinned dependencies.
Continuous Monitoring
CA-7 — develop a continuous monitoring strategy; implement a continuous monitoring program
Operational gap

The framework emits rich structured events for all operations (uploads, errors, reconciler drift, auth failures, config warnings). ALERTING.md defines alert rules and runbooks. The gap is that no monitoring pipeline is activated by default — the log stream must be connected to a SIEM or metrics platform to fulfil CA-7.

→ Closed by operational configuration OPS
  • Log forwarding: Set LOG_FILE in .env and ship logs to ELK, Loki, Splunk, or CloudWatch per LOG_INTEGRATION.md.
  • Alerting: Import the alert rules from ALERTING.md into your chosen platform. Key events to alert on: upload_error, reconciler_mismatch, mongo_tls_disabled, secret_fetch_failed, repeated auth failures.
  • S3 monitoring: Enable AWS CloudTrail data events and S3 Access Logs on the bucket. Route to CloudWatch and set alarms on unexpected DeleteObject or GetObject calls outside approved IAM principals.
  • Uptime monitoring: The /login endpoint is health-checked every 30 s in the Docker Compose configuration — expose this to your monitoring platform.
Risk Assessment and Security Planning
RA-3 / PL-2 — conduct risk assessments; develop and implement a security plan
Organisational

Risk assessments and System Security Plans (SSPs) are organisational artefacts outside the scope of the framework. The codebase supports the evidence-gathering process: audit.py --json produces machine-readable integrity evidence, all configuration warnings are structured log events, and the deployment documentation (SETUP.md, USER_MANUAL.md) provides an accurate description of controls implemented.

Incident Response
IR-4 / IR-6 — handle incidents; report incidents to appropriate authorities
Organisational

The framework surfaces incident-relevant signals (anomalous CRC mismatches, reconciler drift, auth failures, S3 SlowDown events) as distinct structured log events. Translating those signals into an incident response workflow — classification, escalation, notification, and post-incident review — is an organisational procedure. ALERTING.md provides the starting-point alert rules to feed into an incident management system.

NIST CSF 2.0 — Function Mapping

Summary of how the framework maps to the six CSF 2.0 core functions.

CSF FunctionCoverage in this frameworkStatus
GV — Govern Organisational policies, risk tolerance, and supply-chain governance are outside scope. Startup fail-fast validation and startup configuration warnings support governance by preventing misconfigured deployments. Organisational
ID — Identify Asset inventory via files.json.gz published to S3 after every run. Job and bucket registry in MongoDB provides a managed asset catalogue. Dependency list in requirements.txt enables software component identification. Satisfied
PR — Protect RBAC (AC-3/AC-6), session timeout (AC-11), Fernet encryption (SC-28), TLS in transit (SC-8), HSTS + security headers (SC-7), non-root container execution, input validation (SI-10), secrets manager integration (IA-5). Satisfied
DE — Detect Structured JSON event log covers all operations; CRC mismatch events; reconciler drift detection; startup TLS and localhost warnings; ALERTING.md defines threshold alert rules. Monitoring pipeline must be connected operationally. Config required
RS — Respond Framework surfaces incident signals; response workflow (classification, notification, containment) is organisational. delete.py / deleter.py supports containment by removing compromised objects. Organisational
RC — Recover restore.py (full restore with integrity check), restore_onlys3.py (S3-only emergency path), reconciler.py (drift correction), audit.py (verification). Full recovery without framework dependencies is possible. Satisfied

Configuration Checklist

Actions required before a production deployment assessed against NIST SP 800-53 Rev. 5.

#ActionHow resolvedWhereControl
1 Enable SSE-KMS with a customer-managed key on the S3 bucket EXT AWS / Cloudflare console SC-28
2 Enable TLS on MongoDB connection (MONGO_OPTIONS=tls=true&tlsCAFile=…) OPS .env SC-8
3 Store BACKUP_SECRET_KEY and MongoDB credentials in a secrets manager. Set SECRETS_PROVIDER in .env to activate one of the 6 built-in integrations. OPS .env / secrets provider IA-5
4 Set SESSION_TIMEOUT_SECONDS=900 in .env for a 15-minute inactivity lock (NIST moderate baseline) OPS .env AC-11
5 Enable S3 Object Lock (WORM) on the bucket for the required data-retention period EXT AWS / Cloudflare console SI-7 / AU-9
6 Forward log output to an immutable log store. Set LOG_FILE in .env and configure a log shipper per LOG_INTEGRATION.md. Set retention ≥ 1,095 days (3 years). OPS .env / log shipper AU-9 / AU-11
7 Enforce MFA for admin accounts at the IdP (AD FS / Azure AD) or via a VPN / identity-aware proxy EXT AD / proxy / VPN IA-2(1)
8 Connect log stream to a SIEM and activate alert rules per ALERTING.md. Enable CloudTrail data events and S3 Access Logs. OPS SIEM / AWS console CA-7
9 Add pip-audit or Dependabot to CI; scan container image with Trivy OPS CI pipeline RA-5 / SI-3
10 Document a System Security Plan (SSP) referencing this report as technical control evidence EXT Organisational PL-2

Architectural Strengths for NIST

CapabilityHow it supports NIST controls
Fernet encryption of S3 credentialsSatisfies SC-28 for credential data at rest. A MongoDB compromise alone cannot expose S3 access. Key loadable from 6 external secrets managers, keeping secrets off disk (IA-5).
Timing-safe authenticationsecrets.compare_digest() in auth.py prevents timing-based credential enumeration — directly addresses IA-2 and IA-6 requirements.
Startup fail-fast validation_validate_config() raises RuntimeError if SESSION_SECRET, credentials, or AD variables are absent. Prevents operating in a degraded security posture — supports CA-7 and CM-6.
Structured JSON audit logEvery privileged action records actor, resource, and UTC timestamp. Machine-parseable — directly ingestible by SIEM. Satisfies AU-2, AU-3, AU-12.
3-check integrity auditOn-demand verifiable evidence that backup data is intact (SI-7). JSON output can be attached to CP-4 contingency plan test reports.
Non-root container executionContainer runs as appuser (Dockerfile); systemd service runs as backup:backup. Satisfies CM-7 least functionality and reduces privilege escalation risk.
Network isolationInternal Docker bridge network; uvicorn unexposed to host; nginx enforces TLS with HSTS and security headers. Directly addresses SC-7 boundary protection.
S3-only emergency recoveryFiles are plain objects at human-readable paths. No framework binary needed during recovery. Satisfies CP-10 reconstitution and CP-9 backup accessibility.
Important disclaimer: This report is a technical assessment produced by automated analysis of the source code mapped to NIST SP 800-53 Rev. 5 controls and NIST CSF 2.0 functions. It does not constitute a formal NIST assessment, FedRAMP authorisation package, or Authority to Operate (ATO). Control implementations must be independently verified by a qualified assessor. NIST control requirements vary by impact level (low / moderate / high); this report is written against the moderate baseline unless otherwise noted.