This commit is contained in:
StellaOps Bot
2025-12-14 23:20:14 +02:00
parent 3411e825cd
commit b058dbe031
356 changed files with 68310 additions and 1108 deletions

View File

@@ -0,0 +1,5 @@
using System.Runtime.CompilerServices;
using StellaOps.Plugin.Versioning;
[assembly: InternalsVisibleTo("StellaOps.Notify.Connectors.Email.Tests")]
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]

View File

@@ -0,0 +1,5 @@
using System.Runtime.CompilerServices;
using StellaOps.Plugin.Versioning;
[assembly: InternalsVisibleTo("StellaOps.Notify.Connectors.Shared.Tests")]
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]

View File

@@ -0,0 +1,5 @@
using System.Runtime.CompilerServices;
using StellaOps.Plugin.Versioning;
[assembly: InternalsVisibleTo("StellaOps.Notify.Connectors.Slack.Tests")]
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]

View File

@@ -0,0 +1,5 @@
using System.Runtime.CompilerServices;
using StellaOps.Plugin.Versioning;
[assembly: InternalsVisibleTo("StellaOps.Notify.Connectors.Teams.Tests")]
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]

View File

@@ -0,0 +1,5 @@
using System.Runtime.CompilerServices;
using StellaOps.Plugin.Versioning;
[assembly: InternalsVisibleTo("StellaOps.Notify.Connectors.Webhook.Tests")]
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]

View File

@@ -0,0 +1,178 @@
-- Notify Schema Migration 010: Row-Level Security
-- Sprint: SPRINT_3421_0001_0001 - RLS Expansion
-- Category: B (release migration, requires coordination)
--
-- Purpose: Enable Row-Level Security on all tenant-scoped tables in the notify
-- schema to provide database-level tenant isolation as defense-in-depth.
BEGIN;
-- ============================================================================
-- Step 1: Create helper schema and function for tenant context
-- ============================================================================
CREATE SCHEMA IF NOT EXISTS notify_app;
-- Tenant context helper function
CREATE OR REPLACE FUNCTION notify_app.require_current_tenant()
RETURNS TEXT
LANGUAGE plpgsql STABLE SECURITY DEFINER
AS $$
DECLARE
v_tenant TEXT;
BEGIN
v_tenant := current_setting('app.tenant_id', true);
IF v_tenant IS NULL OR v_tenant = '' THEN
RAISE EXCEPTION 'app.tenant_id session variable not set'
USING HINT = 'Set via: SELECT set_config(''app.tenant_id'', ''<tenant>'', false)',
ERRCODE = 'P0001';
END IF;
RETURN v_tenant;
END;
$$;
REVOKE ALL ON FUNCTION notify_app.require_current_tenant() FROM PUBLIC;
-- ============================================================================
-- Step 2: Enable RLS on all tenant-scoped tables
-- ============================================================================
-- notify.channels
ALTER TABLE notify.channels ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.channels FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS channels_tenant_isolation ON notify.channels;
CREATE POLICY channels_tenant_isolation ON notify.channels
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.rules
ALTER TABLE notify.rules ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.rules FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS rules_tenant_isolation ON notify.rules;
CREATE POLICY rules_tenant_isolation ON notify.rules
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.templates
ALTER TABLE notify.templates ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.templates FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS templates_tenant_isolation ON notify.templates;
CREATE POLICY templates_tenant_isolation ON notify.templates
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.deliveries
ALTER TABLE notify.deliveries ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.deliveries FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS deliveries_tenant_isolation ON notify.deliveries;
CREATE POLICY deliveries_tenant_isolation ON notify.deliveries
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.digests
ALTER TABLE notify.digests ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.digests FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS digests_tenant_isolation ON notify.digests;
CREATE POLICY digests_tenant_isolation ON notify.digests
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.quiet_hours
ALTER TABLE notify.quiet_hours ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.quiet_hours FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS quiet_hours_tenant_isolation ON notify.quiet_hours;
CREATE POLICY quiet_hours_tenant_isolation ON notify.quiet_hours
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.maintenance_windows
ALTER TABLE notify.maintenance_windows ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.maintenance_windows FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS maintenance_windows_tenant_isolation ON notify.maintenance_windows;
CREATE POLICY maintenance_windows_tenant_isolation ON notify.maintenance_windows
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.escalation_policies
ALTER TABLE notify.escalation_policies ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.escalation_policies FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS escalation_policies_tenant_isolation ON notify.escalation_policies;
CREATE POLICY escalation_policies_tenant_isolation ON notify.escalation_policies
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.escalation_states
ALTER TABLE notify.escalation_states ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.escalation_states FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS escalation_states_tenant_isolation ON notify.escalation_states;
CREATE POLICY escalation_states_tenant_isolation ON notify.escalation_states
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.on_call_schedules
ALTER TABLE notify.on_call_schedules ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.on_call_schedules FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS on_call_schedules_tenant_isolation ON notify.on_call_schedules;
CREATE POLICY on_call_schedules_tenant_isolation ON notify.on_call_schedules
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.inbox
ALTER TABLE notify.inbox ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.inbox FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS inbox_tenant_isolation ON notify.inbox;
CREATE POLICY inbox_tenant_isolation ON notify.inbox
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.incidents
ALTER TABLE notify.incidents ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.incidents FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS incidents_tenant_isolation ON notify.incidents;
CREATE POLICY incidents_tenant_isolation ON notify.incidents
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.audit
ALTER TABLE notify.audit ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.audit FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS audit_tenant_isolation ON notify.audit;
CREATE POLICY audit_tenant_isolation ON notify.audit
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- notify.locks
ALTER TABLE notify.locks ENABLE ROW LEVEL SECURITY;
ALTER TABLE notify.locks FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS locks_tenant_isolation ON notify.locks;
CREATE POLICY locks_tenant_isolation ON notify.locks
FOR ALL
USING (tenant_id = notify_app.require_current_tenant())
WITH CHECK (tenant_id = notify_app.require_current_tenant());
-- ============================================================================
-- Step 3: Create admin bypass role
-- ============================================================================
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'notify_admin') THEN
CREATE ROLE notify_admin WITH NOLOGIN BYPASSRLS;
END IF;
END
$$;
COMMIT;