I have asked this question on SO but perhaps that was the wrong location. Apologies for double posting but the question may have a better audience here.
The original question is: https://stackoverflow.com/questions/25619290/change-permissions-of-postgres-copy-to-exported-file
And the text is below. Thanks.
When running the postgresql [9.3] "COPY TO" functionality, the postgres user creates a file. I have told it to put the file in the tmp directory (although this can be changed if needed).
This is run as part of a cron job, the user is an "export" user set up especially for this task. The end goal is for the exported file to end up in /home/export/created_file.csv.
1) postgres
can't stash the exported file straight into the home directory of another user without setting up the folder to be overly permissive.
2) the export user can copy the file from /tmp
to it's home directory, but then can not clean up (delete) the postgres
owned file in /tmp
.
This is a daily process and so old files will need to be deleted in some way. I can add a cron job to clean up the files afterwards but I was hoping for a cleaner solution – either a way to change the permissions on the file that postgres
creates, or some way to give the export user the additional permission of being able to delete that file in advance of it's creation.
Giving the export user the same permissions as postgres
in general however isn't an option, as it would then have free reign over the database.
Any advice, be it unix based or postgres based would be very welcome, thanks.
Best Answer
You'll want to create a directory without the
t
(sticky) permissions bit set, and have PostgreSQL copy the file into there. You should also make the directory setgid (g+s
), as that makes the group inherited from the directory, not the creating process; see setgid directories.You could put this directory in
/tmp
but personally I'd put it some neutral location like/var/lib
, or mounted volume somewhere, as/tmp
gets cleaned out automatically so you'll need to have the directory re-created if it's missing.Assuming you do use
/tmp
:then create the csv in there. It'll be automatically created with group-owner
users
, which will make it readable by your users (unless PostgreSQL'sumask
is too restrictive). Because the directory is group-writable byusers
(or whatever group you use) and does not have thet
(sticky) bit set your users can delete files they do not own from it.The reason this doesn't work when using
/tmp/
directly is that the sticky bit is set in/tmp
for security, so that user1 can't delete a file created by user2 and replace it with a symlink that user2 then writes to, allowing user1 to steal their data / trick them into overwriting things.Other options:
export
, usingpsql
's\copy
command, so it writes the data over the client/server socket and the file is created as theexport
user in the first place. This is by far the simplest option, and only slightly slower than a directCOPY
.root
invoke the PostgreSQLcopy
then move the data file and change its ownership once theCOPY
finishes.sudo
to move/delete.postgres
user special permission to write to/home/export
(if POSIX ACLs are enabled on your file system)/home/export
topostgres
and make its permissionsg=wx
. PostgreSQL can add new entries, and overwrite anything within that it has write permission to, but not list entries. I don't like this option much.