From f98b69e088baec74a57c595fbfa90602aec10e46 Mon Sep 17 00:00:00 2001 From: Tom Rogers Date: Tue, 3 Jun 2025 21:45:31 -0500 Subject: [PATCH] Removing problematic code for implementation validation --- c77_secure_db--1.0.sql | 1502 ++++++++++++++++++++-------------------- c77_secure_db.control | 2 +- 2 files changed, 752 insertions(+), 752 deletions(-) diff --git a/c77_secure_db--1.0.sql b/c77_secure_db--1.0.sql index 0d46683..d934b8e 100644 --- a/c77_secure_db--1.0.sql +++ b/c77_secure_db--1.0.sql @@ -1337,762 +1337,762 @@ COMMENT ON FUNCTION c77_secure_db_health_check() IS 'System health check and sta -- TESTING AND VALIDATION FRAMEWORK -- ============================================================================= --- Comprehensive security test suite -CREATE OR REPLACE FUNCTION c77_secure_db_test_security() - RETURNS JSONB - LANGUAGE plpgsql AS $$ -DECLARE - v_test_results JSONB := '{}'; -v_tests_passed INTEGER := 0; -v_tests_failed INTEGER := 0; -v_test_schema TEXT := 'c77_test_' || extract(epoch from now())::bigint; -v_operation_result JSONB; -BEGIN - -- Create test environment -EXECUTE format('CREATE SCHEMA %I', v_test_schema); +-- -- Comprehensive security test suite +-- CREATE OR REPLACE FUNCTION c77_secure_db_test_security() +-- RETURNS JSONB +-- LANGUAGE plpgsql AS $$ +-- DECLARE +-- v_test_results JSONB := '{}'; +-- v_tests_passed INTEGER := 0; +-- v_tests_failed INTEGER := 0; +-- v_test_schema TEXT := 'c77_test_' || extract(epoch from now())::bigint; +-- v_operation_result JSONB; +-- BEGIN +-- -- Create test environment +-- EXECUTE format('CREATE SCHEMA %I', v_test_schema); +-- +-- -- Create test table +-- EXECUTE format(' +-- CREATE TABLE %I.test_secure_table ( +-- id BIGSERIAL PRIMARY KEY, +-- name TEXT NOT NULL, +-- description TEXT, +-- content_hash TEXT, +-- hash_version INTEGER DEFAULT 1, +-- created_at TIMESTAMPTZ DEFAULT NOW(), +-- updated_at TIMESTAMPTZ DEFAULT NOW(), +-- deleted_at TIMESTAMPTZ +-- )', v_test_schema); +-- +-- -- Register schema as secure +-- PERFORM c77_secure_db_manage_secure_schemas('add', v_test_schema); +-- +-- -- TEST 1: Verify direct INSERT is blocked +-- BEGIN +-- EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''bypass_test'')', v_test_schema); +-- +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_insert_blocked', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Direct INSERT was allowed - CRITICAL SECURITY FLAW!' +-- ) +-- ); +-- EXCEPTION WHEN insufficient_privilege THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_insert_blocked', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Direct INSERT correctly blocked' +-- ) +-- ); +-- END; +-- +-- -- TEST 2: Verify direct UPDATE is blocked +-- BEGIN +-- EXECUTE format('UPDATE %I.test_secure_table SET name = ''hacked'' WHERE id = 1', v_test_schema); +-- +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_update_blocked', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Direct UPDATE was allowed - CRITICAL SECURITY FLAW!' +-- ) +-- ); +-- EXCEPTION WHEN insufficient_privilege THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_update_blocked', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Direct UPDATE correctly blocked' +-- ) +-- ); +-- END; +-- +-- -- TEST 3: Verify direct DELETE is blocked +-- BEGIN +-- EXECUTE format('DELETE FROM %I.test_secure_table WHERE id = 1', v_test_schema); +-- +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_delete_blocked', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Direct DELETE was allowed - CRITICAL SECURITY FLAW!' +-- ) +-- ); +-- EXCEPTION WHEN insufficient_privilege THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_delete_blocked', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Direct DELETE correctly blocked' +-- ) +-- ); +-- END; +-- +-- -- TEST 4: Verify legitimate secure operation works +-- BEGIN +-- SELECT c77_secure_db_operation(jsonb_build_object( +-- 'schema_name', v_test_schema, +-- 'table_name', 'test_secure_table', +-- 'operation', 'insert', +-- 'data', jsonb_build_object('name', 'legitimate_test', 'description', 'This should work') +-- )) INTO v_operation_result; +-- +-- IF (v_operation_result->>'success')::boolean THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'legitimate_operation', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Secure operation succeeded', +-- 'operation_id', v_operation_result->>'operation_id' +-- ) +-- ); +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'legitimate_operation', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Secure operation failed: ' || (v_operation_result->>'error') +-- ) +-- ); +-- END IF; +-- EXCEPTION WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'legitimate_operation', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- TEST 5: Test token expiration (simulate expired token) +-- -- Comprehensive security test suite +-- CREATE OR REPLACE FUNCTION c77_secure_db_test_security() +-- RETURNS JSONB +-- LANGUAGE plpgsql AS $$ +-- DECLARE +-- v_test_results JSONB := '{}'; +-- v_tests_passed INTEGER := 0; +-- v_tests_failed INTEGER := 0; +-- v_test_schema TEXT := 'c77_test_' || extract(epoch from now())::bigint; +-- v_operation_result JSONB; +-- BEGIN +-- -- Create test environment +-- EXECUTE format('CREATE SCHEMA %I', v_test_schema); +-- +-- -- Create test table +-- EXECUTE format(' +-- CREATE TABLE %I.test_secure_table ( +-- id BIGSERIAL PRIMARY KEY, +-- name TEXT NOT NULL, +-- description TEXT, +-- content_hash TEXT, +-- hash_version INTEGER DEFAULT 1, +-- created_at TIMESTAMPTZ DEFAULT NOW(), +-- updated_at TIMESTAMPTZ DEFAULT NOW(), +-- deleted_at TIMESTAMPTZ +-- )', v_test_schema); +-- +-- -- Register schema as secure +-- PERFORM c77_secure_db_manage_secure_schemas('add', v_test_schema); +-- +-- -- TEST 1: Verify direct INSERT is blocked +-- BEGIN +-- EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''bypass_test'')', v_test_schema); +-- +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_insert_blocked', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Direct INSERT was allowed - CRITICAL SECURITY FLAW!' +-- ) +-- ); +-- EXCEPTION WHEN insufficient_privilege THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_insert_blocked', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Direct INSERT correctly blocked' +-- ) +-- ); +-- END; +-- +-- -- TEST 2: Verify direct UPDATE is blocked +-- BEGIN +-- EXECUTE format('UPDATE %I.test_secure_table SET name = ''hacked'' WHERE id = 1', v_test_schema); +-- +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_update_blocked', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Direct UPDATE was allowed - CRITICAL SECURITY FLAW!' +-- ) +-- ); +-- EXCEPTION WHEN insufficient_privilege THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_update_blocked', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Direct UPDATE correctly blocked' +-- ) +-- ); +-- END; +-- +-- -- TEST 3: Verify direct DELETE is blocked +-- BEGIN +-- EXECUTE format('DELETE FROM %I.test_secure_table WHERE id = 1', v_test_schema); +-- +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_delete_blocked', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Direct DELETE was allowed - CRITICAL SECURITY FLAW!' +-- ) +-- ); +-- EXCEPTION WHEN insufficient_privilege THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'direct_delete_blocked', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Direct DELETE correctly blocked' +-- ) +-- ); +-- END; +-- +-- -- TEST 4: Verify legitimate secure operation works +-- BEGIN +-- SELECT c77_secure_db_operation(jsonb_build_object( +-- 'schema_name', v_test_schema, +-- 'table_name', 'test_secure_table', +-- 'operation', 'insert', +-- 'data', jsonb_build_object('name', 'legitimate_test', 'description', 'This should work') +-- )) INTO v_operation_result; +-- +-- IF (v_operation_result->>'success')::boolean THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'legitimate_operation', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Secure operation succeeded', +-- 'operation_id', v_operation_result->>'operation_id' +-- ) +-- ); +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'legitimate_operation', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Secure operation failed: ' || (v_operation_result->>'error') +-- ) +-- ); +-- END IF; +-- EXCEPTION WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'legitimate_operation', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- TEST 5: Test token expiration (simulate expired token) +-- BEGIN +-- -- This test verifies that expired tokens don't work +-- PERFORM set_config('c77_secure_db.auth_token', gen_random_uuid()::text, true); +-- EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''token_test'')', v_test_schema); +-- +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'token_expiration', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Invalid token was accepted - SECURITY FLAW!' +-- ) +-- ); +-- EXCEPTION WHEN insufficient_privilege THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'token_expiration', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Invalid token correctly rejected' +-- ) +-- ); +-- WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'token_expiration', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- Clean up token after TEST 5 +-- PERFORM set_config('c77_secure_db.auth_token', '', true); +-- +-- -- TEST 6: Test hash calculation and verification +-- BEGIN +-- -- Insert a record and verify its hash +-- SELECT c77_secure_db_operation(jsonb_build_object( +-- 'schema_name', v_test_schema, +-- 'table_name', 'test_secure_table', +-- 'operation', 'insert', +-- 'data', jsonb_build_object('name', 'hash_test', 'description', 'Test hash calculation') +-- )) INTO v_operation_result; +-- +-- IF (v_operation_result->>'success')::boolean AND (v_operation_result->>'content_hash') IS NOT NULL THEN +-- -- Now verify the hash +-- DECLARE +-- v_freshness_result JSONB; +-- v_record_data JSONB; +-- BEGIN +-- -- Get the inserted record data (simulated) +-- v_record_data := jsonb_build_object( +-- 'id', 1, -- Assuming first record +-- 'name', 'hash_test', +-- 'description', 'Test hash calculation' +-- ); +-- +-- v_freshness_result := c77_secure_db_check_freshness(v_test_schema, 'test_secure_table', v_record_data); +-- +-- IF (v_freshness_result->>'success')::boolean AND (v_freshness_result->>'fresh')::boolean THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Hash calculation and verification working correctly' +-- ) +-- ); +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Hash verification failed: ' || (v_freshness_result->>'error') +-- ) +-- ); +-- END IF; +-- END; +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Hash was not calculated during insert' +-- ) +-- ); +-- END IF; +-- EXCEPTION WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- Cleanup test environment +-- BEGIN +-- PERFORM c77_secure_db_manage_secure_schemas('remove', v_test_schema); +-- EXECUTE format('DROP SCHEMA %I CASCADE', v_test_schema); +-- EXCEPTION WHEN OTHERS THEN +-- -- Log cleanup failure but don't fail the test +-- v_test_results := v_test_results || jsonb_build_object( +-- 'cleanup_warning', 'Failed to cleanup test schema: ' || SQLERRM +-- ); +-- END; +-- +-- RETURN jsonb_build_object( +-- 'test_suite', 'c77_secure_db_security', +-- 'version', '2.0', +-- 'summary', jsonb_build_object( +-- 'tests_passed', v_tests_passed, +-- 'tests_failed', v_tests_failed, +-- 'total_tests', v_tests_passed + v_tests_failed, +-- 'success_rate', CASE +-- WHEN (v_tests_passed + v_tests_failed) > 0 THEN +-- round((v_tests_passed::numeric / (v_tests_passed + v_tests_failed) * 100), 2) +-- ELSE 0 +-- END +-- ), +-- 'overall_status', CASE +-- WHEN v_tests_failed = 0 THEN 'ALL_TESTS_PASSED' +-- ELSE 'SECURITY_ISSUES_DETECTED' +-- END, +-- 'test_results', v_test_results, +-- 'test_schema_used', v_test_schema, +-- 'timestamp', now() +-- ); +-- END; +-- $$; --- Create test table -EXECUTE format(' - CREATE TABLE %I.test_secure_table ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL, - description TEXT, - content_hash TEXT, - hash_version INTEGER DEFAULT 1, - created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW(), - deleted_at TIMESTAMPTZ - )', v_test_schema); - --- Register schema as secure -PERFORM c77_secure_db_manage_secure_schemas('add', v_test_schema); - --- TEST 1: Verify direct INSERT is blocked -BEGIN -EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''bypass_test'')', v_test_schema); - -v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'direct_insert_blocked', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Direct INSERT was allowed - CRITICAL SECURITY FLAW!' - ) - ); -EXCEPTION WHEN insufficient_privilege THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'direct_insert_blocked', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Direct INSERT correctly blocked' - ) - ); -END; - --- TEST 2: Verify direct UPDATE is blocked -BEGIN -EXECUTE format('UPDATE %I.test_secure_table SET name = ''hacked'' WHERE id = 1', v_test_schema); - -v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'direct_update_blocked', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Direct UPDATE was allowed - CRITICAL SECURITY FLAW!' - ) - ); -EXCEPTION WHEN insufficient_privilege THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'direct_update_blocked', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Direct UPDATE correctly blocked' - ) - ); -END; - --- TEST 3: Verify direct DELETE is blocked -BEGIN -EXECUTE format('DELETE FROM %I.test_secure_table WHERE id = 1', v_test_schema); - -v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'direct_delete_blocked', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Direct DELETE was allowed - CRITICAL SECURITY FLAW!' - ) - ); -EXCEPTION WHEN insufficient_privilege THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'direct_delete_blocked', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Direct DELETE correctly blocked' - ) - ); -END; - --- TEST 4: Verify legitimate secure operation works -BEGIN -SELECT c77_secure_db_operation(jsonb_build_object( - 'schema_name', v_test_schema, - 'table_name', 'test_secure_table', - 'operation', 'insert', - 'data', jsonb_build_object('name', 'legitimate_test', 'description', 'This should work') - )) INTO v_operation_result; - -IF (v_operation_result->>'success')::boolean THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'legitimate_operation', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Secure operation succeeded', - 'operation_id', v_operation_result->>'operation_id' - ) - ); -ELSE - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'legitimate_operation', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Secure operation failed: ' || (v_operation_result->>'error') - ) - ); -END IF; -EXCEPTION WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'legitimate_operation', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); -END; - --- TEST 5: Test token expiration (simulate expired token) --- Comprehensive security test suite -CREATE OR REPLACE FUNCTION c77_secure_db_test_security() - RETURNS JSONB - LANGUAGE plpgsql AS $$ -DECLARE - v_test_results JSONB := '{}'; - v_tests_passed INTEGER := 0; - v_tests_failed INTEGER := 0; - v_test_schema TEXT := 'c77_test_' || extract(epoch from now())::bigint; - v_operation_result JSONB; -BEGIN - -- Create test environment - EXECUTE format('CREATE SCHEMA %I', v_test_schema); - - -- Create test table - EXECUTE format(' - CREATE TABLE %I.test_secure_table ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL, - description TEXT, - content_hash TEXT, - hash_version INTEGER DEFAULT 1, - created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW(), - deleted_at TIMESTAMPTZ - )', v_test_schema); - - -- Register schema as secure - PERFORM c77_secure_db_manage_secure_schemas('add', v_test_schema); - - -- TEST 1: Verify direct INSERT is blocked - BEGIN - EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''bypass_test'')', v_test_schema); - - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'direct_insert_blocked', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Direct INSERT was allowed - CRITICAL SECURITY FLAW!' - ) - ); - EXCEPTION WHEN insufficient_privilege THEN - v_tests_passed := v_tests_passed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'direct_insert_blocked', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Direct INSERT correctly blocked' - ) - ); - END; - - -- TEST 2: Verify direct UPDATE is blocked - BEGIN - EXECUTE format('UPDATE %I.test_secure_table SET name = ''hacked'' WHERE id = 1', v_test_schema); - - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'direct_update_blocked', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Direct UPDATE was allowed - CRITICAL SECURITY FLAW!' - ) - ); - EXCEPTION WHEN insufficient_privilege THEN - v_tests_passed := v_tests_passed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'direct_update_blocked', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Direct UPDATE correctly blocked' - ) - ); - END; - - -- TEST 3: Verify direct DELETE is blocked - BEGIN - EXECUTE format('DELETE FROM %I.test_secure_table WHERE id = 1', v_test_schema); - - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'direct_delete_blocked', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Direct DELETE was allowed - CRITICAL SECURITY FLAW!' - ) - ); - EXCEPTION WHEN insufficient_privilege THEN - v_tests_passed := v_tests_passed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'direct_delete_blocked', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Direct DELETE correctly blocked' - ) - ); - END; - - -- TEST 4: Verify legitimate secure operation works - BEGIN - SELECT c77_secure_db_operation(jsonb_build_object( - 'schema_name', v_test_schema, - 'table_name', 'test_secure_table', - 'operation', 'insert', - 'data', jsonb_build_object('name', 'legitimate_test', 'description', 'This should work') - )) INTO v_operation_result; - - IF (v_operation_result->>'success')::boolean THEN - v_tests_passed := v_tests_passed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'legitimate_operation', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Secure operation succeeded', - 'operation_id', v_operation_result->>'operation_id' - ) - ); - ELSE - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'legitimate_operation', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Secure operation failed: ' || (v_operation_result->>'error') - ) - ); - END IF; - EXCEPTION WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'legitimate_operation', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); - END; - - -- TEST 5: Test token expiration (simulate expired token) - BEGIN - -- This test verifies that expired tokens don't work - PERFORM set_config('c77_secure_db.auth_token', gen_random_uuid()::text, true); - EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''token_test'')', v_test_schema); - - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'token_expiration', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Invalid token was accepted - SECURITY FLAW!' - ) - ); - EXCEPTION WHEN insufficient_privilege THEN - v_tests_passed := v_tests_passed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'token_expiration', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Invalid token correctly rejected' - ) - ); - WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'token_expiration', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); - END; - - -- Clean up token after TEST 5 - PERFORM set_config('c77_secure_db.auth_token', '', true); - - -- TEST 6: Test hash calculation and verification - BEGIN - -- Insert a record and verify its hash - SELECT c77_secure_db_operation(jsonb_build_object( - 'schema_name', v_test_schema, - 'table_name', 'test_secure_table', - 'operation', 'insert', - 'data', jsonb_build_object('name', 'hash_test', 'description', 'Test hash calculation') - )) INTO v_operation_result; - - IF (v_operation_result->>'success')::boolean AND (v_operation_result->>'content_hash') IS NOT NULL THEN - -- Now verify the hash - DECLARE - v_freshness_result JSONB; - v_record_data JSONB; - BEGIN - -- Get the inserted record data (simulated) - v_record_data := jsonb_build_object( - 'id', 1, -- Assuming first record - 'name', 'hash_test', - 'description', 'Test hash calculation' - ); - - v_freshness_result := c77_secure_db_check_freshness(v_test_schema, 'test_secure_table', v_record_data); - - IF (v_freshness_result->>'success')::boolean AND (v_freshness_result->>'fresh')::boolean THEN - v_tests_passed := v_tests_passed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Hash calculation and verification working correctly' - ) - ); - ELSE - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Hash verification failed: ' || (v_freshness_result->>'error') - ) - ); - END IF; - END; - ELSE - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Hash was not calculated during insert' - ) - ); - END IF; - EXCEPTION WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; - v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); - END; - - -- Cleanup test environment - BEGIN - PERFORM c77_secure_db_manage_secure_schemas('remove', v_test_schema); - EXECUTE format('DROP SCHEMA %I CASCADE', v_test_schema); - EXCEPTION WHEN OTHERS THEN - -- Log cleanup failure but don't fail the test - v_test_results := v_test_results || jsonb_build_object( - 'cleanup_warning', 'Failed to cleanup test schema: ' || SQLERRM - ); - END; - - RETURN jsonb_build_object( - 'test_suite', 'c77_secure_db_security', - 'version', '2.0', - 'summary', jsonb_build_object( - 'tests_passed', v_tests_passed, - 'tests_failed', v_tests_failed, - 'total_tests', v_tests_passed + v_tests_failed, - 'success_rate', CASE - WHEN (v_tests_passed + v_tests_failed) > 0 THEN - round((v_tests_passed::numeric / (v_tests_passed + v_tests_failed) * 100), 2) - ELSE 0 - END - ), - 'overall_status', CASE - WHEN v_tests_failed = 0 THEN 'ALL_TESTS_PASSED' - ELSE 'SECURITY_ISSUES_DETECTED' - END, - 'test_results', v_test_results, - 'test_schema_used', v_test_schema, - 'timestamp', now() - ); -END; -$$; - --- TEST 6: Test hash calculation and verification -BEGIN --- Insert a record and verify its hash -SELECT c77_secure_db_operation(jsonb_build_object( - 'schema_name', v_test_schema, - 'table_name', 'test_secure_table', - 'operation', 'insert', - 'data', jsonb_build_object('name', 'hash_test', 'description', 'Test hash calculation') - )) INTO v_operation_result; - -IF (v_operation_result->>'success')::boolean AND (v_operation_result->>'content_hash') IS NOT NULL THEN --- Now verify the hash -DECLARE - v_freshness_result JSONB; -v_record_data JSONB; - BEGIN - -- Get the inserted record data (simulated) -v_record_data := jsonb_build_object( - 'id', 1, -- Assuming first record - 'name', 'hash_test', - 'description', 'Test hash calculation' - ); - -v_freshness_result := c77_secure_db_check_freshness(v_test_schema, 'test_secure_table', v_record_data); - -IF (v_freshness_result->>'success')::boolean AND (v_freshness_result->>'fresh')::boolean THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Hash calculation and verification working correctly' - ) - ); -ELSE - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Hash verification failed: ' || (v_freshness_result->>'error') - ) - ); -END IF; -END; -ELSE - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Hash was not calculated during insert' - ) - ); -END IF; -EXCEPTION WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'hash_verification', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); -END; - --- Cleanup test environment -BEGIN -PERFORM c77_secure_db_manage_secure_schemas('remove', v_test_schema); -EXECUTE format('DROP SCHEMA %I CASCADE', v_test_schema); -EXCEPTION WHEN OTHERS THEN - -- Log cleanup failure but don't fail the test - v_test_results := v_test_results || jsonb_build_object( - 'cleanup_warning', 'Failed to cleanup test schema: ' || SQLERRM - ); -END; - -RETURN jsonb_build_object( - 'test_suite', 'c77_secure_db_security', - 'version', '2.0', - 'summary', jsonb_build_object( - 'tests_passed', v_tests_passed, - 'tests_failed', v_tests_failed, - 'total_tests', v_tests_passed + v_tests_failed, - 'success_rate', CASE - WHEN (v_tests_passed + v_tests_failed) > 0 THEN - round((v_tests_passed::numeric / (v_tests_passed + v_tests_failed) * 100), 2) - ELSE 0 - END - ), - 'overall_status', CASE - WHEN v_tests_failed = 0 THEN 'ALL_TESTS_PASSED' - ELSE 'SECURITY_ISSUES_DETECTED' - END, - 'test_results', v_test_results, - 'test_schema_used', v_test_schema, - 'timestamp', now() - ); -END; -$$; +-- -- TEST 6: Test hash calculation and verification +-- BEGIN +-- -- Insert a record and verify its hash +-- SELECT c77_secure_db_operation(jsonb_build_object( +-- 'schema_name', v_test_schema, +-- 'table_name', 'test_secure_table', +-- 'operation', 'insert', +-- 'data', jsonb_build_object('name', 'hash_test', 'description', 'Test hash calculation') +-- )) INTO v_operation_result; +-- +-- IF (v_operation_result->>'success')::boolean AND (v_operation_result->>'content_hash') IS NOT NULL THEN +-- -- Now verify the hash +-- DECLARE +-- v_freshness_result JSONB; +-- v_record_data JSONB; +-- BEGIN +-- -- Get the inserted record data (simulated) +-- v_record_data := jsonb_build_object( +-- 'id', 1, -- Assuming first record +-- 'name', 'hash_test', +-- 'description', 'Test hash calculation' +-- ); +-- +-- v_freshness_result := c77_secure_db_check_freshness(v_test_schema, 'test_secure_table', v_record_data); +-- +-- IF (v_freshness_result->>'success')::boolean AND (v_freshness_result->>'fresh')::boolean THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Hash calculation and verification working correctly' +-- ) +-- ); +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Hash verification failed: ' || (v_freshness_result->>'error') +-- ) +-- ); +-- END IF; +-- END; +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Hash was not calculated during insert' +-- ) +-- ); +-- END IF; +-- EXCEPTION WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'hash_verification', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- Cleanup test environment +-- BEGIN +-- PERFORM c77_secure_db_manage_secure_schemas('remove', v_test_schema); +-- EXECUTE format('DROP SCHEMA %I CASCADE', v_test_schema); +-- EXCEPTION WHEN OTHERS THEN +-- -- Log cleanup failure but don't fail the test +-- v_test_results := v_test_results || jsonb_build_object( +-- 'cleanup_warning', 'Failed to cleanup test schema: ' || SQLERRM +-- ); +-- END; +-- +-- RETURN jsonb_build_object( +-- 'test_suite', 'c77_secure_db_security', +-- 'version', '2.0', +-- 'summary', jsonb_build_object( +-- 'tests_passed', v_tests_passed, +-- 'tests_failed', v_tests_failed, +-- 'total_tests', v_tests_passed + v_tests_failed, +-- 'success_rate', CASE +-- WHEN (v_tests_passed + v_tests_failed) > 0 THEN +-- round((v_tests_passed::numeric / (v_tests_passed + v_tests_failed) * 100), 2) +-- ELSE 0 +-- END +-- ), +-- 'overall_status', CASE +-- WHEN v_tests_failed = 0 THEN 'ALL_TESTS_PASSED' +-- ELSE 'SECURITY_ISSUES_DETECTED' +-- END, +-- 'test_results', v_test_results, +-- 'test_schema_used', v_test_schema, +-- 'timestamp', now() +-- ); +-- END; +-- $$; --- Test RBAC integration -CREATE OR REPLACE FUNCTION c77_secure_db_test_rbac_integration() - RETURNS JSONB - LANGUAGE plpgsql AS $$ -DECLARE - v_rbac_available BOOLEAN; -v_test_results JSONB := '{}'; -v_tests_passed INTEGER := 0; -v_tests_failed INTEGER := 0; -v_test_schema TEXT := 'c77_rbac_test_' || extract(epoch from now())::bigint; -v_operation_result JSONB; -BEGIN - -- Check if c77_rbac is available -SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = 'c77_rbac') INTO v_rbac_available; - -IF NOT v_rbac_available THEN - RETURN jsonb_build_object( - 'test_suite', 'c77_secure_db_rbac_integration', - 'rbac_available', false, - 'message', 'c77_rbac extension not available - skipping RBAC tests', - 'overall_status', 'SKIPPED', - 'timestamp', now() - ); -END IF; - --- Create test environment -EXECUTE format('CREATE SCHEMA %I', v_test_schema); -EXECUTE format(' - CREATE TABLE %I.rbac_test_table ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL, - content_hash TEXT, - created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW() - )', v_test_schema); - -PERFORM c77_secure_db_manage_secure_schemas('add', v_test_schema); - --- Set up RBAC test data -PERFORM c77_rbac_assign_subject('test_user', 'secure_operator', 'global', 'all'); -PERFORM c77_rbac_grant_feature('secure_operator', 'secure_db_insert'); -PERFORM c77_rbac_grant_feature('secure_operator', 'secure_db_update'); - --- TEST 1: Operation with valid RBAC permissions should succeed -BEGIN -PERFORM set_config('c77_rbac.external_id', 'test_user', true); - -SELECT c77_secure_db_operation( - jsonb_build_object( - 'schema_name', v_test_schema, - 'table_name', 'rbac_test_table', - 'operation', 'insert', - 'data', jsonb_build_object('name', 'rbac_test_record') - ), - true, -- check_rbac - 'secure_db_insert' - ) INTO v_operation_result; - -IF (v_operation_result->>'success')::boolean THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'valid_rbac_permission', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Operation with valid RBAC permission succeeded' - ) - ); -ELSE - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'valid_rbac_permission', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Operation failed despite valid RBAC permission: ' || (v_operation_result->>'error') - ) - ); -END IF; -EXCEPTION WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'valid_rbac_permission', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); -END; - --- TEST 2: Operation without required RBAC permission should fail -BEGIN -PERFORM set_config('c77_rbac.external_id', 'test_user', true); - -SELECT c77_secure_db_operation( - jsonb_build_object( - 'schema_name', v_test_schema, - 'table_name', 'rbac_test_table', - 'operation', 'insert', - 'data', jsonb_build_object('name', 'unauthorized_record') - ), - true, -- check_rbac - 'secure_db_delete' -- User doesn't have this permission - ) INTO v_operation_result; - -IF NOT (v_operation_result->>'success')::boolean AND (v_operation_result->>'error') LIKE '%Insufficient permissions%' THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'invalid_rbac_permission', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Operation correctly blocked due to insufficient RBAC permissions' - ) - ); -ELSE - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'invalid_rbac_permission', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Operation should have been blocked by RBAC but was not' - ) - ); -END IF; -EXCEPTION WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'invalid_rbac_permission', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); -END; - --- TEST 3: Operation without user context should fail -BEGIN -PERFORM set_config('c77_rbac.external_id', '', true); - -SELECT c77_secure_db_operation( - jsonb_build_object( - 'schema_name', v_test_schema, - 'table_name', 'rbac_test_table', - 'operation', 'insert', - 'data', jsonb_build_object('name', 'no_context_record') - ), - true, -- check_rbac - 'secure_db_insert' - ) INTO v_operation_result; - -IF NOT (v_operation_result->>'success')::boolean AND (v_operation_result->>'error') LIKE '%no user context%' THEN - v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'no_user_context', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Operation correctly blocked due to missing user context' - ) - ); -ELSE - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'no_user_context', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Operation should have been blocked due to missing user context' - ) - ); -END IF; -EXCEPTION WHEN OTHERS THEN - v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'no_user_context', jsonb_build_object( - 'status', 'ERROR', - 'message', SQLERRM - ) - ); -END; - --- Cleanup RBAC test data -BEGIN -PERFORM c77_rbac_revoke_subject_role('test_user', 'secure_operator', 'global', 'all'); -PERFORM c77_rbac_revoke_feature('secure_operator', 'secure_db_insert'); -PERFORM c77_rbac_revoke_feature('secure_operator', 'secure_db_update'); -EXCEPTION WHEN OTHERS THEN - -- Ignore cleanup errors - NULL; -END; - --- Cleanup test environment -BEGIN -PERFORM c77_secure_db_manage_secure_schemas('remove', v_test_schema); -EXECUTE format('DROP SCHEMA %I CASCADE', v_test_schema); -EXCEPTION WHEN OTHERS THEN - v_test_results := v_test_results || jsonb_build_object( - 'cleanup_warning', 'Failed to cleanup test schema: ' || SQLERRM - ); -END; - -RETURN jsonb_build_object( - 'test_suite', 'c77_secure_db_rbac_integration', - 'rbac_available', true, - 'summary', jsonb_build_object( - 'tests_passed', v_tests_passed, - 'tests_failed', v_tests_failed, - 'total_tests', v_tests_passed + v_tests_failed, - 'success_rate', CASE - WHEN (v_tests_passed + v_tests_failed) > 0 THEN - round((v_tests_passed::numeric / (v_tests_passed + v_tests_failed) * 100), 2) - ELSE 0 - END - ), - 'overall_status', CASE - WHEN v_tests_failed = 0 THEN 'ALL_TESTS_PASSED' - ELSE 'RBAC_INTEGRATION_ISSUES' - END, - 'test_results', v_test_results, - 'timestamp', now() - ); -END; -$$; - --- Master test runner - runs all tests -CREATE OR REPLACE FUNCTION c77_secure_db_run_all_tests() - RETURNS JSONB - LANGUAGE plpgsql AS $$ -DECLARE - v_security_results JSONB; -v_rbac_results JSONB; -v_health_results JSONB; -v_overall_status TEXT := 'ALL_TESTS_PASSED'; -BEGIN - -- Run security tests -v_security_results := c77_secure_db_test_security(); - - -- Run RBAC integration tests -v_rbac_results := c77_secure_db_test_rbac_integration(); - - -- Run health check -v_health_results := c77_secure_db_health_check(); - - -- Determine overall status -IF (v_security_results->>'overall_status') != 'ALL_TESTS_PASSED' THEN - v_overall_status := 'SECURITY_ISSUES_DETECTED'; -ELSIF (v_rbac_results->>'overall_status') NOT IN ('ALL_TESTS_PASSED', 'SKIPPED') THEN - v_overall_status := 'RBAC_INTEGRATION_ISSUES'; -END IF; - -RETURN jsonb_build_object( - 'test_suite', 'c77_secure_db_complete', - 'version', '2.0', - 'overall_status', v_overall_status, - 'security_tests', v_security_results, - 'rbac_integration_tests', v_rbac_results, - 'health_check', v_health_results, - 'recommendation', CASE v_overall_status - WHEN 'ALL_TESTS_PASSED' THEN 'Extension is ready for production use' - WHEN 'SECURITY_ISSUES_DETECTED' THEN 'CRITICAL: Fix security issues before any production use' - WHEN 'RBAC_INTEGRATION_ISSUES' THEN 'RBAC integration needs attention - can use without RBAC' - ELSE 'Review test results and address issues' - END, - 'timestamp', now() - ); -END; -$$; - --- Grant permissions for test functions -GRANT EXECUTE ON FUNCTION c77_secure_db_test_security() TO c77_secure_db_admin; -GRANT EXECUTE ON FUNCTION c77_secure_db_test_rbac_integration() TO c77_secure_db_admin; -GRANT EXECUTE ON FUNCTION c77_secure_db_run_all_tests() TO c77_secure_db_admin; - -COMMENT ON FUNCTION c77_secure_db_test_security() IS 'Comprehensive security test suite for the extension'; -COMMENT ON FUNCTION c77_secure_db_test_rbac_integration() IS 'Tests integration with c77_rbac extension'; -COMMENT ON FUNCTION c77_secure_db_run_all_tests() IS 'Master test runner that executes all test suites'; +-- -- Test RBAC integration +-- CREATE OR REPLACE FUNCTION c77_secure_db_test_rbac_integration() +-- RETURNS JSONB +-- LANGUAGE plpgsql AS $$ +-- DECLARE +-- v_rbac_available BOOLEAN; +-- v_test_results JSONB := '{}'; +-- v_tests_passed INTEGER := 0; +-- v_tests_failed INTEGER := 0; +-- v_test_schema TEXT := 'c77_rbac_test_' || extract(epoch from now())::bigint; +-- v_operation_result JSONB; +-- BEGIN +-- -- Check if c77_rbac is available +-- SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = 'c77_rbac') INTO v_rbac_available; +-- +-- IF NOT v_rbac_available THEN +-- RETURN jsonb_build_object( +-- 'test_suite', 'c77_secure_db_rbac_integration', +-- 'rbac_available', false, +-- 'message', 'c77_rbac extension not available - skipping RBAC tests', +-- 'overall_status', 'SKIPPED', +-- 'timestamp', now() +-- ); +-- END IF; +-- +-- -- Create test environment +-- EXECUTE format('CREATE SCHEMA %I', v_test_schema); +-- EXECUTE format(' +-- CREATE TABLE %I.rbac_test_table ( +-- id BIGSERIAL PRIMARY KEY, +-- name TEXT NOT NULL, +-- content_hash TEXT, +-- created_at TIMESTAMPTZ DEFAULT NOW(), +-- updated_at TIMESTAMPTZ DEFAULT NOW() +-- )', v_test_schema); +-- +-- PERFORM c77_secure_db_manage_secure_schemas('add', v_test_schema); +-- +-- -- Set up RBAC test data +-- PERFORM c77_rbac_assign_subject('test_user', 'secure_operator', 'global', 'all'); +-- PERFORM c77_rbac_grant_feature('secure_operator', 'secure_db_insert'); +-- PERFORM c77_rbac_grant_feature('secure_operator', 'secure_db_update'); +-- +-- -- TEST 1: Operation with valid RBAC permissions should succeed +-- BEGIN +-- PERFORM set_config('c77_rbac.external_id', 'test_user', true); +-- +-- SELECT c77_secure_db_operation( +-- jsonb_build_object( +-- 'schema_name', v_test_schema, +-- 'table_name', 'rbac_test_table', +-- 'operation', 'insert', +-- 'data', jsonb_build_object('name', 'rbac_test_record') +-- ), +-- true, -- check_rbac +-- 'secure_db_insert' +-- ) INTO v_operation_result; +-- +-- IF (v_operation_result->>'success')::boolean THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'valid_rbac_permission', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Operation with valid RBAC permission succeeded' +-- ) +-- ); +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'valid_rbac_permission', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Operation failed despite valid RBAC permission: ' || (v_operation_result->>'error') +-- ) +-- ); +-- END IF; +-- EXCEPTION WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'valid_rbac_permission', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- TEST 2: Operation without required RBAC permission should fail +-- BEGIN +-- PERFORM set_config('c77_rbac.external_id', 'test_user', true); +-- +-- SELECT c77_secure_db_operation( +-- jsonb_build_object( +-- 'schema_name', v_test_schema, +-- 'table_name', 'rbac_test_table', +-- 'operation', 'insert', +-- 'data', jsonb_build_object('name', 'unauthorized_record') +-- ), +-- true, -- check_rbac +-- 'secure_db_delete' -- User doesn't have this permission +-- ) INTO v_operation_result; +-- +-- IF NOT (v_operation_result->>'success')::boolean AND (v_operation_result->>'error') LIKE '%Insufficient permissions%' THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'invalid_rbac_permission', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Operation correctly blocked due to insufficient RBAC permissions' +-- ) +-- ); +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'invalid_rbac_permission', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Operation should have been blocked by RBAC but was not' +-- ) +-- ); +-- END IF; +-- EXCEPTION WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'invalid_rbac_permission', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- TEST 3: Operation without user context should fail +-- BEGIN +-- PERFORM set_config('c77_rbac.external_id', '', true); +-- +-- SELECT c77_secure_db_operation( +-- jsonb_build_object( +-- 'schema_name', v_test_schema, +-- 'table_name', 'rbac_test_table', +-- 'operation', 'insert', +-- 'data', jsonb_build_object('name', 'no_context_record') +-- ), +-- true, -- check_rbac +-- 'secure_db_insert' +-- ) INTO v_operation_result; +-- +-- IF NOT (v_operation_result->>'success')::boolean AND (v_operation_result->>'error') LIKE '%no user context%' THEN +-- v_tests_passed := v_tests_passed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'no_user_context', jsonb_build_object( +-- 'status', 'PASSED', +-- 'message', 'Operation correctly blocked due to missing user context' +-- ) +-- ); +-- ELSE +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'no_user_context', jsonb_build_object( +-- 'status', 'FAILED', +-- 'message', 'Operation should have been blocked due to missing user context' +-- ) +-- ); +-- END IF; +-- EXCEPTION WHEN OTHERS THEN +-- v_tests_failed := v_tests_failed + 1; +-- v_test_results := v_test_results || jsonb_build_object( +-- 'no_user_context', jsonb_build_object( +-- 'status', 'ERROR', +-- 'message', SQLERRM +-- ) +-- ); +-- END; +-- +-- -- Cleanup RBAC test data +-- BEGIN +-- PERFORM c77_rbac_revoke_subject_role('test_user', 'secure_operator', 'global', 'all'); +-- PERFORM c77_rbac_revoke_feature('secure_operator', 'secure_db_insert'); +-- PERFORM c77_rbac_revoke_feature('secure_operator', 'secure_db_update'); +-- EXCEPTION WHEN OTHERS THEN +-- -- Ignore cleanup errors +-- NULL; +-- END; +-- +-- -- Cleanup test environment +-- BEGIN +-- PERFORM c77_secure_db_manage_secure_schemas('remove', v_test_schema); +-- EXECUTE format('DROP SCHEMA %I CASCADE', v_test_schema); +-- EXCEPTION WHEN OTHERS THEN +-- v_test_results := v_test_results || jsonb_build_object( +-- 'cleanup_warning', 'Failed to cleanup test schema: ' || SQLERRM +-- ); +-- END; +-- +-- RETURN jsonb_build_object( +-- 'test_suite', 'c77_secure_db_rbac_integration', +-- 'rbac_available', true, +-- 'summary', jsonb_build_object( +-- 'tests_passed', v_tests_passed, +-- 'tests_failed', v_tests_failed, +-- 'total_tests', v_tests_passed + v_tests_failed, +-- 'success_rate', CASE +-- WHEN (v_tests_passed + v_tests_failed) > 0 THEN +-- round((v_tests_passed::numeric / (v_tests_passed + v_tests_failed) * 100), 2) +-- ELSE 0 +-- END +-- ), +-- 'overall_status', CASE +-- WHEN v_tests_failed = 0 THEN 'ALL_TESTS_PASSED' +-- ELSE 'RBAC_INTEGRATION_ISSUES' +-- END, +-- 'test_results', v_test_results, +-- 'timestamp', now() +-- ); +-- END; +-- $$; +-- +-- -- Master test runner - runs all tests +-- CREATE OR REPLACE FUNCTION c77_secure_db_run_all_tests() +-- RETURNS JSONB +-- LANGUAGE plpgsql AS $$ +-- DECLARE +-- v_security_results JSONB; +-- v_rbac_results JSONB; +-- v_health_results JSONB; +-- v_overall_status TEXT := 'ALL_TESTS_PASSED'; +-- BEGIN +-- -- Run security tests +-- v_security_results := c77_secure_db_test_security(); +-- +-- -- Run RBAC integration tests +-- v_rbac_results := c77_secure_db_test_rbac_integration(); +-- +-- -- Run health check +-- v_health_results := c77_secure_db_health_check(); +-- +-- -- Determine overall status +-- IF (v_security_results->>'overall_status') != 'ALL_TESTS_PASSED' THEN +-- v_overall_status := 'SECURITY_ISSUES_DETECTED'; +-- ELSIF (v_rbac_results->>'overall_status') NOT IN ('ALL_TESTS_PASSED', 'SKIPPED') THEN +-- v_overall_status := 'RBAC_INTEGRATION_ISSUES'; +-- END IF; +-- +-- RETURN jsonb_build_object( +-- 'test_suite', 'c77_secure_db_complete', +-- 'version', '2.0', +-- 'overall_status', v_overall_status, +-- 'security_tests', v_security_results, +-- 'rbac_integration_tests', v_rbac_results, +-- 'health_check', v_health_results, +-- 'recommendation', CASE v_overall_status +-- WHEN 'ALL_TESTS_PASSED' THEN 'Extension is ready for production use' +-- WHEN 'SECURITY_ISSUES_DETECTED' THEN 'CRITICAL: Fix security issues before any production use' +-- WHEN 'RBAC_INTEGRATION_ISSUES' THEN 'RBAC integration needs attention - can use without RBAC' +-- ELSE 'Review test results and address issues' +-- END, +-- 'timestamp', now() +-- ); +-- END; +-- $$; +-- +-- -- Grant permissions for test functions +-- GRANT EXECUTE ON FUNCTION c77_secure_db_test_security() TO c77_secure_db_admin; +-- GRANT EXECUTE ON FUNCTION c77_secure_db_test_rbac_integration() TO c77_secure_db_admin; +-- GRANT EXECUTE ON FUNCTION c77_secure_db_run_all_tests() TO c77_secure_db_admin; +-- +-- COMMENT ON FUNCTION c77_secure_db_test_security() IS 'Comprehensive security test suite for the extension'; +-- COMMENT ON FUNCTION c77_secure_db_test_rbac_integration() IS 'Tests integration with c77_rbac extension'; +-- COMMENT ON FUNCTION c77_secure_db_run_all_tests() IS 'Master test runner that executes all test suites'; \echo 'c77_secure_db extension v2.0 loaded successfully!' diff --git a/c77_secure_db.control b/c77_secure_db.control index 48792f3..67e989d 100644 --- a/c77_secure_db.control +++ b/c77_secure_db.control @@ -3,4 +3,4 @@ comment = 'Secure database operations with tamper detection and transaction cont default_version = '1.0' relocatable = false requires = 'pgcrypto' -suggests = 'c77_rbac' \ No newline at end of file +# suggests = 'c77_rbac' \ No newline at end of file