Postgres unencrypted keyword is no longer supported - postgresql

When executing this postgres command:
EXECUTE 'CREATE USER myuser WITH UNENCRYPTED PASSWORD ''my+password''';
I see the error:
RoundhousE encountered an error.
Npgsql.PostgresException (0x80004005): 0A000: UNENCRYPTED PASSWORD is no longer supported
Is there a workaround for this, or will the password need to be manually encrypted and supplied without the UNENCRYPTED keyword?

No. All you have to do is to omit the UNENCRYPTED.
You can supply both encrypted and unencrypted passwords that way, and PostgreSQL can tell the difference automatically.

PostgreSQL 10+ no longer support user creation with UNENCRYPTED password,
create it with ENCRYPTED:
CREATE USER myuser WITH ENCRYPTED PASSWORD ''my+password''

Related

Authentication error after using stored procedure for creating new db user

I'm having this problem in postgres and I cannot find my way out.
For our key-users to create user accounts in our postgres database (Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1074-azure x86_64)), I created a stored procedure that creates a user with a password.
This is the code for the stored procedure:
CREATE OR REPLACE PROCEDURE geodata_create_user(
username CHARACTER VARYING,
password CHARACTER VARYING
)
LANGUAGE PLPGSQL SECURITY DEFINER
AS
$$
DECLARE
user_to_create CHARACTER VARYING;
BEGIN
-- Check name and create user
IF (username like 'user%') THEN
user_to_create := username;
ELSE
user_to_create := 'user_' || username;
END IF;
PERFORM create_role_if_not_exists (user_to_create);
-- Set password and assign geodata_user role to user
EXECUTE format('ALTER ROLE %I WITH LOGIN PASSWORD ''%I''', user_to_create, password);
EXECUTE format('GRANT another_role TO %I', user_to_create);
end;
$$;
GRANT ALL ON PROCEDURE geodata_create_user TO some_group_role;
If I test it (we have a dev cluster and an acc/prod cluster), it works fine.
The problem is that if one of the key-users creates a new user using this procedure, the user is created yet cannot login using the supplied password.
Following suggestion in pgAdmin and terminal: FATAL: password authentication failed for user to login using peer logon, I tried logging in on psql using the psql -U newuser command it tells me FATAL: Peer authentication failed for user
Then, following suggestion in psql: FATAL: Peer authentication failed for user "dev" logging on the psql using psql -U newuser -d mydbname -h 12.345.678.910 and it replies (after feeding the password created for the user):
Password for user newuser:
psql: error: connection to server at "12.345.678.910", port 8765 failed: could not initiate GSSAPI security context: Unspecified GSS failure. Minor code may provide more information: Server postgres/12.345.678.910#CFSERVICES.COM not found in Kerberos database
connection to server at "12.345.678.910", port 8765 failed: FATAL: password authentication failed for user "newuser"
connection to server at "12.345.678.910", port 8765 failed: FATAL: no pg_hba.conf entry for host "12.345.678.910", user "newuser", database "mydbname", SSL off
I do have a little database experience, however, this kind of stuff is way out of my league. Any one any idea on what goes wrong here? Is there an obvious error in my script? Or might it be a security issue (we use certificates to access the database server when approaching the database server through psql directly, yet usually we set up connections to the database using DBeaver where there is no need to use SSL or SSH Tunnel or certificates or so).
Hope someone can help me out on this.
Regards, Helmoet.
Your format() function is wrong, because a password is not a SQL identifier (which is what %I is for). This will result in it being escaped incorrectly at least in some cases. For example, if the password has a space or a dash in it (or other characters I don't know off the top of my head), this will cause the whole password to be surrounded by literal double quotes. Then the password would work, but you need to specify the double quotes, which is surely not what you would be expecting.
So it should instead look like this, using %L not %I:
EXECUTE format('ALTER ROLE %I WITH LOGIN PASSWORD %L', user_to_create, password);
Your original code would work for passwords that didn't have any of the special symbols in them, so maybe that is why it tested fine.

pgbouncer and scram-sha-256 setup

I was able to get SCRAM-SHA-256 authentication to work with pgpool, but I haven't been able to find a good example how to set this up in pgbouncer. I'm trying to use auth_query. In postgres, the user that pgbouncer will connect as has the password encrypted and stored in SCRAM-SHA-256. But I don't know how to create the entries in userlist.txt. This is supposed to be the format:
SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
What exactly are the storedkey and serverkey and how do I generate those? Which tools can I use to create this? In pgpool, I can use pg_enc but I don't see anything for pgbouncer.
You don't construct the SCRAM hashed password yourself, you get it by querying the pg_authid table in the PostgreSQL database:
SELECT rolpassword
FROM pg_authid
WHERE rolname = 'pgbouncer';
However, as the documentation says:
The passwords or secrets stored in the authentication file serve two purposes. First, they are used to verify the passwords of incoming client connections, if a password-based authentication method is configured. Second, they are used as the passwords for outgoing connections to the backend server, if the backend server requires password-based authentication (unless the password is specified directly in the database's connection string). The latter works if the password is stored in plain text or MD5-hashed. SCRAM secrets can only be used for logging into a server if the client authentication also uses SCRAM, the PgBouncer database definition does not specify a user name, and the SCRAM secrets are identical in PgBouncer and the PostgreSQL server (same salt and iterations, not merely the same password). This is due to an inherent security property of SCRAM: The stored SCRAM secret cannot by itself be used for deriving login credentials.
So if that user is used as auth_user, you cannot use a SCRAM hashed password for that user, but you have to use the clear text password.

Why Is Knex.js Failing on Password Authentication When My Database Has No Password?

I'm trying to connect to my database using Knex like so:
const client = knex({
client: 'postgresql',
connection: {
host: '127.0.0.1',
user: 'me',
database: 'my_db'
}
});
client('some_table').then(console.log);
When I created the database (using createdb my_db at the command line) I set no password. At the command line I can run psql -d my_db and it works just fine.
However, when I try to use Knex, I get an error:
Unhandled rejection error: password authentication failed for user "me"
This happens whether I set a null password, an empty string ('') password, or leave the field off of the configuration entirely.
Can anyone explain why Knex insists on failing password authentication ... when there is no password (and when I can connect without one at the command line just fine)?
PostgreSQL does not permit login based on the presence/absence of a password. Rather, all login authentication is handled via pg_hba.conf. In your particular case--creating the me user without a password (or using null or '', as you would describe it)--the absence of the password doesn't necessarily allow your user to log in. In fact, setting no password will not allow that user to log in unless pg_hba.conf was set to some password-less setting (i.e., peer or trust).
If you want password-less login for the me user (I assume for testing/development purposes, as having password-less login is not good security practice in production), you could simply set trust-level authentication in pg_hba.conf:
#conn_origin database user ip_mask auth_method
host all me 0.0.0.0/0 trust
The more secure method of implementing password-less authentication would be to use a .pgpass file or set the PGPASSWORD environment variable. Seeing that you are trying to use knex.js, you may be better off with tweaking pg_hba.conf as above. Again, I don't know what your intentions are, but please be safe out there ;)
Disclosure: I work for EnterpriseDB (EDB)

postgres uses a database password or a user password

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.

Set postgres password with hash

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';