Is it possible to create a user in PostgreSQL without providing the plain text password (ideally, I would like to be able to create a user providing only its password crypted with sha-256) ?
What I would like to do is to create a user with something like that :
CREATE USER "martin" WITH PASSWORD '$6$kH3l2bj8iT$KKrTAKDF4OoE7w.oy(...)BPwcTBN/V42hqE.';
Is there some way to do that ?
Thank you for your help.
You may provide the password already hashed with md5, as said in the doc (CREATE ROLE):
ENCRYPTED UNENCRYPTED These key words control whether the password is
stored encrypted in the system catalogs. (If neither is specified, the
default behavior is determined by the configuration parameter
password_encryption.) If the presented password string is already in
MD5-encrypted format, then it is stored encrypted as-is, regardless of
whether ENCRYPTED or UNENCRYPTED is specified (since the system cannot
decrypt the specified encrypted password string). This allows
reloading of encrypted passwords during dump/restore.
The information that's missing here is that the MD5-encrypted string should be the password concatened with the username, plus md5 at the beginning.
So for example to create u0 with the password foobar, knowing that md5('foobaru0') is ac4bbe016b808c3c0b816981f240dcae:
CREATE USER u0 PASSWORD 'md5ac4bbe016b808c3c0b816981f240dcae';
and then u0 will be able to log in by typing foobar as the password.
I don't think that there's currently a way to use SHA-256 instead of md5 for PostgreSQL passwords.
I'm not aware of a way to override the default md5 encryption of passwords, but if you have a ROLE (aka "USER") that has an already md5-encrypted password it appears that you can supply that. Verify this using pg_dumpall -g (to see the globals from the cluster)
Eg.
psql postgres
create role foo with encrypted password foobar;
\q
-- View the role from pg_dumpall -g
pg_dumpall -g | grep foo
CREATE ROLE foo;
ALTER ROLE foo WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION PASSWORD 'md5c98cbfeb6a347a47eb8e96cfb4c4b890';
Or get it from:
select * from pg_catalog.pg_shadow;
-- create the role again with the already-encrypted password
psql postgres
drop role foo;
CREATE ROLE foo;
ALTER ROLE foo WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION PASSWORD 'md5c98cbfeb6a347a47eb8e96cfb4c4b890';
\q
-- view the ROLE with the same password
pg_dumpall -g | grep foo
CREATE ROLE foo;
ALTER ROLE foo WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION PASSWORD 'md5c98cbfeb6a347a47eb8e96cfb4c4b890';
Docs for CREATE ROLE
At least from version 10.10, it's possible to use SCRAM-SHA-256 as well.
CREATE USER user_name
WITH PASSWORD 'SCRAM-SHA-256$4096:UunGvPETiX/JNGBvjOgW9A==$CPGNh7/MRfs0ispH9/HSJajOI8Uhp+UCRo/b/ToXIEY=:L6NzxQ3XUeWEeRa+oiuajC9Vgl7wk6ZpHAHl+pv4m00=';
GRANT CONNECT ON DATABASE database_name TO user_name;
(It's important not to forget to GRANT privileges to the new user)
If you want SCRAM to be used by default, you can set the password_cryptography to SCRAM-SHA-256:
ALTER SYSTEM SET password_encryption = 'scram-sha-256';
SELECT pg_reload_conf();
I know it's possible to set the passwords also avoiding SQL statements, this link to the documentation should help. Maybe, this is a bit less verbose.
Anyway, md5 should be avoided when possible, SCRAM is a more robust way to store passwords.
In case you cannot find a way to create the SCRAM string accepted by Postgres, you can let it crate one for you with the following code.
Remember to set the password_encryption to SCRAM
ALTER SYSTEM SET password_encryption = 'scram-sha-256';
SELECT pg_reload_conf();
This cannot be run in a transaction block. If for instance, you're using migration files, you probably have to create two different files just ofr those two commands.
Create a user with the password you need to encode.
CREATE USER tmp_user_to_create_a_password
WITH PASSWORD 'your_password';
Read the password with SCRAM encryption.
SELECT rolpassword
FROM pg_catalog.pg_authid
WHERE rolname='tmp_user_to_create_a_password';
Drop the user
DROP USER IF EXISTS tmp_user_to_create_a_password;
Now you can create your user without using plain text.
CREATE USER user_name
WITH PASSWORD 'SCRAM-SHA-256$4096:3Lctb6GmH15cSO4bjcDsXg==$BSuI1c10J+NZ/Wmx4hwP4TvpdKEO9rl2hekZ8/DVuyA=:j8G9NJ30Xbz3Za2mjXF/j6O3DJbWyqvX886haFe4aCs=';
GRANT CONNECT ON DATABASE database_name TO user_name;
You can now use 'user_name' and 'your_password' to log-in.
Much easier way to to this is:
CREATE USER u0 PASSWORD 'foobar';
select * from pg_catalog.pg_shadow;
Gives passwd: md5ac4bbe016b808c3c0b816981f240dcae
Related
I am launching postgres conatainer by placing sql script in docker-initdb. Everything is running fine. But can someone tell what's the password of my database created with below script?
CREATE DATABASE mydb;
CREATE USER mydbadmin WITH ENCRYPTED PASSWORD 'mypwd';
ALTER DATABASE mydb owner to mydbadmin;
GRANT ALL PRIVILEGES ON DATABASE mydb TO mydbadmin;
GRANT CONNECT ON DATABASE mydb to mydbadmin;
I am not providing any explicit password for DB. What would be default password in this case?
How can I provide my explicit password?
A database cannot have a password.
Only roles (users) can authenticate with the PostgreSQL server, so only they can have a password.
Database has no password, users have passwords. There is no "default password" (i guess that means new users would have pre-set password)
User mydbadmin has the password you have set. Other users will have the password you set when you CREATE USER
Make sure you have necessary settings in pg_hba.conf
If I create a user logged in as postgres to the root db and create a user... it doesn't work. What am I doing wrong?
postgres=> CREATE ROLE myUser WITH LOGIN PASSWORD 'xxx';
CREATE ROLE
postgres=> GRANT CONNECT ON DATABASE myDatabase TO myUser;
GRANT
postgres=> GRANT USAGE ON SCHEMA public to myUser;
GRANT
postgres=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO myUser;
GRANT
When I go to authenticate I get an error.
psql -h $dbURL -U myUser myDatabase
FATAL: password authentication failed for user myUser
The user you created is "myuser", because case is ignored for SQL identifiers not within double quotes, and folded to lower case. But case is not ignored in command-line tools, so you are trying to log in as non-existent user "myUser". Since non-existent users don't have a password hash, password authentication must fail.
You might want to check if you have a .pgpass file present and inspect the environment variables to see if you have set a PGPASSWORD or PGPASSFILE. In any of these cases, psql will not prompt for the password and take it from the file or variable instead - and if what's there is incorrect, it will give you that exact error.
You can
unset the PGPASSWORD or PGPASSFILE variable
get rid of the .pgpass file
remove the entry corresponding to this connection from .pgpass file
correct the value of PGPASSFILE/PGPASSWORD variable or the contents of .pgpass file
use psql with a -W switch making it ignore other settings and always prompt for a password
alter the host-based authentication settings in pg_hba.conf file to change the authentication method or trust a certain type of connection
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;
I imported a postgres database in my local postgres server.
I had to connect to the database (to allows django to retrive data) using the file called setup.local.
There is required to specify: DB_HOST=localhost, DB_NAME, DB_USER, DB_PASSWORD.
DB_HOST is localhost without any doubt. The DB_name is the one I choose importing (psql imported_db < downloaded_DB)
DB_USER is my_name (or I can change the owner ALTER DATABASE imported_db OWNER TO other_name).
The wire thing, for me, is that I have to use the user (either the my_name or other_name) password and not the database password (even if the variable name is DB_PASSWORD).
So the question:
does a psql database have a password or just the roles/users have ones and use them to access the database?
Andrea
Passwords are set for USER and ROLE only. A user may access multiple databases, according to the GRANTs for the ROLE.
See also:
https://www.postgresql.org/docs/10/static/ddl-priv.html
https://www.postgresql.org/docs/10/static/client-authentication.html
https://www.postgresql.org/docs/10/static/user-manag.html
DB_HOST=localhost is a key here. Look into the pg_hba.conf you will find ident against localhost connections most probably.
https://www.postgresql.org/docs/current/static/auth-methods.html#AUTH-IDENT
When ident is specified for a local (non-TCP/IP) connection, peer
authentication (see Section 20.3.6) will be used instead.
https://www.postgresql.org/docs/current/static/auth-methods.html#AUTH-PEER
The peer authentication method works by obtaining the client's
operating system user name from the kernel and using it as the allowed
database user name (with optional user name mapping). This method is
only supported on local connections.
I need to clone role from one postgresql database to another. Is it possible to somehow extract role password hash and set it in another database ? I'd like to avoid any clear password manipulation...
If PostgreSQL thinks you're setting the password with an MD5 hash, it stores it directly. From the docs
If the presented password string is already in MD5-encrypted format, then it is stored encrypted as-is, regardless of whether ENCRYPTED or UNENCRYPTED is specified (since the system cannot decrypt the specified encrypted password string). This allows reloading of encrypted passwords during dump/restore.
you can select password from pg_shadow and use it as per docs, as Eavn told. Or you can use pg_dumpall -g which will basically prepare statements to run with md5 passwords eg. at my machine:
CREATE ROLE r;
ALTER ROLE r WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION NOBYPASSRLS PASSWORD 'md5514f1b439f404f86f77090fa9edc96ce';