permission denied for schema public at character 14 - postgresql

I am using postgresql 15
and I tried running these
grant all privileges on database my_database to my_database_user;
grant all privileges on all tables in schema public to my_database_user;
grant all privileges on all sequences in schema public to my_database_user;
grant all privileges on all functions in schema public to my_database_user;
but when I run
php artisan migrate --seed
I got
SQLSTATE[42501]: Insufficient privilege: 7 ERROR: permission denied for schema public at character 14 (SQL: create table "migrations" ("id" serial primary key not null, "migration" varchar(255) not null, "batch" integer not null))
What I am missing?
I do make sure .env has correct credentials
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=my_database
DB_USERNAME=my_database_user
DB_PASSWORD=password
Checking that i did
postgres=# \du my_database_user
List of roles
Role name | Attributes | Member of
-------------+------------+-----------
my_database_user | | {}
and
postgres=# SELECT * FROM pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
---------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
my_database_user | f | t | f | f | t | f | -1 | ******** | | f | | 16389

You are missing permissions on the schema:
GRANT CREATE ON SCHEMA public TO my_database_user;
You are probably using PostgreSQL v15 or higher. The default permissions on the public schema have changed in v15. Before, the insecure default was to allow everyone (PUBLIC) to create objects in schema public. Now only the database owner can do that, unless you grant extra privileges.

Related

Jooq not able to find my public schemas from database

I'm trying to programatically generate code using jooq 3.12.3 with the following code, but the program runs successfully and no code is generated.
Configuration configuration =
new Configuration()
.withJdbc(
new Jdbc()
.withDriver("org.postgresql.Driver")
.withUrl("jdbc:postgresql://127.0.0.1:6666/postgres")
.withUser("<username>")
.withPassword("<correct password>"))
.withGenerator(
new Generator()
.withDatabase(
new Database()
.withName("org.jooq.meta.postgres.PostgresDatabase")
.withIncludes(".*")
.withExcludes("")
.withInputSchema("public"))
.withGenerate(
new Generate()
.withDaos(true)
.withDeprecated(false)
.withImmutablePojos(false)
.withPojosEqualsAndHashCode(true)
.withValidationAnnotations(true)
.withVarargSetters(false))
.withTarget(
new Target()
.withPackageName("com.package.data.jooq")
.withDirectory("src/main/java")));
GenerationTool.generate(configuration);
Some debugging info
\dt
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+----------
public | django_migrations | table | postgres
public | table1 | table | postgres
public | table2 | table | postgres
,
\l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+-------------------+----------+------------+------------+-----------------------------------------
cloudsqladmin | cloudsqladmin | UTF8 | en_US.UTF8 | en_US.UTF8 |
postgres | cloudsqlsuperuser | UTF8 | en_US.UTF8 | en_US.UTF8 |
,
SELECT table_catalog, table_schema, table_name
FROM information_schema.tables;
doesn't show public under table_schema
What could be the problem?
The problem was with permissions..
GRANT SELECT ON TABLE public.table1 TO user;
GRANT SELECT ON TABLE public.table2 TO user;
Solved the problem. After this the tables started showing up in
SELECT table_catalog, table_schema, table_name
FROM information_schema.tables;

Multi-Database Multi-Schemas do't seem to work in newer versions of postgresql

I have a problem where I want to create two databases
and two schemas. Each database will have a separate schema.
The public schema has been dropped. I have tried this without dropping
the public schema with the same result. When connecting to the database with the database and schema owner the schema cannot be seen or used.
I have set up single databases with an schema, but never tried to set up more than one. The problem sees to come from multiple databases and schemas.
create user tom;
create database fishes owner tom encoding = 'UTF8';
create schema fish authorization tom;
alter database fishes set schema 'fish';
create user harry;
create database lizards owner harry encoding = 'UTF8';
create schema lizard authorization harry;
alter database lizards set schema 'lizard';
psql (10.8)
postgres=# create user tom;
CREATE ROLE
postgres=# create database fishes owner tom encoding = 'UTF8';
CREATE DATABASE
postgres=# create schema fish authorization tom;
CREATE SCHEMA
postgres=# alter database fishes set schema 'fish';
ALTER DATABASE
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
tom | | {}
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+----------------------------+----------------------------+-----------------------
fishes | tom | UTF8 | English_United States.1252 | English_United States.1252 |
postgres | postgres | UTF8 | English_United States.1252 | English_United States.1252 |
template0 | postgres | UTF8 | English_United States.1252 | English_United States.1252 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | English_United States.1252 | English_United States.1252 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
postgres=# \dn
List of schemas
Name | Owner
------+-------
fish | tom
(1 row)
postgres=# create user harry;
CREATE ROLE
postgres=# create database lizards owner harry encoding = 'UTF8';
CREATE DATABASE
postgres=# create schema lizard authorization harry;
CREATE SCHEMA
postgres=# alter database lizards set schema 'lizard';
ALTER DATABASE
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
harry | | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
tom | | {}
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+----------------------------+----------------------------+-----------------------
fishes | tom | UTF8 | English_United States.1252 | English_United States.1252 |
lizards | harry | UTF8 | English_United States.1252 | English_United States.1252 |
postgres | postgres | UTF8 | English_United States.1252 | English_United States.1252 |
template0 | postgres | UTF8 | English_United States.1252 | English_United States.1252 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | English_United States.1252 | English_United States.1252 | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
postgres=# \dn
List of schemas
Name | Owner
--------+-------
fish | tom
lizard | harry
(2 rows)
postgres=# alter user tom password 'xxx';
ALTER ROLE
postgres=# alter user harry password 'xxx';
ALTER ROLE
when I did a \dnpsql -U tom fishes
Password for user tom:
psql (10.8)
WARNING: Console code page (437) differs from Windows code page (1252)
8-bit characters might not work correctly. See psql reference
page "Notes for Windows users" for details.
Type "help" for help.
fishes=> \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+----------------------------+----------------------------+-----------------------
fishes | tom | UTF8 | English_United States.1252 | English_United States.1252 |
lizards | harry | UTF8 | English_United States.1252 | English_United States.1252 |
postgres | postgres | UTF8 | English_United States.1252 | English_United States.1252 |
template0 | postgres | UTF8 | English_United States.1252 | English_United States.1252 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | English_United States.1252 | English_United States.1252 | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
fishes=> \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
harry | | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
tom | | {}
fishes=> \dn
List of schemas
Name | Owner
--------+----------
public | postgres
(1 row)
fishes=> show search_path;
search_path
-------------
fish
(1 row)
fishes=> create table eels( type varchar(30) primary key );
ERROR: no schema has been selected to create in
LINE 1: create table eels( type varchar(30) primary key );
^
fishes=> create table fish.eels( type varchar(30) primary key );
ERROR: schema "fish" does not exist
LINE 1: create table fish.eels( type varchar(30) primary key );
^
I would expect when I logged in with either user that when I logged in with one of my non-postgres users that \dn would show the schema for the database that is show with the show search_path. Search_path is correct. Also it seems that access is not granted to the owner of the schema.
The answer is as Jeremy suggested in his comment.
Before creating the schema connect to the database you want to create the schema in.
There is no create schema syntax that includes the database name it should be created in, so it needs to be done this way.

Relation between roles and pg_terminate_backend and/or pg_cancel_backend admin functions in PostgreSQL

Consider the following example:
A superuser admin executes the following commands in a PostgreSQL database:
CREATE DATABASE admindb;
CREATE ROLE dbo WITH CREATEDB CREATEROLE;
GRANT ALL PRIVILEGES ON DATABASE admindb TO dbo WITH GRANT OPTION;
CREATE ROLE user1 WITH LOGIN PASSWORD 'user1pw';
GRANT dbo TO user1;
ALTER ROLE user1 SET ROLE dbo;
In the next step, user1 does the following:
psql -h 10.11.4.32 -d admindb -U user1
# creates a table in admindb database
CREATE TABLE test1 ( a INT, b INT);
# check pg_stat_activity
datid | datname | pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | xact_start | query_start | state_change | wait_event_type | wait_event | state | backend_xid | backend_xmin | query
17816 | admindb | 21314 | 17819 | user12 | psql | | | | | | | | | | | | 625 |<insufficient privilege>
(1 row)
Please see that query field shows insufficient privilege.
If I don't run ALTER ROLE user1 SET ROLE dbo while creating user1, the query field displays it correctly as given below.
17816 | admindb | 18386 | 17819 | user12 | psql | 192.168.0.12 | | 58794 | 2018-08-10 06:13:48.762903+00 | 2018-08-10 06:14:57.119916+00 | 2018-08-10 06:14:57.119916+00 | 2018-08-10 06:14:57.119917+00 | | | active | | 624 | select * from pg_stat_activity;
(1 row)
I would like to understand what causes this behavior.
As a consequence of this, if user1 runs a long query and tries to cancel it by connecting using psql to admindb as user1 and running select pg_cancel_backend(pid), it fails with the error.
ERROR: must be a member of the role whose query is being canceled or member of pg_signal_backend
If I remove ALTER ROLE user1 SET ROLE dbo, then user1 is able to cancel the query.
The reason is that the SET ROLE changes your active user context to dbo right after you connect, but your “session user” still is user1:
SELECT current_user, session_user;
current_user | session_user
--------------+--------------
dbo | user1
(1 row)
In pg_stat_activity you can only see the sessions whose session user equals your currently active user, and pg_cancel_backend and pg_terminate_backend allow you only to affect backends whose session user equals your current user.
You can execute RESET ROLE to revert to user1 and perform these operations.

PostgreSQL: Serializable transactions with GRANT/DROP role

I have been reading a lot about serializable transactions in Postgres, but came across an issue that I haven't been able to resolve. Let's assume that I have two Postgres sessions A and B from different psql processes, and that before starting any transactions, I create roles role1 and role2
myuser=# CREATE ROLE role1 ;
CREATE ROLE
myuser=# CREATE ROLE role2 ;
CREATE ROLE
At this point, I can start transactions in both of the sessions via myuser=# BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE ; and verify that both sessions see both roles, via SELECT * FROM pg_catalog.pg_roles;
Let's assume that I drop the role role2 from the session B, verify that it's not shown and commit:
myuser=# DROP ROLE role2 ;
DROP ROLE
myuser=# SELECT * FROM pg_catalog.pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
-----------------------------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+-------
role1 | f | t | f | f | f | f | -1 | ******** | | f | | 16563
myuser=# commit ;
COMMIT
Now, let's go back to session A:
Even after dropping role2 and committing inside session B, we can still see that the transaction in session A still sees both roles (as expected, as this is serializable):
myuser=# SELECT * FROM pg_catalog.pg_roles;
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid
-----------------------------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+------
role1 | f | t | f | f | f | f | -1 | ******** | | f | | 16563
role2 | f | t | f | f | f | f | -1 | ******** | | f | | 16564
Now, let's try the GRANT command. Here is the weird part:
myuser=# GRANT role2 TO role1 ;
ERROR: role "role2" does not exist
Right before running the GRANT, we can see that both roles role1 and role2 exist, but now we see such error. Why is that?
Thanks!
With “normal” (i.e. non-catalog) tables conflicting operations like this would lead to a serialization error. While a serializable transaction sees an old state of the database, any attempt to modify a value that has been changed since would lead to such an error.
What makes this case different is that the tables that store roles and role membership (pg_authid and pg_auth_members) are catalog tables (even shared catalogs since roles apply to all databases), and for these processing and error messages are slightly different.
It is good and necessary that the operation fails, even if the error message is surprising.

user with CREATEUSER can create database?

Team, I am using Redshift 8.0.2. I created one user as below:
create user user004 with password 'User123#' CREATEUSER valid until '2015-03-31';
redshift3=# select * from pg_user where usename = 'user004' ;
usename | usesysid | usecreatedb | usesuper | usecatupd | passwd | valuntil | useconfig
---------+----------+-------------+----------+-----------+----------+------------------------+-----------
user004 | 104 | f | t | f | ******** | 2015-03-31 00:00:00+00 |
(1 row)
I did not grant CREATEDB to this user. However, this user able to create a database.
redshift3=# create database mydb4 ;
CREATE DATABASE
redshift3=# \list
List of databases
name | owner | encoding | access privileges
----------------+---------+----------+-------------------
mydb4 | user004 | UNICODE |
In pg_user, property shows false. Please guide me. Is this default behaviour in Redshift ?
You gave the user the CREATEUSER privilege which makes the user into a superuser and therefore they can do whatever they want. See http://docs.aws.amazon.com/redshift/latest/dg/r_superusers.html for details.