Commit graph

67 commits

Author SHA1 Message Date
5fb5fea25e
feat: require org owner permission to update organization settings
- Add authorization check in organization_controller.ex update action
- Only organization owners can modify organization settings via API
- Returns 403 Forbidden if user is not an owner
- Affects all organization settings including use_sites and name
- Organization name can now be updated via API (existing field)

This ensures critical organization settings are only changed by authorized users.
2026-03-10 13:32:38 -05:00
b3cff9afbb
stripe and email after signup 2026-03-06 10:07:27 -06:00
1d928d4356
security: implement comprehensive security audit fixes
Critical Fixes:
- Remove /health/time endpoint exposing system time information
  * Prevents attackers from detecting time sync issues for TOTP attacks
  * Removed route and controller function, updated tests
- Add email confirmation check to account data export
  * GDPR export now requires confirmed email address
  * Prevents unconfirmed accounts from accessing data export
- Add path traversal validation for MIB archive uploads
  * Extract to temp directory, validate all paths, then copy if safe
  * Prevents malicious tar/zip files from writing outside target directory
  * Added validate_extracted_paths/1 helper function

High Priority Fixes:
- Add comprehensive input validation for mobile auth
  * Length limits: device_name (255), device_os (100), app_version (50), push_token (512)
  * Prevents database corruption and storage exhaustion
- Add heartbeat rate limiting to agent channel
  * Limit database updates to once per 30 seconds (max ~2/min per agent)
  * Prevents malicious agents from exhausting database connections
- Sanitize 500 error responses
  * Return generic error messages to clients
  * Log full details server-side with request_id for support
  * Prevents leaking stack traces and module names
- Add message size limits to agent channel
  * 10MB maximum for all protobuf messages (result, heartbeat, error)
  * Prevents DoS attacks via oversized payloads

Medium Priority Fixes:
- Add GraphQL query depth limits (max_depth: 10)
  * Prevents DoS from deeply nested queries
  * Complements existing complexity limits

Code Quality:
- Refactor agent channel handlers to reduce nesting depth
  * Extract message processing into separate private functions
  * Fixes Credo warnings about excessive nesting
  * Improves code readability and maintainability

Files changed:
- lib/towerops_web/controllers/health_controller.ex
- lib/towerops_web/controllers/api/account_data_controller.ex
- lib/towerops_web/controllers/api/v1/mib_controller.ex
- lib/towerops/mobile_sessions/mobile_session.ex
- lib/towerops_web/channels/agent_channel.ex
- lib/towerops_web/controllers/error_json.ex
- lib/towerops_web/router.ex
- CHANGELOG.txt
- priv/static/changelog.txt
- test/towerops_web/controllers/health_controller_test.exs
- test/towerops_web/controllers/error_json_test.exs

All 7,424 tests passing.
2026-03-05 13:08:10 -06:00
91dd7ad985
fix: allow site_id on device create regardless of use_sites setting
The API was silently stripping site_id when use_sites was false, causing
the Terraform provider to report inconsistent state after apply.
2026-02-15 12:28:06 -06:00
c790794191 Fix tests, credo issues, and Gaiia sync bugs
- Fix CLOAK_KEY placeholder in nix shell (invalid base64)
- Fix error HTML test assertion to match actual template
- Fix Gaiia sync: read 'subnet' field instead of 'block' for IP blocks
- Fix Gaiia sync: extract nested status name from subscription objects
- Fix security headers tests for environment detection
- Fix mobile auth tests to use raw_token
- Fix LiveView test assertions to match actual template content
- Fix SNMP config test expectations for test environment
- Refactor: resolve all Credo complexity/nesting issues
  - Extract helper functions in NetBox sync, VISP sync, Sonar sync
  - Flatten nested conditionals in settings, integrations, alerts
  - Use with/validate_present pattern for connection testing
2026-02-15 11:55:49 -06:00
34fe5d7e49 Security fixes: mask credentials in logs/API, fix cookie/CSP/LIKE injection/webhooks
CRITICAL fixes:
- Mask SNMP community string in agent channel logs (CRITICAL-1)
- Remove snmpv3 passwords from REST API responses, return _set booleans (CRITICAL-2)
- Replace snmp_community with snmp_community_set in GraphQL type (CRITICAL-3)

HIGH fixes:
- Fix cookie same_site from invalid 'Towerops' to 'Lax' (HIGH-4)
- Remove unsafe-eval from CSP script-src (HIGH-6)
- Block GraphQL introspection queries in production (HIGH-7)
- Sanitize LIKE wildcards in SNMP device name search (HIGH-8)
- Reject webhooks when no secret configured instead of accepting (HIGH-9)

MEDIUM fixes:
- Hash mobile session tokens (SHA-256) before DB storage (MEDIUM-10)
- Apply security headers in all environments, not just prod (MEDIUM-14)
- Add GraphQL query complexity limit (500) in production (MEDIUM-16)
- Fix X-Frame-Options to DENY to match frame-ancestors 'none' (MEDIUM-13)
2026-02-15 09:09:04 -06:00
968c5008ec api: expand format_site to return all fields including lat/lng 2026-02-14 17:46:28 -06:00
e954c7930a Fix Gaiia webhook timestamp: Gaiia sends millis, not seconds
The timestamp check was comparing millisecond timestamps against
System.system_time(:second), causing every webhook to be rejected
as 'expired'. Now normalizes timestamps >10 digits to seconds.
2026-02-14 17:15:25 -06:00
f59db9565c Gaiia webhook: clean rewrite per exact docs, detailed logging on failure 2026-02-14 16:57:55 -06:00
2c55ab5b77 Gaiia webhook: accept even when signature fails, log details for debugging 2026-02-14 16:52:25 -06:00
8f04a3f684 Fix credo: extract PagerDuty HMAC verification to reduce nesting 2026-02-14 16:31:54 -06:00
be5fa8f4d7 Gaiia webhook: proper HMAC verification per docs, optional when no header 2026-02-14 16:28:35 -06:00
ba895b0ca2 Remove Gaiia webhook secret verification entirely — Gaiia has no signing mechanism 2026-02-14 16:25:56 -06:00
95d833874a Gaiia webhook: verify secret via query param instead of signature header 2026-02-14 16:08:27 -06:00
82dd75d2e9 Fix Gaiia webhook (no signature), sites page with table + insights 2026-02-14 16:07:26 -06:00
05cdc79124 Fix Gaiia webhook: eventName field, payload extraction, add header logging 2026-02-14 15:40:06 -06:00
7b72ed3164 PagerDuty two-way sync: webhook receiver for resolve/acknowledge
- POST /api/v1/webhooks/pagerduty/:organization_id endpoint
- HMAC-SHA256 signature verification (optional, via webhook_secret)
- incident.resolved → resolve_alert_silent (no re-notify to PagerDuty)
- incident.acknowledged → acknowledge_alert_silent (no re-notify)
- Matches alerts via dedup_key format: towerops-alert-<uuid>
- Webhook secret configurable in org settings PagerDuty panel
- Setup instructions in UI for PagerDuty Generic Webhooks (v3)
2026-02-14 14:58:58 -06:00
db40a3e5b7 feat: show human-readable sync status messages for integrations
- Added last_sync_message field to integrations schema
- Gaiia sync: shows item counts on success, friendly error on failure
- Preseem sync: shows AP/device counts on success, friendly error on failure
- Error messages translated from technical errors to user-friendly text
- Message displayed on integration card next to status badge
- Exposed in REST API response
2026-02-14 14:11:02 -06:00
a028695d3b
format 2026-02-14 13:57:25 -06:00
950f4d9ae0 fix: implement Gaiia webhook signature verification per their spec
- Header: X-Gaiia-Webhook-Signature with t=timestamp,v1=signature format
- Signed payload: timestamp.body (not just body)
- 5-minute timestamp tolerance to prevent replay attacks
- Updated tests to match new 4-arity verify_signature/4
2026-02-14 13:37:26 -06:00
146f5745cf
fix: resolve compilation errors, test failures, and credo issues
- Escape HEEx template braces in GraphQL/API docs with raw(~S[...])
- Fix test assertions for updated marketing copy and UI text
- Extract helper functions in GraphQL resolvers to reduce nesting depth
- Create shared ErrorHelpers module for API controllers
- Fix ETS race condition in brute force whitelist cache for async tests
- Fix property test generators to use ASCII instead of printable unicode
- Add alert_severity helper to site_live/show
- Update accounts fixtures for explicit user confirmation
2026-02-14 12:23:10 -06:00
a8339797fa feat: expand REST API with alerts, agents, org settings, members, integrations, metrics, activity endpoints 2026-02-14 11:28:57 -06:00
bad1590fed
add gaiia webhook listener with per-org signature verification
Stage 3 of Gaiia integration: webhook event processing for real-time
incremental updates from Gaiia. HMAC-SHA256 signature verification
using per-organization secrets stored in integration credentials.
Handles account, billing subscription, and inventory item events.
2026-02-13 10:40:49 -06:00
c7df6a8569
Add CI-triggered mass agent update webhook
POST /api/v1/webhooks/agent-release triggers all connected agents
to self-update via their existing WebSocket channels. Authenticated
with a shared secret (AGENT_WEBHOOK_SECRET env var).

- Add ReleaseChecker.invalidate_cache/0 for fresh GitHub fetch
- Add Agents.list_updatable_agents/0 (enabled + seen < 10min)
- Add Agents.broadcast_mass_update/0 orchestration function
- Add WebhookAuth plug with timing-safe secret comparison
- Add AgentReleaseWebhookController with :webhook pipeline
- Configure AGENT_WEBHOOK_SECRET in dev/test/runtime configs
2026-02-10 13:40:32 -06:00
fb8ffde119
fix: prevent site assignment when sites are disabled for org
When an organization has sites disabled (use_sites=false), the API
now automatically removes any site_id from device creation requests,
ensuring devices are assigned directly to the organization instead.

This prevents Terraform (and other API clients) from creating devices
in sites when sites functionality is disabled for the organization.

Fixes issue where Terraform could bypass site restrictions via API.
2026-02-08 13:24:48 -06:00
fb1d4c564f
security: fix critical vulnerabilities and atom exhaustion risks
Critical fixes:
- Add [:safe] option to binary_to_term to prevent RCE attacks
- Implement whitelist validation for String.to_atom conversions
- Add input validation before String.to_existing_atom usage

Changes:
- MIB compiler and cache: Use safe binary deserialization
- SNMP contexts: Whitelist protocol, device type, and source atoms
- API controllers: Validate error message keys before atom conversion
- Reduce function nesting to comply with Credo standards

All 6,145 tests passing with zero Credo issues.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 10:30:30 -06:00
e3e47fb82f
fix: include SNMPv3 fields in API device responses
The API was not returning SNMPv3 fields (security_level, username,
auth_protocol, auth_password, priv_protocol, priv_password) in device
responses, causing Terraform provider to see inconsistent state between
plan and apply.

Updated both format_device/1 and format_device_details/1 to include
all SNMPv3 fields in JSON responses.
2026-02-06 14:05:15 -06:00
89911bae9c
Device list bug fix 2026-02-04 16:49:17 -06:00
7a1317d0d0
API: Default organization_id to authenticated org when empty
When creating devices via API, organization_id is now properly defaulted
to the authenticated organization's ID even when an empty string is sent.

This fixes Terraform provider compatibility where organization_id may be
sent as "" instead of omitted entirely.

Before: Only checked if key was missing (Map.has_key?)
After: Also handles nil and empty string values
2026-02-04 16:03:20 -06:00
8382b5df6a
make devices site optional and many test fix 2026-02-04 15:05:42 -06:00
1a054fd598
make sites optional 2026-02-04 13:05:32 -06:00
e46ecbfca2 Replace single name field with first_name and last_name 2026-02-01 15:00:23 -06:00
7232dab601
live device polling 2026-02-01 13:19:32 -06:00
61a06fc11c
Add firmware version tracking system
- Add firmware context module with upsert, query, and logging functions
- Add FirmwareVersionFetcherWorker to fetch MikroTik RSS daily
- Add Oban cron schedules (2 AM dev, 4 AM prod)
- Add version change detection to Discovery module
- Track firmware history with PubSub broadcasts
- All tests passing

Phase 3-5 of firmware tracking implementation complete.
Next: LiveView UI indicators.
2026-02-01 10:46:27 -06:00
3c00dcf37c remove passkeys for now 2026-01-31 09:50:35 -06:00
22ae257b60 refactor 2026-01-31 09:35:07 -06:00
6ca22c5dd0 enhance user auditing 2026-01-30 17:38:07 -06:00
25397139c1 nif ci fix complie in ci 2026-01-30 13:01:44 -06:00
09e1d81a9a fix superuser api device limits 2026-01-29 13:01:21 -06:00
aed15dd6a1 impersonate fixes 2026-01-28 14:41:27 -06:00
a4ea96bebc support prod ip db import 2026-01-28 14:03:35 -06:00
0b27300931 support prod ip db import 2026-01-28 13:48:33 -06:00
234ff7cbd2 add upsert support for geoip imports to prevent duplicates 2026-01-28 13:37:02 -06:00
7ecc986bcd support prod ip db import 2026-01-28 13:20:53 -06:00
d1fd1d4a62 remove Mix.env and support ip database import 2026-01-28 13:08:06 -06:00
220f1edce3 cookie improvements 2026-01-28 12:30:28 -06:00
124d68d28d
credo fixes 2026-01-27 09:12:22 -06:00
756a6b4cd4
poller agent fix and trigger device rediscovery 2026-01-26 14:51:32 -06:00
d78c42c8f4
test improvements 2026-01-18 17:15:44 -06:00
1f123bbeb9
add honeybadger and snmp overhaul 2026-01-18 16:16:08 -06:00