-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2.2-apply_rules.sql
More file actions
118 lines (96 loc) · 4.1 KB
/
2.2-apply_rules.sql
File metadata and controls
118 lines (96 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*============================================================================================
* Star this project if it helped you! | Deixe uma estrela se te ajudou!
* Contributions welcome! | Contribuições são bem-vindas!
============================================================================================*/
-- POLICY MANAGEMENT - APPLY RULES
--
-- This file contains:
-- - Function to synchronize audit policies with database triggers
-- - Reads configuration from audit.log_control
-- - Dynamically creates/updates triggers on target tables
-- - Validates and marks policies as applied
--============================================================================================
-- Reads audit policies from log_control and synchronizes triggers on all tables
CREATE OR REPLACE FUNCTION audit.apply_rules()
RETURNS text
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
DECLARE
r_schema RECORD;
r_table RECORD;
v_table_full TEXT;
v_events TEXT;
v_sql TEXT;
v_counter INT := 0;
BEGIN
/*===========================================================================
* Project: postgres-audit-log
* Repository: https://github.com/richwrd/postgres-audit-log
* Author: richwrd (Eduardo Richard)
* Star this project if it helped you!
=============================================================================*/
-- Check for pending policies
IF NOT EXISTS (SELECT 1 FROM audit.log_control WHERE validated = FALSE) THEN
RETURN '[OK] All policies are up to date.';
END IF;
-- Iterate through pending schemas
FOR r_schema IN (
SELECT id, schema_name, log_insert, log_update, log_delete
FROM audit.log_control
WHERE validated = FALSE
)
LOOP
-- Safety: Prevent circular logging
IF r_schema.schema_name = 'audit' THEN
RAISE WARNING '[!] Security Alert: Policy for schema "audit" ignored.';
UPDATE audit.log_control SET validated = TRUE WHERE id = r_schema.id;
CONTINUE;
END IF;
RAISE NOTICE '[->] Processing Policy for Schema: % ...', r_schema.schema_name;
-- Build Event String
v_events := '';
IF r_schema.log_insert THEN v_events := 'INSERT'; END IF;
IF r_schema.log_update THEN
IF v_events != '' THEN v_events := v_events || ' OR '; END IF;
v_events := v_events || 'UPDATE';
END IF;
IF r_schema.log_delete THEN
IF v_events != '' THEN v_events := v_events || ' OR '; END IF;
v_events := v_events || 'DELETE';
END IF;
-- Apply to Tables
FOR r_table IN (
SELECT tablename
FROM pg_catalog.pg_tables
WHERE schemaname = r_schema.schema_name
)
LOOP
v_table_full := quote_ident(r_schema.schema_name) || '.' || quote_ident(r_table.tablename);
-- Clean up old trigger
EXECUTE format('DROP TRIGGER IF EXISTS audit_dml_trigger ON %s', v_table_full);
-- Create new trigger (if events exist)
IF v_events != '' THEN
v_sql := format(
'CREATE TRIGGER audit_dml_trigger ' ||
'AFTER %s ON %s ' ||
'FOR EACH ROW EXECUTE FUNCTION audit.record_change()',
v_events, v_table_full
);
EXECUTE v_sql;
END IF;
v_counter := v_counter + 1;
END LOOP;
-- Feedback
IF v_events = '' THEN
RAISE NOTICE '[X] Audit removed for schema: %', r_schema.schema_name;
ELSE
RAISE NOTICE '[OK] Audit active (%s) for schema: %', v_events, r_schema.schema_name;
END IF;
-- Mark as Validated
UPDATE audit.log_control SET validated = TRUE WHERE id = r_schema.id;
END LOOP;
RETURN format('[OK] Policies successfully applied to %s tables.', v_counter);
END;
$function$;
COMMENT ON FUNCTION audit.apply_rules() IS 'Synchronizes audit policies from log_control table and creates/updates triggers on target tables';