Export postgres user list to migrate to a new version on GCP - google-cloud-sql

I need to migrate my postgres database to a newer version. For that, I do the dump and restore, without problems. However, users from one instance are not copied to another, as was the case with the dump_all command using local postgres.
How do I export these users to a new installation, thus allowing to migrate my database to a newer version?

This article explains a workaround for Google Cloud for Postgres.
Basically you enable access to the pg_shadow table for the user you login with, e.g. "postgres", by setting the database flag cloudsql.pg_shadow_select_role, then run this query to create a dynamic query to re-create the users with the existing hashed passwords:
SELECT 'CREATE ROLE "'|| usename ||'" NOINHERIT LOGIN PASSWORD '''|| passwd ||''';'
FROM pg_shadow
WHERE usename <> 'postgres' AND usename not ilike 'cloud%' ORDER BY usename ASC
What this can't do is upgrade passwords from md5 to SCRAM automatically. You would have to enter all the passwords manually to do that.

According to the Cloud Sql upgrade documentation you should provide user details manually in a new instance, which implies that tables containing information on users are not getting propagated during the dump and restore.

Related

Create Postgres User with admin rights just for one database

How can I create a postgres user who has admin access only to one database but cannot inspect or interfere with other databases in the postgres instance? The use case is I'm creating a multitenant application
where each tenant gets his own database in the postgresql instance and can create schemas, tables etc and
perhaps use a few pg_tables to inspect his own database but not others.
cannot change the name of the database as it's controlled by me
EDIT: Added more constraints
That's fairly trivial:
CREATE DATABASE newdb;
GRANT CREATE ON DATABASE newdb TO newdba;
Add pg_hba.conf entries to allow newdba to connect to newdb only.

Is "postgres" a default and special user of 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.

What happens after a "DROP DATABASE postgres"

I have a funny question about PostgreSQL database: What happens if the postgres database is dropped?
dropdb postgres worked.
createdb postgres worked too.
psql worked.
But I thought the users would be lost. Yet the old users are still there.
So where are the users stored for the database and which implications does dropping the postgres database have?
PostgreSQL metadata are stored in catalog tables, which are in the pg_catalog schema. These are accessible like regular views and tables.
There are shared system catalog tables which are shared between all databases. These tables are not affected when databases are dropped.
pg_authid, the table where the users are stored, is one of those shared catalogs. This is because in PostgreSQL, users don't belong to a database, but to the whole database cluster.
You can list all shared catalog tables like this:
SELECT relname FROM pg_class
WHERE relisshared AND relkind = 'r';
In the documentation you can find more information about the system catalogs.
When connecting to a Postgres server, you always need to specify which database you want to connect to.
When you set up a new server, you need something to connect to before you can run your first CREATE DATABASE statement.
That's all the postgres database is: a dummy database to use as a connection target for admin commands. There's no data in there, and you're free to drop it and use a different one instead (though whoever inherits your system will probably not thank you for it...).
As gil.fernandes said in his answer, server-wide objects like users are accessible from every database, but aren't stored inside any database in particular.

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;

View database user and password in PgAdmin

How do I change a user's password in Postgresql (using PgAdmin) so that I can connect with Rails to the Postgres database using these credentials?
So far: In PgAdmin I right clicked the database name, clicked Create Script and then typed the command:
CREATE USER usr1 WITH PASSWORD 'pwd1!##$';
Question: where exactly in PgAdmin am I able to see the user and password or list of users and passwords? So far I am unable to see this in Db properties --> 'privileges'?? Any tips on other security elements? or something that can be improved in my current methods? Thanks a lot.
In the file "pgpass.conf" in this path:
C:\Users\[User's name]\AppData\Roaming\postgresql
Login roles are common for all databases in a server. You can see them in the bottom of the object browser (left panel).
To execute arbitrary SQL query open Query tool (Ctrl-E) from Tools in main menu or click on icon with 'SQL' (previously you have to select a database).
To change user password execute SQL:
ALTER ROLE username PASSWORD 'newpassword'
ALTER USER is an alias for ALTER ROLE. Read about it in documentation.
Run the query from pgadmin:
SELECT rolname, rolpassword FROM pg_authid;
This requires superuser privileges to protect the password.