Non-superuser cannot connect if the server does not request a password while using dblink - postgresql

I want to do some cross database references in my application. Briefly, i have two databases called meta and op. I want to do some select query from meta to a table in op database like below but getting the below error. I tried with password and without password. by the way caixa user is a non-super user and my target server (op db server is having MD5 authentication mode.)
meta=> select * from dblink('dbname=op password=caixa','SELECT op_col from op_table') AS t(op_col varchar);
ERROR: password is required
DETAIL: Non-superuser cannot connect if the server does not request a password.
HINT: Target server's authentication method must be changed.
What the HINT in the above error message suggests? do i need to change the server's auth mode? Without changing the server's auth mode (MD5) can't i run the above query?

From documentation:
Only superusers may use dblink_connect to create
non-password-authenticated connections. If non-superusers need this
capability, use dblink_connect_u instead.
and
dblink_connect_u() is identical to dblink_connect(), except that it
will allow non-superusers to connect using any authentication method.
That means your dblink call is using dblink_connect implicitly. Use dblink_connect_u instead or change your auth method to e.g. md5.
Note that you also need grant execute privilege to caixa role, for example by:
GRANT EXECUTE ON FUNCTION dblink_connect_u(text) TO caixa;
GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO caixa;
Working example (after GRANT):
meta=> SELECT dblink_connect_u('conn1', 'dbname=op');
meta=> SELECT * FROM dblink('conn1','SELECT op_col from op_table')
AS t(op_col varchar);
op_col
--------
aaa
bbb
ccc
(3 rows)
meta=> SELECT dblink_disconnect('conn1');
EDIT:
Sorry for slightly misleading answer. Of course you don't need dblink_connect_u for md5 authenticated
connection. There is one possibility I see. PostgreSQL has two different connection types: host and local.
Running:
psql -h localhost ..
incorporates host connection, but
dblink_connect('mycon','dbname=vchitta_op user=caixa password=caixa');
uses local type, so if you have non-password method for local connection (for example ident method or trust), then it returns
ERROR: password is required
DETAIL: Non-superuser cannot connect if the server does not request a password.
HINT: Target server's authentication method must be changed.
Check
dblink_connect('mycon','hostaddr=127.0.0.1 dbname=vchitta_op user=caixa password=caixa')
for host connection. For clarity if possible please post your pg_hba.conf.
I also checked what about CONNECT privilege on vchitta_op DB, but error message is different:
REVOKE CONNECT ON DATABASE vchitta_op FROM PUBLIC;
REVOKE CONNECT ON DATABASE vchitta_op FROM caixa;
SELECT dblink_connect('mycon','dbname=vchitta_op user=caixa password=caixa');
ERROR: could not establish connection
DETAIL: FATAL: permission denied for database "vchitta_op"
DETAIL: User does not have CONNECT privilege.

There's a workaround that did the trick for me. Non-superusers can execute functions with privileges of a superuser if "SECURITY DEFINER" option is set.
( http://www.postgresql.org/docs/9.1/static/sql-createfunction.html )
That means you can create a function (with superuser owner and SECURITY DEFINER option) that does cross-database manipulation (using dblink() without password) and execute it under non-superuser

I have a similar but a different issue. I have two servers with identical postgres.conf and pg_hba.conf. However one on version 9.2.3 and one on 9.2.4
9.2.3
pg_hba.conf has
local all dblinkuser trust
then I connect to database using any ordinary user
theater_map=# select dblink_connect('dbname=TheaterDB user=dblinkuser password=dbl123');
dblink_connect
----------------
OK
(1 row)
success in connection.
9.2.4
my pg_hba.conf has the same entry as above
theater_map=> select dblink_connect('dbname=TheaterDB user=dblinkuser password=dbl123');
ERROR: password is required
DETAIL: Non-superuser cannot connect if the server does not request a password.
HINT: Target server's authentication method must be changed.
NOW
I change my pg_hba.conf on 9.2.4 as below
local all dblinkuser md5
and restart postgres
theater_map=> select dblink_connect('dbname=TheaterDB user=dblinkuser password=dbl123');
dblink_connect
----------------
OK
(1 row)
I Checked the change log between versions 9.2.3 and 9.2.4 but could not find any details.
note: changing auth method from trust to md5 on 9.2.3 does not make any difference and still works.

I found this question googling for same error message, though I use fdw extension rather than db_link. Following steps helped to fix my problem:
find user has no password and set it on - alter user myuser with password 'mypassword'
find authentication method is trust and set it to md5 - vim /var/lib/postgresql/data_/pg_hba.conf
reload pg_hba.conf - SELECT pg_reload_conf(); from psql (log out and log in to verify password is required)
(optionally try access from remote machine, db browser etc.)
setup foreign server and its user mapping - CREATE USER MAPPING FOR CURRENT_USER SERVER myserver OPTIONS (user 'myuser', password 'mypassword');

PostgreSQL 11.10
SELECT ext.column1 from
dblink('hostaddr=192.192.192.192 dbname=yourDbname user=yourUsername password=yourpass',
'select a."column1" from "Table1" a where a."column2"=2')
as ext(column1 text)

Related

Postgres 14.3 created user authentication failed

I am new to this SQL stuff and I recently installed Postgres 14.3 on my windows machine as part of an online learning requirement. I created a database and a user to connect to the database in the following lines from the shell:
postgres=# create database staff;
postgres=# create user Naruto with encrypted password 'secret';
postgres=# grant all privileges on database staff to Naruto;
postgres=# \c staff Naruto;
password for user Naruto:
After inputting the password I get an error message like this
connection to server at "local host" (127.0.0.1), port 5432 failed: FATAL: password authentication failed for user "Naruto"
Previous connection kept
Whereas the video description from which I am taking tutorials didn't ask for a password prompt but it connected to the database straight up with the designated user.
I have tried numerous suggestions on stack overflow but still, no breakthrough in any way. I'd appreciate any hint because I haven't recorded any progress with my learning recently. Thanks!
The user you created is named "naruto", not "Naruto", because identifiers are case-folded when not inside double quotes. In the \c, however, it is not case folded because at that point is not an identifier, it is more like a command line argument.
Depending on the contents of pg_hba.conf, PostgreSQL might not tell you when you try to login as a nonexistent user. Instead it goes through the motions of authentication, even though authentication is doomed to fail. This is so that an attacker cannot determine which users exist by trying a bunch and looking at the error messages. The real reason for failure is published to the db server's log file, so if you had looked there you should have seen role "Naruto" does not exist.
If you want the user to have a capital letter, put double quotes around the name when you do the CREATE. Alternatively given that you already created the user without the cap, connect to it using the lower-case spelling. And either way, look in the servers log file when you run into problems.
I hope this might help someone in the future. All I had to do was fix the caps for the user I initially created as 'Naruto' and it got executed smoothly.
postgres=# create database staff;
postgres=# create user naruto with encrypted password 'secret';
postgres=# grant all privileges on database staff to naruto;
postgres=# \c staff naruto;

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.

Can't connect to a database with another user

I'm using Postgresql, and I have a database named django_db and a user manuel. I want to connect to this database by this user, I tried this \c django_db manuel but I get this error:
FATAL: Peer authentication failed for user "manuel"
Previous connection kept
How can I solve this problem?
Make sure the user manuel has access to the database django_db in the pg_hba.conf file, e.g.
host django_db manuel your_ip_adress md5
Or if you prefer to give this user access to all databases
host all manuel your_ip_adress md5
After modifying your pg_hba.conf you have to either restart postgres or simply reload the file using the following function:
SELECT pg_reload_conf();
Unless you have a user mapping in place, only the OS user named 'manuel' can connect as the PostgreSQL user named 'manuel'. This is what "peer authentication" means.
You have many choices here. Try this as an OS user named 'manuel', or change from peer to some other type of authentication (in pg_hba.conf), or create a pg_ident.conf file (and then configure pg_hba.conf to use it) that allows the OS user you actually are to login as PostgreSQL user 'manuel'.

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.

Postgres: Using dblink to make remote connection

We got a Postgres database credentials (with SSL on) from our contractor, which allow us to connect to the DB using pdAdmin 3. The DB is read-only (can't do pg_dump) to us and basically the contractor will not grant us more privileges.
We need to fetch some data from this remote DB to our local DB. So I wanted to use dblink to perform this task.
I run this on psql:
insert into shifts select * from dblink('hostaddr=remote_addr port=9000 dbname=production user=user password=passwd', 'select user_id, location_id from shifts') as t1(user_id integer, location_id integer);
Then I got:
ERROR: password is required DETAIL: Non-superuser cannot connect if
the server does not request a password. HINT: Target server's
authentication method must be changed.
Since I am new to Postgres and dblink, I have no idea why it is complaining there is no password. And I wonder, to do a dblink connection, does the remote database needs to grant any more privileges?
If the pdAdmin 3 is able to connect to the remote DB with the credentials, what should I do to make dblink work?
Thanks!
Yes only superuser can provide you to the facility to connect through DBLINK
just run this command below whether you are able to connect to database
SELECT dblink_connect('myconn', 'dbname=postgres');
SELECT dblink_connect('myconn', 'hostaddr=remote_addr port=9000 dbname=production user=user password=passwd');
just give the name of database u want to connect after dbname
You can connect
dblink_connect_u
dblink_connect_u() is identical to dblink_connect(), except that it
will allow non-superusers to connect using any authentication method.
Link on postgres site is
dblink
For Superuser ask them to create extension
CREATE EXTENSION dblink;
for your database or schema .