Dear Postgreezers, been banging my head against this one for a couple days. Googling and StackExchange were just as useful, so you're my last hope. I've been unable to get a non-admin user to run Copy From Program even after granting pg_execute_server_program, and everything else I could think of. It always fails with ERROR: permission denied to COPY to or from an external program.
I'll let the code speak by itself. Here's a minimal example that I've tried in the last official Docker image: -- Spin a temporal Pg and connect to psql --docker run --name pg16 -e POSTGRES_PASSWORD=qwer -d postgres:16 --docker exec -ti pg16 psql -U postgres CREATE TABLE testtable ( id int NOT NULL GENERATED ALWAYS AS IDENTITY, name text NOT NULL ); Create Role justintestin noinherit login password 'qwer'; -- Necessary privileges GRANT CONNECT ON DATABASE postgres TO justintestin; GRANT USAGE ON SCHEMA public TO justintestin; GRANT ALL ON ALL TABLES IN SCHEMA public TO justintestin; -- Apply them to new tables/views created by admin account ALTER DEFAULT IN SCHEMA public GRANT ALL ON TABLES TO justintestin; -- Allow Copy From Program... or try to anyway GRANT pg_execute_server_program TO justintestin; -- Tests GRANT ALL ON testtable TO justintestin; GRANT ALL ON SCHEMA public TO justintestin; GRANT ALL ON DATABASE postgres to justintestin; GRANT pg_read_all_data TO justintestin; GRANT pg_write_all_data TO justintestin; --Copy works with admin account Copy testtable(name) From Program 'echo "Buffa Testata"' CSV; -- COPY 1 --But fails with justintestin SET role justintestin; Copy testtable(name) From Program 'echo "Errato Denegato"' CSV; --SQL Error [42501]: 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 tho he's privileged SELECT rolname FROM pg_roles WHERE pg_has_role(current_user, oid, 'member'); -- rolname --------------------------- -- pg_read_all_data -- pg_write_all_data -- pg_execute_server_program -- justintestin --Insert works Insert Into testtable ("name") VALUES('Pazzo Intestinato'); --INSERT 0 1 Select * From testtable; SELECT current_user, session_user; -- Clean up for new test SET role postgres; Drop Table testtable; Drop Owned By justintestin; Drop Role justintestin; What am I missing? (besides a few chunks of hair)