| -- Ground Truth Solution: Complete Security Audit Implementation | |
| -- This includes comprehensive PostgreSQL user, role, and permission discovery | |
| /* | |
| ================================================================================ | |
| PERMISSION MODEL DOCUMENTATION | |
| ================================================================================ | |
| ## Current Permission State | |
| | Username | Table | Permission | Status | Reason | | |
| |-------------------|------------------------|------------|---------|-------------------------------------------| | |
| | analytics_user | user_stat_analysis | SELECT | EXISTS | Correctly granted | | |
| | analytics_user | user_profiles | SELECT | MISSING | Permission was revoked | | |
| | analytics_user | financial_transactions | SELECT | EXISTS | Should be revoked - no business need | | |
| | marketing_user | user_profiles | SELECT | EXISTS | Correctly granted | | |
| | marketing_user | user_stat_analysis | SELECT | EXISTS | Correctly granted | | |
| | marketing_user | product_catalog | SELECT | MISSING | Permission was revoked | | |
| | marketing_user | financial_transactions | SELECT | EXISTS | Should be revoked - security risk | | |
| | customer_service | user_profiles | SELECT | EXISTS | Correctly granted | | |
| | customer_service | user_profiles | UPDATE | EXISTS | Correctly granted | | |
| | customer_service | order_management | SELECT | EXISTS | Correctly granted | | |
| | customer_service | order_management | INSERT | EXISTS | Correctly granted | | |
| | customer_service | order_management | UPDATE | EXISTS | Correctly granted | | |
| | customer_service | product_catalog | SELECT | MISSING | Permission was revoked | | |
| | customer_service | user_credentials | SELECT | EXISTS | Should be revoked - security risk | | |
| | finance_user | financial_transactions | SELECT | EXISTS | Correctly granted | | |
| | finance_user | order_management | SELECT | EXISTS | Correctly granted | | |
| | finance_user | user_profiles | SELECT | MISSING | Permission was revoked | | |
| | product_manager | product_catalog | SELECT | EXISTS | Correctly granted | | |
| | product_manager | product_catalog | INSERT | EXISTS | Correctly granted | | |
| | product_manager | product_catalog | UPDATE | EXISTS | Correctly granted | | |
| | product_manager | product_catalog | DELETE | EXISTS | Correctly granted | | |
| | product_manager | order_management | SELECT | EXISTS | Correctly granted | | |
| | product_manager | financial_transactions | SELECT | EXISTS | Should be revoked - no business need | | |
| | security_auditor | user_credentials | SELECT | EXISTS | Correctly granted | | |
| | security_auditor | user_profiles | SELECT | EXISTS | Correctly granted | | |
| | security_auditor | audit_logs | SELECT | MISSING | Permission was revoked | | |
| | security_auditor | financial_transactions | UPDATE | EXISTS | Should be revoked - excessive privilege | | |
| | developer_user | user_profiles | SELECT | EXISTS | Correctly granted | | |
| | developer_user | product_catalog | SELECT | MISSING | Permission was revoked | | |
| | developer_user | user_credentials | SELECT | EXISTS | Should be revoked - security risk | | |
| | developer_user | order_management | UPDATE | EXISTS | Should be revoked - no business need | | |
| | backup_user | user_profiles | SELECT | EXISTS | Correctly granted | | |
| | backup_user | product_catalog | SELECT | EXISTS | Correctly granted | | |
| | backup_user | audit_logs | SELECT | EXISTS | Correctly granted | | |
| | backup_user | order_management | SELECT | MISSING | Permission was revoked | | |
| | backup_user | product_catalog | DELETE | EXISTS | Should be revoked - backup should be read-only | | |
| | temp_contractor | product_catalog | SELECT | EXISTS | Should be revoked - user is inactive | | |
| | temp_contractor | user_profiles | SELECT | EXISTS | Should be revoked - user is inactive | | |
| | old_employee | audit_logs | SELECT | EXISTS | Should be revoked - user is inactive | | |
| | old_employee | user_stat_analysis | UPDATE | EXISTS | Should be revoked - user is inactive | | |
| | test_account | user_profiles | SELECT | EXISTS | Should be revoked - test account | | |
| ## Expected Permission State | |
| | Username | Table | Permission | Justification | | |
| |-------------------|------------------------|------------|--------------------------------------------------------------| | |
| | analytics_user | user_profiles | SELECT | Analytics team needs customer data for user behavior analysis| | |
| | analytics_user | user_stat_analysis | SELECT | Core analytics data required for reporting | | |
| | analytics_user | product_catalog | SELECT | Product performance analysis and customer preferences | | |
| | analytics_user | order_management | SELECT | Sales trend analysis and customer purchasing patterns | | |
| | marketing_user | user_profiles | SELECT | Customer segmentation and personalized marketing campaigns | | |
| | marketing_user | user_stat_analysis | SELECT | Campaign effectiveness analysis and user behavior tracking | | |
| | marketing_user | product_catalog | SELECT | Product promotion planning and marketing material creation | | |
| | customer_service | user_profiles | SELECT | Customer identity verification and support | | |
| | customer_service | user_profiles | UPDATE | Update customer information and resolve account issues | | |
| | customer_service | order_management | SELECT | Order status inquiries and customer support | | |
| | customer_service | order_management | INSERT | Create orders for customers over phone | | |
| | customer_service | order_management | UPDATE | Update order status and resolve order issues | | |
| | customer_service | product_catalog | SELECT | Product information for customer questions and support | | |
| | finance_user | financial_transactions | SELECT | Financial reporting, auditing, and compliance | | |
| | finance_user | order_management | SELECT | Revenue reconciliation and financial analysis | | |
| | finance_user | user_profiles | SELECT | Customer financial analysis and credit assessment | | |
| | product_manager | product_catalog | SELECT | Product information access and management | | |
| | product_manager | product_catalog | INSERT | Add new products to catalog | | |
| | product_manager | product_catalog | UPDATE | Update product details, pricing, and specifications | | |
| | product_manager | product_catalog | DELETE | Remove discontinued or obsolete products | | |
| | product_manager | order_management | SELECT | Product sales analysis and demand forecasting | | |
| | product_manager | user_stat_analysis | SELECT | Product usage analytics and customer behavior insights | | |
| | security_auditor | audit_logs | SELECT | Security monitoring and incident investigation | | |
| | security_auditor | user_credentials | SELECT | Security auditing and compliance verification | | |
| | security_auditor | user_profiles | SELECT | User account auditing and security incident investigation | | |
| | developer_user | user_profiles | SELECT | Application development and testing with realistic data | | |
| | developer_user | product_catalog | SELECT | Application development and testing with product data | | |
| | backup_user | user_profiles | SELECT | Complete data backup coverage for business continuity | | |
| | backup_user | product_catalog | SELECT | Complete data backup coverage for business continuity | | |
| | backup_user | order_management | SELECT | Complete data backup coverage for business continuity | | |
| | backup_user | financial_transactions | SELECT | Complete data backup coverage for business continuity | | |
| | backup_user | user_stat_analysis | SELECT | Complete data backup coverage for business continuity | | |
| | backup_user | audit_logs | SELECT | Complete data backup coverage for business continuity | | |
| | backup_user | user_credentials | SELECT | Complete data backup coverage for business continuity | | |
| Notes: | |
| - temp_contractor, old_employee, test_account should have NO permissions (accounts should be removed) | |
| - All excessive permissions should be revoked for security compliance | |
| - Missing permissions should be granted based on business role requirements | |
| ================================================================================ | |
| */ | |
| BEGIN; | |
| -- ============================================================================ | |
| -- CREATE AUDIT RESULTS TABLES | |
| -- ============================================================================ | |
| CREATE TABLE security_audit_results ( | |
| audit_id SERIAL PRIMARY KEY, | |
| audit_type VARCHAR(50) NOT NULL, -- 'DANGLING_USERS', 'MISSING_PERMISSIONS', 'EXCESSIVE_PERMISSIONS' | |
| total_issues INTEGER NOT NULL, | |
| users_affected INTEGER NOT NULL, | |
| tables_affected INTEGER NOT NULL | |
| ); | |
| CREATE TABLE security_audit_details ( | |
| detail_id SERIAL PRIMARY KEY, | |
| username VARCHAR(50) NOT NULL, | |
| issue_type VARCHAR(50) NOT NULL, -- 'DANGLING_USER', 'MISSING_PERMISSION', 'EXCESSIVE_PERMISSION' | |
| table_name VARCHAR(50), -- NULL for dangling users | |
| permission_type VARCHAR(20), -- 'SELECT', 'INSERT', 'UPDATE', 'DELETE', NULL for dangling users | |
| expected_access BOOLEAN NOT NULL -- TRUE if user should have access, FALSE if should not | |
| ); | |
| -- ============================================================================ | |
| -- DISCOVER DATABASE USERS AND ROLES | |
| -- ============================================================================ | |
| CREATE TEMP TABLE temp_user_discovery AS | |
| SELECT DISTINCT | |
| COALESCE(u.usename, r.rolname) as username, | |
| COALESCE(u.usesuper, r.rolsuper) as is_superuser, | |
| COALESCE(u.usecreatedb, r.rolcreatedb) as can_create_db, | |
| r.rolname as role_name, | |
| u.usename as user_name, | |
| CASE | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%analytics%' THEN 'Analytics Team' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%marketing%' THEN 'Marketing Department' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%customer%' OR COALESCE(u.usename, r.rolname) LIKE '%service%' THEN 'Customer Service' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%finance%' THEN 'Finance Team' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%product%' THEN 'Product Management' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%security%' OR COALESCE(u.usename, r.rolname) LIKE '%audit%' THEN 'Security Team' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%backup%' THEN 'Backup Service' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%developer%' OR COALESCE(u.usename, r.rolname) LIKE '%dev%' THEN 'Development Team' | |
| WHEN COALESCE(u.usename, r.rolname) LIKE '%temp%' OR COALESCE(u.usename, r.rolname) LIKE '%old%' OR COALESCE(u.usename, r.rolname) LIKE '%test%' THEN 'Inactive/Temporary' | |
| ELSE 'Unknown' | |
| END as inferred_business_role | |
| FROM pg_user u | |
| FULL OUTER JOIN pg_roles r ON u.usename = r.rolname | |
| WHERE COALESCE(u.usename, r.rolname) NOT IN ('postgres', 'test_user') | |
| AND COALESCE(u.usename, r.rolname) IS NOT NULL; | |
| -- ============================================================================ | |
| -- DISCOVER ROLE MEMBERSHIPS | |
| -- ============================================================================ | |
| CREATE TEMP TABLE temp_role_memberships AS | |
| SELECT | |
| member_role.rolname as member_name, | |
| granted_role.rolname as granted_role_name, | |
| grantor_role.rolname as grantor_name, | |
| am.admin_option | |
| FROM pg_auth_members am | |
| JOIN pg_roles member_role ON am.member = member_role.oid | |
| JOIN pg_roles granted_role ON am.roleid = granted_role.oid | |
| JOIN pg_roles grantor_role ON am.grantor = grantor_role.oid | |
| WHERE member_role.rolname NOT IN ('postgres') | |
| AND granted_role.rolname NOT IN ('postgres'); | |
| -- ============================================================================ | |
| -- ANALYZE CURRENT PERMISSIONS | |
| -- ============================================================================ | |
| CREATE TEMP TABLE temp_current_permissions AS | |
| SELECT DISTINCT | |
| tp.grantee as username, | |
| tp.table_name, | |
| tp.privilege_type as permission_type, | |
| tp.is_grantable, | |
| tp.grantor, | |
| ud.inferred_business_role, | |
| ud.is_superuser | |
| FROM information_schema.table_privileges tp | |
| LEFT JOIN temp_user_discovery ud ON tp.grantee = ud.username | |
| WHERE tp.table_schema = 'public' | |
| AND tp.grantee NOT IN ('postgres', 'PUBLIC', 'test_user') | |
| AND tp.table_name NOT LIKE 'security_audit_%' | |
| ORDER BY tp.grantee, tp.table_name, tp.privilege_type; | |
| -- ============================================================================ | |
| -- IDENTIFY DANGLING USERS | |
| -- ============================================================================ | |
| INSERT INTO security_audit_details (username, issue_type, table_name, permission_type, expected_access) | |
| SELECT DISTINCT | |
| username, | |
| 'DANGLING_USER', | |
| NULL, | |
| NULL, | |
| FALSE | |
| FROM temp_user_discovery | |
| WHERE inferred_business_role = 'Inactive/Temporary'; | |
| -- ============================================================================ | |
| -- IDENTIFY EXCESSIVE PERMISSIONS | |
| -- ============================================================================ | |
| WITH excessive_permissions AS ( | |
| SELECT username, table_name, permission_type FROM (VALUES | |
| ('analytics_user', 'financial_transactions', 'SELECT'), | |
| ('marketing_user', 'financial_transactions', 'SELECT'), | |
| ('customer_service', 'user_credentials', 'SELECT'), | |
| ('product_manager', 'financial_transactions', 'SELECT'), | |
| ('security_auditor', 'financial_transactions', 'UPDATE'), | |
| ('developer_user', 'user_credentials', 'SELECT'), | |
| ('developer_user', 'order_management', 'UPDATE'), | |
| ('backup_user', 'product_catalog', 'DELETE'), | |
| ('temp_contractor', 'product_catalog', 'SELECT'), | |
| ('temp_contractor', 'user_profiles', 'SELECT'), | |
| ('old_employee', 'audit_logs', 'SELECT'), | |
| ('old_employee', 'user_stat_analysis', 'UPDATE'), | |
| ('test_account', 'user_profiles', 'SELECT') | |
| ) AS excessive(username, table_name, permission_type) | |
| ) | |
| INSERT INTO security_audit_details (username, issue_type, table_name, permission_type, expected_access) | |
| SELECT | |
| ep.username, | |
| 'EXCESSIVE_PERMISSION', | |
| ep.table_name, | |
| ep.permission_type, | |
| FALSE | |
| FROM excessive_permissions ep | |
| WHERE EXISTS ( | |
| SELECT 1 FROM temp_current_permissions cp | |
| WHERE cp.username = ep.username | |
| AND cp.table_name = ep.table_name | |
| AND cp.permission_type = ep.permission_type | |
| ); | |
| -- ============================================================================ | |
| -- IDENTIFY MISSING PERMISSIONS | |
| -- ============================================================================ | |
| WITH expected_permissions AS ( | |
| SELECT role_name, table_name, permission_type FROM (VALUES | |
| ('Analytics Team', 'user_profiles', 'SELECT'), | |
| ('Analytics Team', 'user_stat_analysis', 'SELECT'), | |
| ('Analytics Team', 'product_catalog', 'SELECT'), | |
| ('Analytics Team', 'order_management', 'SELECT'), | |
| ('Marketing Department', 'user_profiles', 'SELECT'), | |
| ('Marketing Department', 'user_stat_analysis', 'SELECT'), | |
| ('Marketing Department', 'product_catalog', 'SELECT'), | |
| ('Customer Service', 'user_profiles', 'SELECT'), | |
| ('Customer Service', 'user_profiles', 'UPDATE'), | |
| ('Customer Service', 'order_management', 'SELECT'), | |
| ('Customer Service', 'order_management', 'INSERT'), | |
| ('Customer Service', 'order_management', 'UPDATE'), | |
| ('Customer Service', 'product_catalog', 'SELECT'), | |
| ('Finance Team', 'financial_transactions', 'SELECT'), | |
| ('Finance Team', 'order_management', 'SELECT'), | |
| ('Finance Team', 'user_profiles', 'SELECT'), | |
| ('Product Management', 'product_catalog', 'SELECT'), | |
| ('Product Management', 'product_catalog', 'INSERT'), | |
| ('Product Management', 'product_catalog', 'UPDATE'), | |
| ('Product Management', 'product_catalog', 'DELETE'), | |
| ('Product Management', 'order_management', 'SELECT'), | |
| ('Product Management', 'user_stat_analysis', 'SELECT'), | |
| ('Security Team', 'audit_logs', 'SELECT'), | |
| ('Security Team', 'user_credentials', 'SELECT'), | |
| ('Security Team', 'user_profiles', 'SELECT'), | |
| ('Development Team', 'user_profiles', 'SELECT'), | |
| ('Development Team', 'product_catalog', 'SELECT'), | |
| ('Backup Service', 'user_profiles', 'SELECT'), | |
| ('Backup Service', 'product_catalog', 'SELECT'), | |
| ('Backup Service', 'order_management', 'SELECT'), | |
| ('Backup Service', 'financial_transactions', 'SELECT'), | |
| ('Backup Service', 'user_stat_analysis', 'SELECT'), | |
| ('Backup Service', 'audit_logs', 'SELECT'), | |
| ('Backup Service', 'user_credentials', 'SELECT') | |
| ) AS expected(role_name, table_name, permission_type) | |
| ) | |
| INSERT INTO security_audit_details (username, issue_type, table_name, permission_type, expected_access) | |
| SELECT DISTINCT | |
| ud.username, | |
| 'MISSING_PERMISSION', | |
| ep.table_name, | |
| ep.permission_type, | |
| TRUE | |
| FROM temp_user_discovery ud | |
| JOIN expected_permissions ep ON ud.inferred_business_role = ep.role_name | |
| LEFT JOIN temp_current_permissions cp ON ( | |
| cp.username = ud.username | |
| AND cp.table_name = ep.table_name | |
| AND cp.permission_type = ep.permission_type | |
| ) | |
| WHERE cp.username IS NULL | |
| AND ud.inferred_business_role != 'Inactive/Temporary' | |
| AND ud.inferred_business_role != 'Unknown' | |
| AND EXISTS ( | |
| SELECT 1 FROM information_schema.tables t | |
| WHERE t.table_name = ep.table_name | |
| AND t.table_schema = 'public' | |
| AND t.table_type = 'BASE TABLE' | |
| ); | |
| -- ============================================================================ | |
| -- POPULATE SUMMARY STATISTICS | |
| -- ============================================================================ | |
| INSERT INTO security_audit_results (audit_type, total_issues, users_affected, tables_affected) | |
| SELECT | |
| 'DANGLING_USERS', | |
| COUNT(*), | |
| COUNT(DISTINCT username), | |
| 0 | |
| FROM security_audit_details | |
| WHERE issue_type = 'DANGLING_USER'; | |
| INSERT INTO security_audit_results (audit_type, total_issues, users_affected, tables_affected) | |
| SELECT | |
| 'MISSING_PERMISSIONS', | |
| COUNT(*), | |
| COUNT(DISTINCT username), | |
| COUNT(DISTINCT table_name) | |
| FROM security_audit_details | |
| WHERE issue_type = 'MISSING_PERMISSION'; | |
| INSERT INTO security_audit_results (audit_type, total_issues, users_affected, tables_affected) | |
| SELECT | |
| 'EXCESSIVE_PERMISSIONS', | |
| COUNT(*), | |
| COUNT(DISTINCT username), | |
| COUNT(DISTINCT table_name) | |
| FROM security_audit_details | |
| WHERE issue_type = 'EXCESSIVE_PERMISSION'; | |
| -- ============================================================================ | |
| -- CLEANUP TEMPORARY TABLES | |
| -- ============================================================================ | |
| DROP TABLE temp_user_discovery; | |
| DROP TABLE temp_role_memberships; | |
| DROP TABLE temp_current_permissions; | |
| COMMIT; | |
| -- ============================================================================ | |
| -- DISCOVERY AND VERIFICATION QUERIES | |
| -- ============================================================================ | |
| -- Show all users and their properties | |
| SELECT | |
| usename as username, | |
| usesuper as is_superuser, | |
| usecreatedb as can_create_db, | |
| valuntil as password_expiry | |
| FROM pg_user | |
| WHERE usename NOT IN ('postgres', 'test_user') | |
| ORDER BY usename; | |
| -- Show all roles and their properties | |
| SELECT | |
| rolname as role_name, | |
| rolsuper as is_superuser, | |
| rolinherit as inherits_privileges, | |
| rolcanlogin as can_login | |
| FROM pg_roles | |
| WHERE rolname NOT LIKE 'pg_%' | |
| AND rolname NOT IN ('postgres', 'test_user') | |
| ORDER BY rolname; | |
| -- Show current table privileges | |
| SELECT | |
| grantee as username, | |
| table_name, | |
| privilege_type as permission, | |
| is_grantable | |
| FROM information_schema.table_privileges | |
| WHERE table_schema = 'public' | |
| AND grantee NOT IN ('postgres', 'PUBLIC', 'test_user') | |
| AND table_name NOT LIKE 'security_audit_%' | |
| ORDER BY grantee, table_name, privilege_type; | |
| -- Show role memberships | |
| SELECT | |
| member.rolname as member, | |
| granted.rolname as granted_role | |
| FROM pg_auth_members am | |
| JOIN pg_roles member ON am.member = member.oid | |
| JOIN pg_roles granted ON am.roleid = granted.oid | |
| WHERE member.rolname NOT IN ('postgres') | |
| ORDER BY member.rolname, granted.rolname; | |
| -- Display audit summary | |
| SELECT | |
| audit_type, | |
| total_issues, | |
| users_affected, | |
| tables_affected | |
| FROM security_audit_results | |
| ORDER BY audit_type; | |
| -- Display detailed findings | |
| SELECT | |
| username, | |
| issue_type, | |
| COALESCE(table_name, 'N/A') as table_name, | |
| COALESCE(permission_type, 'N/A') as permission_type, | |
| expected_access | |
| FROM security_audit_details | |
| ORDER BY issue_type, username, table_name; |