PostgreSQL: permission denied to COPY to or from an external program, even after Grant pg_execute_server_program
0
votes
1
answer
209
views
Running
Copy test(id, name) From Program 'zcat /tmp/test.csv.gz' CSV Header;
fails with:
SQL Error : ERROR: permission denied to COPY to or from an external program
Detail: Only roles with privileges of the "pg_execute_server_program" role may COPY to or from an external program.
even though it's been granted to the current user:
SELECT current_user;
-- report_mgr
SELECT rolname FROM pg_roles WHERE
pg_has_role(current_user, oid, 'member');
|rolname |
|-------------------------|
|pg_execute_server_program|
|report_mgr |
Running on the official postgres:16 Docker image (PostgreSQL 16.2 (Debian 16.2-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
).
The query works fine with the postgres user, both in psql and SQLModel/SQLAlchemy, but haven't been able to get it to work for report_mgr. The file is readable, though that's irrelevant as the command is never executed. The user was created like this:
CREATE OR REPLACE FUNCTION grant_on_schemas(
role text,
schemas text[],
privilege text default 'select')
RETURNS SETOF text AS $$
DECLARE
query text;
schema text;
BEGIN
query := format('GRANT CONNECT ON DATABASE %I TO %s;', (SELECT current_database()), role);
-- Add query to result table as a new row, then execute
Return Next query;
Execute query;
FOREACH schema IN ARRAY schemas LOOP
If privilege = 'select' Then
-- Grant select
query := format('GRANT USAGE ON SCHEMA %I TO %s;', schema, role);
Return Next query;
Execute query;
query := format('GRANT SELECT ON ALL TABLES IN SCHEMA %I TO %s;', schema, role);
Return Next query;
Execute query;
query := format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT SELECT ON TABLES TO %s;', schema, role);
Return Next query;
Execute query;
Elsif privilege = 'all' Then
-- Grant all
query := format('GRANT USAGE ON SCHEMA %I TO %s;', schema, role);
Return Next query;
Execute query;
query := format('GRANT ALL ON ALL TABLES IN SCHEMA %I TO %s;', schema, role);
Return Next query;
Execute query;
-- Apply them to new tables/views created by this admin account
query := format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON TABLES TO %s;', schema, role);
Return Next query;
Execute query;
-- Other permissions: functions, procedures, routines, sequences
Else
Return Next format('Error: privilege "%s" not found', privilege);
End If;
END LOOP;
Return;
END;
$$ LANGUAGE plpgsql;
Create Role report_mgr login password 'qwert';
Select grant_on_schemas('report_mgr', array['public'], 'all');
Grant pg_execute_server_program To report_mgr;
Any ideas will be appreciated.
Asked by Chema
(131 rep)
Jun 12, 2024, 11:03 AM
Last activity: Jun 24, 2025, 01:06 AM
Last activity: Jun 24, 2025, 01:06 AM