up
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.Abstractions.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.Cisco.CSAF.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.MSRC.CSAF.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.OCI.OpenVEX.Attest.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.Oracle.CSAF.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.RedHat.CSAF.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.SUSE.RancherVEXHub.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
[assembly: InternalsVisibleTo("StellaOps.Excititor.Connectors.Ubuntu.CSAF.Tests")]
|
||||
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "1.99.99")]
|
||||
@@ -0,0 +1,102 @@
|
||||
-- VEX Schema Migration 003: 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 vex
|
||||
-- schema to provide database-level tenant isolation as defense-in-depth.
|
||||
--
|
||||
-- Note: VEX tables use 'tenant' column (not 'tenant_id') as per original schema.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 1: Create helper schema and function for tenant context
|
||||
-- ============================================================================
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS vex_app;
|
||||
|
||||
-- Tenant context helper function
|
||||
CREATE OR REPLACE FUNCTION vex_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 vex_app.require_current_tenant() FROM PUBLIC;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 2: Enable RLS on all tenant-scoped tables
|
||||
-- ============================================================================
|
||||
|
||||
-- vex.linksets
|
||||
ALTER TABLE vex.linksets ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE vex.linksets FORCE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS linksets_tenant_isolation ON vex.linksets;
|
||||
CREATE POLICY linksets_tenant_isolation ON vex.linksets
|
||||
FOR ALL
|
||||
USING (tenant = vex_app.require_current_tenant())
|
||||
WITH CHECK (tenant = vex_app.require_current_tenant());
|
||||
|
||||
-- vex.linkset_observations (inherits tenant via FK to linksets)
|
||||
ALTER TABLE vex.linkset_observations ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE vex.linkset_observations FORCE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS linkset_observations_tenant_isolation ON vex.linkset_observations;
|
||||
CREATE POLICY linkset_observations_tenant_isolation ON vex.linkset_observations
|
||||
FOR ALL
|
||||
USING (
|
||||
linkset_id IN (
|
||||
SELECT linkset_id FROM vex.linksets
|
||||
WHERE tenant = vex_app.require_current_tenant()
|
||||
)
|
||||
);
|
||||
|
||||
-- vex.linkset_disagreements (inherits tenant via FK to linksets)
|
||||
ALTER TABLE vex.linkset_disagreements ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE vex.linkset_disagreements FORCE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS linkset_disagreements_tenant_isolation ON vex.linkset_disagreements;
|
||||
CREATE POLICY linkset_disagreements_tenant_isolation ON vex.linkset_disagreements
|
||||
FOR ALL
|
||||
USING (
|
||||
linkset_id IN (
|
||||
SELECT linkset_id FROM vex.linksets
|
||||
WHERE tenant = vex_app.require_current_tenant()
|
||||
)
|
||||
);
|
||||
|
||||
-- vex.linkset_mutations (inherits tenant via FK to linksets)
|
||||
ALTER TABLE vex.linkset_mutations ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE vex.linkset_mutations FORCE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS linkset_mutations_tenant_isolation ON vex.linkset_mutations;
|
||||
CREATE POLICY linkset_mutations_tenant_isolation ON vex.linkset_mutations
|
||||
FOR ALL
|
||||
USING (
|
||||
linkset_id IN (
|
||||
SELECT linkset_id FROM vex.linksets
|
||||
WHERE tenant = vex_app.require_current_tenant()
|
||||
)
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 3: Create admin bypass role
|
||||
-- ============================================================================
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'vex_admin') THEN
|
||||
CREATE ROLE vex_admin WITH NOLOGIN BYPASSRLS;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
COMMIT;
|
||||
@@ -0,0 +1,95 @@
|
||||
-- VEX Schema Migration 004: Generated Columns for JSONB Hot Keys
|
||||
-- Sprint: SPRINT_3423_0001_0001 - Generated Columns for JSONB Hot Keys
|
||||
-- Category: A (safe, can run at startup)
|
||||
--
|
||||
-- Purpose: Extract frequently-queried fields from JSONB columns as generated columns
|
||||
-- to enable efficient B-tree indexing and accurate query planning statistics.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- vex.vex_raw_documents: Extract metadata and provenance hot fields
|
||||
-- ============================================================================
|
||||
|
||||
-- Format version from metadata (e.g., "openvex/0.2.0", "csaf/2.0")
|
||||
ALTER TABLE vex.vex_raw_documents
|
||||
ADD COLUMN IF NOT EXISTS doc_format_version TEXT
|
||||
GENERATED ALWAYS AS (metadata_json->>'formatVersion') STORED;
|
||||
|
||||
-- Tool name that produced the VEX document
|
||||
ALTER TABLE vex.vex_raw_documents
|
||||
ADD COLUMN IF NOT EXISTS doc_tool_name TEXT
|
||||
GENERATED ALWAYS AS (metadata_json->>'toolName') STORED;
|
||||
|
||||
-- Tool version for provenance tracking
|
||||
ALTER TABLE vex.vex_raw_documents
|
||||
ADD COLUMN IF NOT EXISTS doc_tool_version TEXT
|
||||
GENERATED ALWAYS AS (metadata_json->>'toolVersion') STORED;
|
||||
|
||||
-- Author/supplier from provenance (common filter)
|
||||
ALTER TABLE vex.vex_raw_documents
|
||||
ADD COLUMN IF NOT EXISTS doc_author TEXT
|
||||
GENERATED ALWAYS AS (provenance_json->>'author') STORED;
|
||||
|
||||
-- Timestamp from provenance (useful for ordering)
|
||||
ALTER TABLE vex.vex_raw_documents
|
||||
ADD COLUMN IF NOT EXISTS doc_timestamp TIMESTAMPTZ
|
||||
GENERATED ALWAYS AS ((provenance_json->>'timestamp')::timestamptz) STORED;
|
||||
|
||||
-- ============================================================================
|
||||
-- Indexes on generated columns
|
||||
-- ============================================================================
|
||||
|
||||
-- Index for filtering by format version (common dashboard query)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_vex_raw_docs_format_version
|
||||
ON vex.vex_raw_documents (doc_format_version)
|
||||
WHERE doc_format_version IS NOT NULL;
|
||||
|
||||
-- Index for filtering by tool name (compliance reporting)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_vex_raw_docs_tool_name
|
||||
ON vex.vex_raw_documents (tenant, doc_tool_name)
|
||||
WHERE doc_tool_name IS NOT NULL;
|
||||
|
||||
-- Index for author-based queries (supplier filtering)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_vex_raw_docs_author
|
||||
ON vex.vex_raw_documents (tenant, doc_author)
|
||||
WHERE doc_author IS NOT NULL;
|
||||
|
||||
-- Composite index for time-ordered tool queries
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_vex_raw_docs_tool_time
|
||||
ON vex.vex_raw_documents (tenant, doc_tool_name, doc_timestamp DESC)
|
||||
WHERE doc_tool_name IS NOT NULL;
|
||||
|
||||
-- Covering index for document listing dashboard
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_vex_raw_docs_listing
|
||||
ON vex.vex_raw_documents (tenant, retrieved_at DESC)
|
||||
INCLUDE (format, doc_format_version, doc_tool_name, doc_author);
|
||||
|
||||
-- Update statistics for query planner
|
||||
ANALYZE vex.vex_raw_documents;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- ============================================================================
|
||||
-- Verification queries (run manually to confirm):
|
||||
-- ============================================================================
|
||||
--
|
||||
-- -- Check generated columns are populated:
|
||||
-- SELECT
|
||||
-- digest,
|
||||
-- format,
|
||||
-- doc_format_version,
|
||||
-- doc_tool_name,
|
||||
-- doc_author,
|
||||
-- doc_timestamp
|
||||
-- FROM vex.vex_raw_documents
|
||||
-- LIMIT 10;
|
||||
--
|
||||
-- -- Verify index usage:
|
||||
-- EXPLAIN ANALYZE
|
||||
-- SELECT digest, doc_tool_name, doc_timestamp
|
||||
-- FROM vex.vex_raw_documents
|
||||
-- WHERE tenant = 'test-tenant'
|
||||
-- AND doc_tool_name = 'trivy'
|
||||
-- ORDER BY doc_timestamp DESC
|
||||
-- LIMIT 20;
|
||||
Reference in New Issue
Block a user