Me pregunto por qué un usuario recién creado puede crear una tabla después de conectarse a una base de datos. Tengo una base de datos project2_core
:
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+--------------+-----------+-------------+-------------+-------------------------------
postgres | postgres | SQL_ASCII | C | C |
project2_core | atm_project2 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2
template0 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
Hasta aquí todo bien. Ahora creo un usuario:
postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER
Bueno. Cuando intento conectarme a la base de datos, el usuario no puede hacerlo:
$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich:
psql: FATAL: permission denied for database "project2_core"
DETAIL: User does not have CONNECT privilege.
Esto es lo que esperaba. Ahora comienzan las cosas extrañas. Le otorgo al usuario CONNECT
:
postgres=# GRANT CONNECT ON DATABASE project2_core TO dietrich;
GRANT
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+--------------+-----------+-------------+-------------+-------------------------------
postgres | postgres | SQL_ASCII | C | C |
project2_core | atm_project2 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2+
| | | | | dietrich=c/project2
template0 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
Y sin más concesiones, el usuario puede crear una tabla:
$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich:
psql (9.2.3)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
project2_core=> create table adsf ();
CREATE TABLE
project2_core=> \d
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | adsf | table | dietrich
(1 row)
Hubiera esperado que el usuario no tenga permitido hacer nada antes de hacerlo explícitamente GRANT USAGE
en el esquema y luego GRANT SELECT
en las tablas.
¿Dónde está mi error? ¿Qué estoy haciendo mal? ¿Cómo puedo lograr lo que quiero (que un nuevo usuario no tenga permitido hacer nada antes de otorgarle explícitamente los derechos correspondientes)?
Estoy perdido, y tu ayuda es muy apreciada :)
EDITAR Siguiendo el consejo de @ daniel-verite, ahora revoqué todo inmediatamente después de crear la base de datos. El usuario dietrich ya no puede crear una tabla. Bueno. PERO : Ahora, también el propietario de la base de datos, project2 , no tiene permitido crear una tabla. Incluso después de emitir GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2
y GRANT ALL PRIVILEGES ON SCHEMA public TO project2
recibo un error ERROR: no se ha seleccionado ningún esquema para crear , y cuando lo intento específicamente CREATE TABLE public.WHATEVER ();
, obtengo ERROR: permiso denegado para el esquema público . ¿Qué estoy haciendo mal?
fuente
REVOKE ALL ON DATABASE project2_core FROM PUBLIC;
. ¿Por qué esto no tuvo ningún efecto?CREATE TABLE
. mira mi edición arriba.Lo crucial para entender aquí es que los privilegios no son heiraquicos y no se heredan de contener objetos .
ALL
significa todos los privilegios para este objeto, no todos los privilegios para este objeto y todos los objetos contenidos .Cuando otorgas
ALL
en una base de datos, estás otorgandoCREATE, CONNECT, TEMP
. Estas son acciones en el objeto de la base de datos en sí mismo:CONNECT
: Conectarse a la base de datosCREATE
: Crear un esquema ( no una tabla)TEMP
: Crea objetos temporales, incluidas, entre otras, tablas temporalesAhora, cada base de datos PostgreSQL por defecto tiene un
public
esquema que se crea cuando se crea la base de datos. Este esquema tiene todos los derechos otorgados al rolpublic
, del cual todos son implícitamente miembros. Para un esquema,ALL
significaCREATE, USAGE
:CREATE
: Crear objetos (incluidas tablas) dentro de este esquemaUSAGE
: Enumere los objetos en el esquema y acceda a ellos si sus permisos lo permitenSi no especifica el esquema para crear un objeto como una tabla, el motor de la base de datos usa el
search_path
, y de manera predeterminada elpublic
esquema está primero en el,search_path
por lo que la tabla se crea allí. Todos tienen derechospublic
de forma predeterminada, por lo que se permite la creación. Los derechos de los usuarios en la base de datos son irrelevantes en este momento, ya que el usuario no está tratando de hacer nada al objeto de la base de datos, solo un esquema dentro de él.No importa que no haya otorgado al usuario ningún derecho que no sea otorgar
CONNECT
en la base de datos, porque elpublic
esquema permite a todos los usuarios crear tablas en él de manera predeterminada. Daniel ya ha explicado cómo revocar ese derecho si lo desea.Si desea delegar todos los derechos explícitamente, revoque todo de public, o simplemente descarte el esquema público. Puede crear una nueva base de datos de plantilla con este cambio aplicado si lo desea. Alternativamente, puede aplicarlo
template1
, pero eso probablemente romperá un montón de código de terceros que se supone quepublic
existe y que se puede escribir.Esto podría tener más sentido si observa una analogía del sistema de archivos.
Si tengo la estructura de directorios (modo simplificado para mostrar solo el modo que se aplica al usuario actual):
entonces no puedo crear nada dentro
/dir1
, porque no tengo permiso de escritura. Entonces, sitouch /dir1/somefile
recibo un error de permiso denegado.Sin embargo, sí tengo permiso para mirar dentro
/dir1
y acceder a archivos y directorios contenidos, incluidos/dir1/dir2
. Tengo permiso de escritura sobredir2
. Asítouch /dir1/dir2/somefile
tendrá éxito , a pesar de que no tengo permiso de escrituradir1
.Lo mismo con bases de datos y esquemas.
fuente
Si solo desea evitar que los nuevos usuarios creen tablas, debe ejecutar el siguiente comando:
Si tu
REVOKE ALL
(como sugieren otras respuestas), también evitará que los usuarios tenganUSAGE
permisos.USAGE
significa que los usuarios pueden usar los permisos asignados a ellos, por lo que si los elimina, sus usuarios no podrán enumerar o acceder a las tablas a las que tienen acceso.Alternativamente, también podría
REVOKE CREATE
para un usuario específico:Consulte también: Cómo crear un usuario de solo lectura con PostgreSQL .
fuente