File: 10_acl.sql

package info (click to toggle)
powa-archivist 5.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,224 kB
  • sloc: sql: 40,620; ansic: 495; makefile: 34; sh: 4
file content (153 lines) | stat: -rw-r--r-- 5,676 bytes parent folder | download | duplicates (3)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
-- Check the relations for which powa_admin is missing ACL

CREATE FUNCTION has_table_or_seq_privilege(relkind "char", rolname text,
                                           relid oid, priv text)
RETURNS bool
AS $$
BEGIN
    IF relkind = 'S' THEN
        RETURN has_sequence_privilege(rolname, relid, priv);
    ELSE
        RETURN has_table_privilege(rolname, relid, priv);
    END IF;
END;
$$ LANGUAGE plpgsql;

CREATE FUNCTION check_has_privilege(rolname text,
                                    tbl_priv text[], seq_priv text[])
RETURNS TABLE (powa_role text, relname name, relkind "char", priv text)
AS $$
    WITH ext AS (
        SELECT c.oid, c.relname, c.relkind
        FROM pg_depend d
        JOIN pg_extension e ON d.refclassid = 'pg_extension'::regclass
            AND e.oid = d.refobjid
            AND e.extname = 'powa'
        JOIN pg_class c ON d.classid = 'pg_class'::regclass
            AND c.oid = d.objid
    ),
    acls(priv, isseq) AS (
        SELECT unnest(tbl_priv), false
        UNION ALL
        SELECT unnest(seq_priv), true
    )
    SELECT rolname AS powa_role, relname, relkind, priv
    FROM ext
    JOIN acls ON acls.isseq = (ext.relkind = 'S')
    WHERE NOT has_table_or_seq_privilege(relkind, rolname, ext.oid, priv)
    ORDER BY relname, priv;
$$ LANGUAGE sql;

CREATE FUNCTION check_has_not_privilege(rolname text,
                                        tbl_priv text[], seq_priv text[])
RETURNS TABLE (powa_role text, relname name, relkind "char", priv text)
AS $$
    WITH ext AS (
        SELECT c.oid, c.relname, c.relkind
        FROM pg_depend d
        JOIN pg_extension e ON d.refclassid = 'pg_extension'::regclass
            AND e.oid = d.refobjid
            AND e.extname = 'powa'
        JOIN pg_class c ON d.classid = 'pg_class'::regclass
            AND c.oid = d.objid
    ),
    acls(priv, isseq) AS (
        SELECT unnest(tbl_priv), false
        UNION ALL
        SELECT unnest(seq_priv), true
    )
    SELECT rolname AS powa_role, relname, relkind, priv
    FROM ext
    JOIN acls ON acls.isseq = (ext.relkind = 'S')
    WHERE has_table_or_seq_privilege(relkind, rolname, ext.oid, priv)
    ORDER BY relname, priv;
$$ LANGUAGE sql;


-- powa_admin should have all privileges on all relations
SELECT powa_role, relname, priv
FROM check_has_privilege('powa_admin',
    array ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES',
           'TRIGGER'],
    array ['USAGE', 'SELECT', 'UPDATE']);

-- powa_read_all_data should have SELECT privilege on all relation except
 -- *_src_tmp tables and sequences
SELECT powa_role, relname, priv
FROM check_has_privilege('powa_read_all_data',
    array ['SELECT'],
    array []::text[]);

-- powa_read_all_data should not have non-SELECT privilege on any table, and no
-- privilege on sequences
SELECT powa_role, relname, priv
FROM check_has_not_privilege('powa_read_all_data',
    array ['INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'],
    array ['USAGE', 'SELECT', 'UPDATE']);

-- powa_read_all_metrics should be the same as powa_read_all_data except that
-- it can't acceess any pg_qualstats related table
SELECT powa_role, relname, priv
FROM check_has_privilege('powa_read_all_metrics',
    array ['SELECT'],
    array []::text[]);

SELECT powa_role, relname, priv
FROM check_has_not_privilege('powa_read_all_metrics',
    array ['INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'],
    array ['USAGE', 'SELECT', 'UPDATE']);

-- powa_write_all_data should have SELECT/INSERT/UPDATE/DELETE/TRUNCATE
-- privileges on all relations (and all privileges on sequences)
SELECT powa_role, relname, priv
FROM check_has_privilege('powa_write_all_data',
    array ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE'],
    array ['USAGE', 'SELECT', 'UPDATE']);

-- powa_write_all_data should not have TRIGGER/REFERENCES privileges on any
-- relations
SELECT powa_role, relname, priv
FROM check_has_not_privilege('powa_write_all_data',
    array ['TRIGGER', 'REFERENCES'],
    array []::text[]);

-- powa_snapshot should have SELECT/INSERT/UPDATE/DELETE/TRUNCATE
-- privileges on all metric-related relations (and all privileges on sequences)
-- only
SELECT powa_role, relname, relkind, array_agg(priv)
FROM check_has_privilege('powa_snapshot',
    array ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE'],
    array ['USAGE', 'SELECT', 'UPDATE'])
GROUP BY 1, 2, 3
ORDER BY 1, 2, 3;

-- powa_snapshot should not have TRIGGER/REFERENCES privileges on any relations
SELECT powa_role, relname, priv
FROM check_has_not_privilege('powa_snapshot',
    array ['TRIGGER', 'REFERENCES'],
    array []::text[]);

-- and try to detect any unexpected GRANT on powa_snapshot, as any newly
-- created table will have too many privileges granted unless explicitly
-- handled
SELECT DISTINCT powa_role, relname
FROM check_has_not_privilege('powa_snapshot',
    array ['INSERT', 'UPDATE', 'DELETE', 'TRUNCATE'],
    array ['USAGE', 'SELECT', 'UPDATE'])
WHERE relkind != 'v'
AND relname NOT LIKE '%history'
AND relname NOT LIKE '%history\_db'
AND relname NOT LIKE '%history\_current'
AND relname NOT LIKE '%history\_current\_db'
AND relname NOT LIKE '%src\_tmp'
AND relname NOT LIKE 'powa\_catalog\_%'
AND relname NOT LIKE '%qualstats%'
AND relname NOT LIKE '%kcache%'
AND relname NOT IN ('powa_databases', 'powa_snapshot_metas', 'powa_statements');

-- powa_signal_backend should not have any privilege on any relation
SELECT powa_role, relname, priv
FROM check_has_not_privilege('powa_signal_backend',
    array ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES',
           'TRIGGER'],
    array ['USAGE', 'SELECT', 'UPDATE']);