Security hardening: policy-based actions, 3-role tokens, and security flags #10
No reviewers
Labels
No labels
bug
codex
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
quentinreytinas/borgmatic-api-nextcloud-aio!10
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/security-hardening"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Security Hardening: Policy-Based Automation
Summary
Hardens the Borgmatic API against Node-RED compromise by introducing a policy-based automation layer, role-separated tokens, and granular security flags.
Changes
1. Three-role token system
API_ADMIN_TOKEN— Full access (admin, config, locks, passphrase)API_ACTION_TOKEN— Predefined actions only (for Node-RED)API_READ_TOKEN— Read-only (status, health, polling, logs)SECURE_MODE=trueenforces all 3 tokens;falsepreserves legacyAPI_TOKENbehavior2. Policy-based actions
ACTIONS_POLICY_PATH)POST /actions/<name>/run— no payload, no sensitive paramstarget_display)New endpoints:
/actions/actions/<name>/run3. Security flags (5 ENABLE_* env vars)
ENABLE_ADMIN_ENDPOINTS/emergency/shutdownENABLE_CONFIG_WRITE/configs/*PUT/DELETE,/nextcloud/backup-targetPOSTENABLE_BREAK_LOCK/borgmatic-locks/break/*ENABLE_PASSPHRASE_CHANGE/repositories/*/passphrase/changeENABLE_ARBITRARY_TARGETS/nextcloud/daily-backup/run-for-target*4. Structured audit logging
action_start/action_completeAUDIT_LOG_PATH) and/or stdout (AUDIT_STDOUT)5. Unit tests (38 tests — all passing)
Attack surface if Node-RED is compromised
Files changed
borgmatic_api_app/config.pyborgmatic_api_app/auth.pyborgmatic_api_app/actions.pyborgmatic_api_app/audit.pyborgmatic_api_app/routes/actions.pyborgmatic_api_app/routes/legacy.pyborgmatic_api_app/services.pyborgmatic_api_app/app.pytests/test_security.py.env.exampleSECURITY_REVIEW.mdactions-policy.example.yamlValidation
See
SECURITY_REVIEW.mdfor the complete audit document.💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:
34ae54cd76ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
@ -19,12 +23,29 @@ def create_app() -> Flask:buffers = BufferStore()The app factory currently hardcodes
stdout=Trueand dropslog_pathwheneveraudit_stdoutis enabled, soAUDIT_STDOUT=falseis ignored and dual logging (file + stdout) cannot work. This breaks the documented behavior of the audit flags and can prevent required audit persistence depending on deployment settings.Useful? React with 👍 / 👎.
@ -40,12 +61,101 @@ class AuthManager:if not auth_header.startswith("Bearer "):require_role()callsauth.require()directly and letsAuthErrorescape from the decorator. On/actionsroutes this exception is raised before entering the view-leveltry/except, so invalid or missing credentials produce a server error response path instead of an auth error response, which is incorrect API behavior for expected unauthenticated requests.Useful? React with 👍 / 👎.
@ -0,0 +127,4 @@def _execute_nextcloud_backup(services: "Services",policy: "ActionPolicy", # noqa: F821job_id: str,The background action worker imports
run_nextcloud_daily_backupfromborgmatic_api_app.services, but that symbol is not defined there (repo-wide search only finds this call site). As a result, everyPOST /actions/<name>/runjob will hit anImportErrorat execution time and fail immediately instead of running the backup.Useful? React with 👍 / 👎.