mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-03 16:38:35 +08:00
* Use a custom query to find user db privileges on tables to avoid the "grantor" filter condition in the information_schema.tables_privileges view. This fixes the cases where the grantor for a privilege is set to the table owner rather than the user (teleport) who issued the grant. Most notably, this happens when a superuser grants privileges on a table they do not own to a user. * Grant USAGE on schemas that contain tables where we intend to grant table privileges. This is necessary to use the table privileges we grant. * Wrap all remaining plpgsql procedure creation/calls with retries. * Add a db permissions e2e test for RDS * Expand e2e tests to test with and without a superuser db admin * Significantly speed up the RDS e2e tests by wrapping EventuallyWithT in a helper func that tries the condition func immediately rather than waiting for the first tick duration.
69 lines
2.7 KiB
PL/PgSQL
69 lines
2.7 KiB
PL/PgSQL
CREATE OR REPLACE PROCEDURE pg_temp.teleport_remove_permissions(username VARCHAR)
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
row_data RECORD;
|
|
BEGIN
|
|
-- Check active connections.
|
|
IF EXISTS (SELECT usename FROM pg_stat_activity WHERE usename = username AND datname = current_database()) THEN
|
|
RAISE NOTICE 'User has active connections to current database';
|
|
ELSE
|
|
-- create temp table with ON COMMIT DROP so that this procedure can be
|
|
-- retried within a single session without getting an error that the
|
|
-- table already exists.
|
|
CREATE TEMPORARY TABLE cur_perms ON COMMIT DROP AS (
|
|
SELECT DISTINCT
|
|
pg_namespace.nspname::information_schema.sql_identifier AS table_schema,
|
|
obj.relname::information_schema.sql_identifier AS table_name
|
|
FROM
|
|
pg_class as obj
|
|
INNER JOIN
|
|
pg_namespace ON obj.relnamespace = pg_namespace.oid
|
|
INNER JOIN LATERAL
|
|
aclexplode(COALESCE(obj.relacl, acldefault('r'::"char", obj.relowner))) AS acl ON true
|
|
INNER JOIN
|
|
pg_roles AS grantee ON acl.grantee = grantee.oid
|
|
WHERE
|
|
-- only objects that are one of r=ordinary table, v=view, f=foreign table, p=partitioned table.
|
|
(obj.relkind = ANY (ARRAY['r', 'v', 'f', 'p']))
|
|
-- only privileges we support provisioning.
|
|
AND (acl.privilege_type = ANY (ARRAY['DELETE'::text, 'INSERT'::text, 'REFERENCES'::text, 'SELECT'::text, 'TRUNCATE'::text, 'TRIGGER'::text, 'UPDATE'::text]))
|
|
-- only the user in we are revoking permissions from.
|
|
AND grantee.rolname = username
|
|
);
|
|
|
|
-- Loop through and revoke all table permissions
|
|
FOR row_data IN (
|
|
SELECT
|
|
table_schema,
|
|
table_name
|
|
FROM
|
|
cur_perms
|
|
)
|
|
LOOP
|
|
EXECUTE format('REVOKE ALL PRIVILEGES ON %I.%I FROM %I',
|
|
row_data.table_schema,
|
|
row_data.table_name,
|
|
username
|
|
);
|
|
END LOOP;
|
|
|
|
-- We implicitly grant USAGE on any schema for which we make table privilege grants.
|
|
-- Loop through and revoke all schema USAGE.
|
|
-- See: https://github.com/gravitational/teleport/issues/51851
|
|
FOR row_data IN (
|
|
SELECT DISTINCT
|
|
table_schema
|
|
FROM
|
|
cur_perms
|
|
)
|
|
LOOP
|
|
EXECUTE format('REVOKE USAGE ON SCHEMA %I FROM %I',
|
|
row_data.table_schema,
|
|
username
|
|
);
|
|
END LOOP;
|
|
END IF;
|
|
END;
|
|
$$;
|