From 9048691ce14cadc8fba422f76adca80b0430064b Mon Sep 17 00:00:00 2001 From: Mike Kell Date: Thu, 17 Jul 2025 18:32:19 -0400 Subject: [PATCH] Seed data sql files for testing Supabase throughout development --- auth/supabase/seed_auth_users.sql | 22 +++ auth/supabase/seed_data.sql | 101 ++++++++++++++ frontend/authentication.md | 218 ++++++++++++++++++++++++++++++ 3 files changed, 341 insertions(+) create mode 100644 auth/supabase/seed_auth_users.sql create mode 100644 auth/supabase/seed_data.sql create mode 100644 frontend/authentication.md diff --git a/auth/supabase/seed_auth_users.sql b/auth/supabase/seed_auth_users.sql new file mode 100644 index 0000000..072e481 --- /dev/null +++ b/auth/supabase/seed_auth_users.sql @@ -0,0 +1,22 @@ +-- ============================================ +-- Supabase Auth User Seeding (for dev/testing) +-- Required to satisfy FK constraint on users.id +-- ============================================ + +-- ACME Users +INSERT INTO auth.users (id, email, encrypted_password) +VALUES + ('00000000-0000-0000-0000-000000000001', 'jane@acme.com', 'hash-jane'), + ('00000000-0000-0000-0000-000000000002', 'mark@acme.com', 'hash-mark'); + +-- Orion Users +INSERT INTO auth.users (id, email, encrypted_password) +VALUES + ('00000000-0000-0000-0000-000000000003', 'kbrooks@orioncyber.io', 'hash-kyle'), + ('00000000-0000-0000-0000-000000000004', 'tina@orioncyber.io', 'hash-tina'); + +-- Internal Roles +INSERT INTO auth.users (id, email, encrypted_password) +VALUES + ('00000000-0000-0000-0000-000000000005', 'emily@complycore.com', 'hash-emily'), + ('00000000-0000-0000-0000-000000000006', 'admin@complycore.com', 'hash-admin'); diff --git a/auth/supabase/seed_data.sql b/auth/supabase/seed_data.sql new file mode 100644 index 0000000..8cec149 --- /dev/null +++ b/auth/supabase/seed_data.sql @@ -0,0 +1,101 @@ +-- ============================================== +-- ComplyCore: Clean Dev Seed with Valid UUIDs +-- ============================================== + +-- Clean tables (safe for dev only) +DELETE FROM auth_audit_log; +DELETE FROM evaluations; +DELETE FROM api_clients; +DELETE FROM users; +DELETE FROM tenants; + +-- --------------------- +-- TENANTS +-- --------------------- +INSERT INTO tenants (id, name, cage_code, sam_uid, primary_contact_name, primary_contact_email) +VALUES + ('11111111-1111-1111-1111-111111111111', 'ACME Defense Solutions', '5X9L2', 'JHE92SLMNTY4', 'Jane Smith', 'jane@acme.com'), + ('22222222-2222-2222-2222-222222222222', 'Orion Cyber Systems', '9X4T1', 'AER74Q9MDK33', 'Kyle Brooks', 'kbrooks@orioncyber.io'); + +-- --------------------- +-- USERS +-- --------------------- +-- ACME users +INSERT INTO users (id, tenant_id, role, first_name, last_name, email, phone_office, job_title) +VALUES + ('00000000-0000-0000-0000-000000000001', '11111111-1111-1111-1111-111111111111', 'client_admin', 'Jane', 'Smith', 'jane@acme.com', '555-1000', 'IT Manager'), + ('00000000-0000-0000-0000-000000000002', '11111111-1111-1111-1111-111111111111', 'client_user', 'Mark', 'Lee', 'mark@acme.com', '555-2001', 'System Analyst'); + +-- Orion users +INSERT INTO users (id, tenant_id, role, first_name, last_name, email, phone_office, job_title) +VALUES + ('00000000-0000-0000-0000-000000000003', '22222222-2222-2222-2222-222222222222', 'client_admin', 'Kyle', 'Brooks', 'kbrooks@orioncyber.io', '555-2002', 'Security Lead'), + ('00000000-0000-0000-0000-000000000004', '22222222-2222-2222-2222-222222222222', 'client_user', 'Tina', 'Ramos', 'tina@orioncyber.io', '555-2003', 'Compliance Analyst'); + +-- Global users +INSERT INTO users (id, tenant_id, role, first_name, last_name, email, phone_office, job_title) +VALUES + ('00000000-0000-0000-0000-000000000005', '11111111-1111-1111-1111-111111111111', 'reviewer', 'Emily', 'Nguyen', 'emily@complycore.com', '555-9001', 'CMMC Reviewer'), + ('00000000-0000-0000-0000-000000000006', '11111111-1111-1111-1111-111111111111', 'superadmin', 'Michael', 'Kell', 'admin@complycore.com', '555-9999', 'Platform Owner'); + +-- --------------------- +-- SERVICE ACCOUNTS +-- --------------------- +INSERT INTO api_clients ( + id, tenant_id, name, client_id, client_secret, scopes, description, created_by +) VALUES + ('99999999-1111-1111-1111-111111111111', '11111111-1111-1111-1111-111111111111', + 'ACME Upload Bot', 'acme-bot-1', 'acme-secret-1', ARRAY['upload', 'evaluate']::api_scope[], + 'Auto uploader for ACME', '00000000-0000-0000-0000-000000000001'), + + ('99999999-2222-2222-2222-222222222222', '22222222-2222-2222-2222-222222222222', + 'Orion CI/CD Service', 'orion-bot', 'orion-secret-token', ARRAY['upload', 'evaluate']::api_scope[], + 'Orion automation client', '00000000-0000-0000-0000-000000000003'); + +-- --------------------- +-- EVALUATIONS +-- --------------------- +-- Predefined UUIDs for project consistency +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM evaluations WHERE id = '44444444-aaaa-aaaa-aaaa-aaaaaaaaaaaa') THEN + INSERT INTO evaluations (id, tenant_id, project_id, control_id, status, notes, created_by) + VALUES + -- ACME + ('44444444-aaaa-aaaa-aaaa-aaaaaaaaaaaa', '11111111-1111-1111-1111-111111111111', + '55555555-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'AC.1.001', 'implemented', + 'Policy approved.', '00000000-0000-0000-0000-000000000002'), + + ('44444444-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '11111111-1111-1111-1111-111111111111', + '55555555-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'AC.2.007', 'partial', + 'Procedure referenced but not enforced.', '00000000-0000-0000-0000-000000000002'), + + ('44444444-cccc-cccc-cccc-cccccccccccc', '11111111-1111-1111-1111-111111111111', + '55555555-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'CM.2.063', 'missing', + 'No documented process.', '00000000-0000-0000-0000-000000000002'), + + -- Orion + ('44444444-dddd-dddd-dddd-dddddddddddd', '22222222-2222-2222-2222-222222222222', + '55555555-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'IA.1.076', 'implemented', + 'MFA enforced.', '00000000-0000-0000-0000-000000000004'), + + ('44444444-eeee-eeee-eeee-eeeeeeeeeeee', '22222222-2222-2222-2222-222222222222', + '55555555-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'AU.2.042', 'missing', + 'No audit logs collected.', '00000000-0000-0000-0000-000000000004'); + END IF; +END $$; + +-- --------------------- +-- AUDIT LOG +-- --------------------- +INSERT INTO auth_audit_log ( + id, actor_id, tenant_id, action, target_table, target_id, ip_address, user_agent, result +) VALUES + (gen_random_uuid(), '00000000-0000-0000-0000-000000000001', '11111111-1111-1111-1111-111111111111', + 'login_success', NULL, NULL, '192.168.1.101', 'Chrome', 'success'), + + (gen_random_uuid(), '99999999-1111-1111-1111-111111111111', '11111111-1111-1111-1111-111111111111', + 'upload_evaluation', 'evaluations', '44444444-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '10.0.1.15', 'bot/1.0', 'success'), + + (gen_random_uuid(), '00000000-0000-0000-0000-000000000005', '22222222-2222-2222-2222-222222222222', + 'view_evaluation', 'evaluations', '44444444-eeee-eeee-eeee-eeeeeeeeeeee', '192.168.5.25', 'Firefox', 'success'); diff --git a/frontend/authentication.md b/frontend/authentication.md new file mode 100644 index 0000000..074b84b --- /dev/null +++ b/frontend/authentication.md @@ -0,0 +1,218 @@ +# 🔐 ComplyCore Authentication & Authorization Design + +**Component:** Identity & Access Management (IAM) +**Version:** v1.0 +**Last Updated:** 2024-07-11 +**Owner:** Kell Engineering + +--- + +## ✅ Overview + +ComplyCore uses a **multi-tenant, RBAC-enforced identity system** built on PostgreSQL with Supabase Auth. All user and system access is governed by: + +- **Tenant isolation** via Row-Level Security (RLS) +- **Role-Based Access Control (RBAC)** via ENUM roles +- **Session-scoped variables** (`set_config()`) instead of legacy JWT hooks +- **Support for both human users and non-person entities (NPEs)** +- **Audit logging** for access, evaluation, and data modification events + +--- + +## 🧱 Database Entity Model + +```mermaid +erDiagram + tenants ||--o{ users : has + tenants ||--o{ api_clients : owns + tenants ||--o{ evaluations : owns + users ||--o{ evaluations : creates + users ||--o{ auth_audit_log : actor + api_clients ||--o{ auth_audit_log : actor + + tenants { + UUID id PK + TEXT name + TEXT cage_code + TEXT sam_uid + } + + users { + UUID id PK + UUID tenant_id FK + TEXT first_name + TEXT last_name + TEXT email + user_role role + } + + api_clients { + UUID id PK + UUID tenant_id FK + TEXT client_id + TEXT client_secret + api_scope[] scopes + } + + evaluations { + UUID id PK + UUID tenant_id FK + TEXT control_id + TEXT status + } + + auth_audit_log { + UUID id PK + UUID actor_id + UUID tenant_id FK + TEXT action + TEXT result + } +``` + +--- + +## 👤 User Roles + +```mermaid +flowchart LR + A[client_user] -->|RLS: Own tenant only| EvalTable + B[client_admin] -->|RLS: Own tenant only + mgmt| EvalTable + C[reviewer] -->|RLS: Read all tenants| EvalTable + D[superadmin] -->|RLS: Full control| EvalTable & UserTable +``` + +| Role | Description | Access Scope | +|--------------|----------------------------------|----------------------| +| `client_user`| End user | Own tenant only | +| `client_admin`| Tenant admin | Own tenant (plus user mgmt) | +| `reviewer` | Internal auditor or compliance | All tenants (read-only) | +| `superadmin` | Platform operator | Full access to all data | + +--- + +## 🔐 RLS Policies + +| Table | Role(s) | Access Type | Rule Description | +|------------------|----------------------|-----------------|--------------------------------------------| +| `users` | All | Self only | `id = auth.uid()` | +| `evaluations` | `client_*` | Tenant-bound | Match tenant via `set_config()` | +| `evaluations` | `reviewer` | Global read | Unrestricted SELECT | +| `evaluations` | `superadmin` | Full access | Unrestricted ALL w/ check | +| `api_clients` | All | Own tenant only | `enabled=true` AND tenant match | +| `auth_audit_log` | All | Tenant-bound | Match tenant | + +--- + +## 🔑 Session Variables (No JWT Custom Claims) + +Instead of deprecated JWT claim injection, ComplyCore uses: + +```sql +SELECT set_config('request.jwt.claim.role', user.role, true); +SELECT set_config('request.jwt.claim.tenant_id', user.tenant_id::text, true); +``` + +This enables per-session RLS enforcement and simplifies system-wide access control. + +--- + +## 🛡️ NPE: Non-Person Entities (API Clients) + +**Table:** `api_clients` + +| Field | Purpose | +|---------------|----------------------------------| +| `client_id` | Public API token ID | +| `client_secret` | Auth key (hashed) | +| `tenant_id` | Enforces scope per client | +| `scopes[]` | Least-privilege operations | +| `enabled` | Soft-delete / disable mechanism | + +**Scopes Enum:** +- `upload` +- `evaluate` +- `read_reports` +- `manage_projects` + +> RLS prevents disabled clients or cross-tenant access. + +--- + +## 📝 Audit Logging + +**Table:** `auth_audit_log` + +| Field | Type | Description | +|---------------|------------|----------------------------------------------| +| `actor_id` | UUID | User or service account | +| `tenant_id` | UUID | Organization context | +| `action` | TEXT | Description (e.g., `login_success`) | +| `target_table`| TEXT | Optional: table affected | +| `result` | TEXT | `success` or `fail` | +| `timestamp` | TIMESTAMP | System-generated UTC timestamp | + +This log supports: +- Login tracking +- API usage validation +- Internal audit trail for CMMC/DFARS controls + +--- + +## 🧠 CMMC Practice Coverage + +| Practice | Control Area | Implementation | +|----------------------|-----------------------|----------------------------------------| +| AC.1.001 | Access Control | Unique accounts (auth.users + users) | +| AC.1.002 | Access Enforcement | RBAC and RLS | +| AC.1.003 | Least Privilege | Role + tenant-scoped access | +| AU.2.042 | Audit Logs | `auth_audit_log` | +| IA.2.078 | MFA Capable | `mfa_enabled` flag (enforced by UI) | +| SC.3.177 | NPE Separation | `api_clients` with isolated scopes | + +--- + +## 📎 Appendices + +### 🔧 Initial Setup Function + +```sql +CREATE OR REPLACE FUNCTION set_claim_context() +RETURNS void +LANGUAGE plpgsql +SECURITY DEFINER +AS $$ +DECLARE + v_role TEXT; + v_tenant UUID; +BEGIN + SELECT role, tenant_id INTO v_role, v_tenant + FROM public.users + WHERE id = auth.uid(); + + PERFORM set_config('request.jwt.claim.role', v_role, true); + PERFORM set_config('request.jwt.claim.tenant_id', v_tenant::text, true); +END; +$$; +``` + +Call this at the start of every request/session to enforce scoped access. + +--- + +## ✅ Status + +| Component | Status | Notes | +|--------------------|---------------|----------------------------------------| +| Supabase Auth | ✅ Integrated | Used for identity backing | +| Postgres Tables | ✅ Complete | tenants, users, api_clients, audits | +| RLS Policies | ✅ Enforced | All core tables | +| Session Claims | ✅ Supported | Via `set_config()` | +| MFA Support | 🟡 Flagged | Client-side UI pending | + +--- + +**Maintained by:** Kell Engineering +**Contact:** mtkell@kellengineering.com +**Document ID:** `AUTH-DOC-001` +