Is "postgres" a default and special user of PostgreSQL? - postgresql

Chapter 21. Database Roles lists the default roles of PostgreSQL. But I don't find user postgres there,
which has been created by default in PostgreSQL. Is postgres a
default role? Does the manual miss it or do I misunderstand?
In PostgreSQL, is postgres a special user, or a regular user just
like one created manually? Does the PostgreSQL server need the user postgres? Will removing it cause some trouble to the server or something else?
The following two commands run in psql provide default roles or
usernames, which both include postgres. Why do they differ?
# select usename from pg_catalog.pg_user;
usename
----------
postgres
(1 row)
# select rolname from pg_catalog.pg_roles;
rolname
----------------------
postgres
pg_monitor
pg_read_all_settings
pg_read_all_stats
pg_stat_scan_tables
pg_signal_backend
(6 rows)

postgres is not a default role.
When you create the PostgreSQL database cluster with initdb, you can specify the name of the installation superuser with the -U option. If you omit that option, the name of the superuser will be the same as the name of the operating system user you are using.
Since it is customary to have initdb PostgreSQL run by an operating system user postgres, the superuser is usually called postgres too, but that isn't in any way required.
postgres is just a normal superuser like any other.
You will have trouble dropping it because it owns all the system objects, and you cannot easily modify those objects. You are advised not to try.
pg_read_all_settings and the others don't show up in pg_user because they are not login roles.

postgres is the first user that is available after an installation. it is a super user. But, it is possible to define your own super users which will have equivalent permissions to the postgres user.
A user is a role that has the ability to log in.
Roles without login privilege are used for various system level uses and are sometimes also used to manage access control rules through inheritance (e.g. you may have a role analysts and a user hal that is granted membership to the analysts role)
Thus pg_user only returns those roles that are able to log into the database.

Related

How can I force prefix "pg_" to create new user in postgres?

I have problem with postgres. It is possible to force prefix "pg_" to create user in PostgreSQL? For example:
CREATE USER pg_admin PASSWORD 'qwerty';
I am using PostgreSQL 10.6
This limitation has been in effect since version 9.6, where system roles starting with pg_ were introduced.
You could create a role with a different name and then update rolname in pg_authid, but that would be a bad idea, since PostgreSQL treats such roles differently than others. For example, the role would not be dumped by pg_dumpall -r.

Non-SuperUser Database Management

I am using the PostgreSql manual and other guides to setup my database environment.
So far things are looking good, but I am wondering if I have a problem.
I am trying to apply this:
Tip It is good practice to create a role that has the CREATEDB and CREATEROLE privileges, but is not a superuser, and then use this role for all routine management of databases and roles. This approach avoids the dangers of operating as a superuser for tasks that do not really require it.
I have already created a user for this role.
createuser --interactive --pwprompt
Enter name of role to add: Manager
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) y
...and connected to an already existing database as the new user (Manager) Or so I thought.
psql -d test
Password for user postgres:
psql (11.2)
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.
test=# \c test Manager
Password for user Manager
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.
You are now connected to database "test" as user "Manager".
test=>
I created a table for the database "test", but on checking it,the Owner isn't Manager, but postgres.
test=> \dt
List of relations
Schema | Name | Type | Owner
--------+---------------+-------+----------
public | Data-projects | table | postgres
(1 row)
test=> \dn
List of schemas
Name | Owner
--------+----------
public | postgres
(1 row)
I am not sure if this is good. I expected the owner to be Manager.
This is my first time using these tools. Can someone guide me in the right direction, please?
I want Manager to manage all the databases.
Wouldn't that make him owner?
Thanks
Database test is not owned by Manager because it was created by user postgres. The user who created an object will be its owner.
However, a superuser can transfer ownership:
ALTER DATABASE test OWNED BY "Manager";
I'll give you some additional tips:
Only use lower case letters, numbers and _ in the names of objects and users, because otherwise you always have to user double quotes for them in SQL, like I did above. That leads to needless suffering.
Run the following to make the database more secure:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
Create a new schema that will hold the objects for your application:
CREATE SCHEMA myapp;
Set the search_path appropriately:
ALTER DATABASE test SET search_path = myapp, public;

Postgres ACL for Schemas

I'm not a DBA and I have got some questions around access controls for schemas. Let's say I have a Postgres server running a several databases. The admin user is postgres. I have another user tmpUser with which I could log in to the remote server using pgadmin3 client.
I now create a database called myDatabase which is by default owned by the postgres user. I then use my admin client to remotely log in to this myDatabase using the tmpUser account.
I now create a new schema inside this myDatabase called myDbSchema. I created a new role called myDbRole and did a grant usage, grant all on myDatabase, myDbSchema to the myDbRole.
The question now is how should I control access to this myDatabase. I tried to log in to the remote server using the tmpUser and when I tried to execute select * from myTable where myTable is a table in myDatabase, it came back with a permission denied sql message. So I changed the owner of the table to the tmpUser which I really do not want to!
Is there a guide or something on how I should go about creating and organizing roles with schemas in postgres?
It is not entirely clear what your problem is (for instance, what is role "myDbRole" for, is that a group role (NOLOGIN) or a user role (LOGIN)?) but in general you could follow this pattern of permission management:
Create a specific role to own a database and all or most of the objects in it. This should be a group role (NOLOGIN) for security reasons. Do not use the postgres user; if you need to login as that role often to do regular database work, you are doing something wrong. Any superuser (or other user role that has that role granted to it) can "impersonate" that owner role using SET SESSION AUTHORIZATION to do necessary maintenance. In a production environment this should be hardly ever necessary; during development you might want to consider making the role with LOGIN permission for ease of use.
The owner creates all the schemas, tables, views, functions, etc. that you need for your application. By default, all of those objects are only available to the database owner, with the exception of functions.
Define a number of group role profiles, each having specific requirements of the database. You could have, for instance sales_staff, product_managers, accounting and senior_management for a company, or web_user, web_admin, app_developer and app_manager for a web site. The database owner then GRANTs access to the database (CONNECT), schemas (USAGE), tables, views and functions (EXECUTE), as needed. I usually REVOKE ALL ON FUNCTION x() TO public, for security reasons.
Assign group role membership to user roles, as needed: GRANT sales_staff TO jane. The user roles should have LOGIN INHERIT such that they can log in and inherit the permission of group roles that they are a member of. That includes the permission to connect to a database and usage rights on schemas. Note that a single user role can have membership in multiple group roles.
Lastly, update your pg_hba.conf file to enable remote access to the database.

Database named "postgres"

I've just set up Postgres for use by different users on my network. Every user has his own username/password/database, but when I connect to Pg I can also see a 'postgres' database (and even create tables etc). I tried to REVOKE access to that database from public but then it won't let me connect. What exactly is the postgres database and why is it needed? Can I disable it so that users only see the database(s) I've created for them?
The postgres database is created by default when you run initdb.
Quote from the manual:
Creating a database cluster consists of creating the directories in which the database data will live (...) creating the template1 and postgres databases. When you later create a new database, everything in the template1 database is copied. (...) The postgres database is a default database meant for use by users, utilities and third party applications.
There is nothing special about it, and if you don't need it, you can drop it:
drop database postgres;
You need to do that as a superuser of course. The only downside of this is that when you run psql as the postgres operating system user, you need to explicitly provide a database name to connect to
If you drop the postgres database you'll find a few things to be confusing. Most tools default to using it as the default database to connect to, for one thing. Also, anything run under the postgres user will by default expect to connect to the postgres database.
Rather than dropping it, REVOKE the default connect right to it.
REVOKE connect ON DATABASE postgres FROM public;
The superuser (usually postgres), and any users you explicitly grant rights to access the database can still use it as a convenience DB to connect to. But others can't.
To grant connect rights to a user, simply:
GRANT connect ON DATABASE postgres TO myuser;

Why can I not set permissions on fresh install of PostgreSQL

A fresh installation of PostgreSQL 9.3 (according to the YUM Installation manual on the PostgreSQL wiki) on CentOS 6 (64-bit) will not grant permissions to any users.
I log in to the postgres user and open psql, then I create a role for my default user:
CREATE ROLE <name> WITH PASSWORD '<password>';
and then try to grant it privileges on the default postgres database:
GRANT ALL ON DATABASE postgres TO <user>;
which gives the expected output, but the user does not have any permissions on postgres.
The output of \dp <user> is quizically empty as well. Additional testing shows that I cannot give any users permissions. However, when I try to drop a role that has been granted these nonexistent permissions, it says
ERROR: role "<user>" cannot be dropped because some objects depend on it
DETAIL: privileges for database postgres
I am at a loss. I did also check to make sure the postgres Linux user has the appropriate file permissions on the PostgreSQL data directory.
Presumably you're expecting too much of GRANT ALL ON DATABASE postgres TO <user>;
ALL in this context means that the command is equivalent to:
GRANT CREATE,CONNECT,TEMPORARY ON DATABASE postgres TO <user>;
And the way you create the ROLE, it cannot login to any database anyway (you can check this with \du).
It could if it was created with:
CREATE ROLE name WITH LOGIN PASSWORD 'pass';
or use ALTER ROLE name WITH LOGIN later on.
Starting from this, to give the user permissions to create objects in the database, other forms of GRANT should be used.