Sample Header Ad - 728x90

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