user with CREATEUSER can create database? - amazon-redshift

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.

Related

Postgres: How Can a Role Both Have INSERT Permissions and Not?

I have a table called resources and a user/role called public_anonymous ... and as far as I can tell, the user doesn't have INSERT permissions on that table. Here's DBeaver showing as much:
And here's the output of \z resources (at the psql command line):
Schema | Name | Type | Access privileges | Column privileges | Policies
--------+-----------+-------+--------------------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------
public | resources | table | admin=arwdDxt/admin +| | select_resources (r):
+
| | | public_postgraphile=arwd/admin+| | (u): true
+
| | | public_anonymous=r/admin +| | update_resources (w):
+
| | | public_admin_user=arwd/admin +| | (u): (( SELECT resource_authors.user_id
+
| | | public_user=ar/admin +| | FROM resource_authors
+
| | | =a/admin | | WHERE ((resource_authors.resource_id = resource_authors.resource_id) AND (resource_authors.user_id = (NULLIF(current_setting('jwt.claims.person_id'::text, true), ''::text))::integer))) IS NOT NULL)+
| | | | | to: public_user
+
| | | | | delete_resources (d):
+
| | | | | (u): (( SELECT resource_authors.user_id
+
| | | | | FROM resource_authors
+
| | | | | WHERE ((resource_authors.resource_id = resource_authors.resource_id) AND (resource_authors.user_id = (NULLIF(current_setting('jwt.claims.per
son_id'::text, true), ''::text))::integer))) IS NOT NULL)+
| | | | | to: public_user
The key part of that is:
public_anonymous=r/admin
ie. the role has only been granted read ("r") permissions by the admin role.
Furthermore, I have repeatedly tried to remove INSERT permissions by running:
REVOKE INSERT ON resources FROM public_anonymous;
Nevertheless, when I tried using pgTAP to verify my permissions, I was surprised to find that it reported that the user did have INSERT permissions. When I asked the maintainer why it thought that, he explained that it used the pg_catalog.has_table_privilege function ... and sure enough, when I ran:
select pg_catalog.has_table_privilege('public_anonymous', 'resources', 'INSERT');
I saw:
has_table_privilege
---------------------
t
I'm not a Postgres expert, so forgive me if this is a dumb question. Also I should note that I have been using both GRANT statements and row-level security policies on this table ...
... but still, I don't understand why multiple sources all say the user doesn't have INSERT permissions, AND I explicitly REVOKE-ed them ... yet pg_catalog.has_table_privilege still thinks I do have the permission.
Can anyone explain what's going on, and possibly how I might remove this permission (for good)?
This ACL item
=a/admin
means that PUBLIC (that is, everyone) has INSERT privileges on the relation. REVOKE that if you don't want it.

Why does selecting all tables from postgres gives different results based on syntax used

If I log into postgres and switch to the postgres database, when I check for tables with this command I get nothing back:
postgres=# \c postgres
You are now connected to database "postgres" as user "postgres".
postgres=# \dt+
Did not find any relations.
However if I do a select on the DB tables I do see that the tables are there:
postgres=# SELECT *
postgres-# FROM pg_catalog.pg_tables
postgres-# WHERE schemaname != 'pg_catalog' AND
postgres-# schemaname != 'information_schema';
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
------------+----------------+------------+------------+------------+----------+-------------+-------------
pgagent | pga_jobclass | postgres | | t | f | t | f
pgagent | pga_job | postgres | | t | f | t | f
pgagent | pga_jobagent | postgres | | t | f | t | f
pgagent | pga_jobstep | postgres | | t | f | t | f
pgagent | pga_schedule | postgres | | t | f | t | f
pgagent | pga_exception | postgres | | t | f | t | f
pgagent | pga_joblog | postgres | | t | f | t | f
pgagent | pga_jobsteplog | postgres | | t | f | t | f
(8 rows)
Why do I get nothing when I use \dt+ but I can see the tables using a select statement?
I think that this will help LINK
\d [NAME] describe table, index, sequence, or view
\d{t|i|s|v|S} [PATTERN] ("+" detail) list tables/indexes/sequences/views/system tables
\da [PATTERN] list aggregate functions
\db [PATTERN] list tablespaces (add "+" for more detail)
use \dt+ *
the * to match all as the command needs a pattern
The reason is that the pgagent schema is not on your search_path. \dt will only show those tables that you can access without schema qualification.

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.

Can see tables in phpPgAdmin but not in psql (or any other method)

I have recently installed postgres on my Mac and loaded a dump from our public website that I am trying to replicate locally. The pg_restore appeared to be successful, and I can see all my tables and user permissions in phpPgAdmin. They all look normal, and I can browse the data. However, when I access the database via psql I get no relations found. Similarly I have python scripts that access this database, and they also fail to find any tables.
I'm at a loss as to what to do.
Here are some psql commands I've done:
> psql -U mgd_dbo pub_mgd
psql (9.3.4)
Type "help" for help.
pub_mgd=# \d
No relations found.
pub_mgd=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
------------+------------+----------+------------------+-------+-------------------------
postgres | postgres | UTF8 | C | C | =CTc/postgres +
| | | | | postgres=CTc/postgres +
| | | | | mgd_dbo=CTc/postgres +
| | | | | mgd_public=CTc/postgres
pub_fe | postgres | LATIN9 | en_US.ISO8859-15 | C | =CTc/postgres +
| | | | | postgres=CTc/postgres +
| | | | | mgd_dbo=CTc/postgres +
| | | | | mgd_public=CTc/postgres
pub_mgd | postgres | LATIN9 | en_US.ISO8859-15 | C | =CTc/postgres +
| | | | | postgres=CTc/postgres +
| | | | | mgd_dbo=CTc/postgres +
| | | | | mgd_public=CTc/postgres
template0 | postgres | UTF8 | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
pub_mgd=# \dn+
List of schemas
Name | Owner | Access privileges | Description
--------+----------+----------------------+------------------------
mgd | mgd_dbo | mgd_dbo=UC/mgd_dbo +|
| | mgd_public=U/mgd_dbo |
public | postgres | postgres=UC/postgres+| standard public schema
| | =UC/postgres |
(2 rows)
pub_mgd is the database I've loaded. mgd_public and mgd_dbo are the two different users our scripts use (mgd_public is a read-only user).
I've tried both users, and even as the postgres user. Yet, the results are the same, no relations.
I even tried to see if phpPgAdmin was somehow hitting a different postgres sever, so I added a new database through it, and verified that the new database appears when I do \l in psql.
Any suggestions as to what to check next?
Ask for the list of relations in the mgd schema
\d mgd.*
To make the mgd schema the default place it at the beginning of the search path
set search_path to mgd, "$user", public;

Check if a role in PostgreSQL has a password set

I wonder how I can verify whether or not a role (users are just a specific kind of role) has a password set in PostgreSQL 9.1.
I tried the command \dg+ and \du+ but they don't show you anything password related. I also used the following query, but it doesn't help either because of its indifference (I'm quite sure that the postgresql user has no password set in this case):
SELECT * FROM pg_user;
usename | usesysid | usecreatedb | usesuper | usecatupd | userepl | passwd | valuntil | useconfig
----------+----------+-------------+----------+-----------+---------+----------+----------+-----------
postgres | 10 | t | t | t | t | ******** | |
aef | 16201 | t | t | t | t | ******** | |
Passwords are stored in pg_shadow
In documentation:
Password (possibly encrypted); null if none. See pg_authid for details
of how encrypted passwords are stored.
So you should select * from pg_shadow;
You should also check pg_authid table.