Configure gssapi to connect PostgreSQL server using AD - postgresql

I'm trying to connect Postgres server with the gssapi protocol. User accounts have been created in Active Directory.
I used the following commands:
postgres#xxxxx:John $ ktutil
ktutil: add_entry -password -p POSTGRES/myserver.domain.com -k 1 -e aes256-cts-hmac-sha1-96
Password for POSTGRES/myserver.domain.com#myad.domain.com
ktutil: write_kt postgres.keytab
ktutil: quit
postgres#xxxxx:John $ klist -k postgres.keytab
Keytab name: FILE:postgres.keytab
KVNO Principal
---- --------------------------------------------------------------------------
1 POSTGRES/myserver.domain.com#myad.domain.com
postgres#xxxxx:John $ kinit john
Password for john#myad.domain.com
postgres#xxxxx:John $ klist
Ticket cache: KEYRING:persistent:26:26
Default principal: john#myad.domain.com
Valid starting Expires Service principal
09/28/2020 14:45:09 09/29/2020 00:45:09 krbtgt/myad.domain.com#myad.domain.com
renew until 10/05/2020 14:45:00
When I try connecting with my admin user, I got this unsuccessful reply.
psql -d postgres -h pgserver -p 5432 -U john#domain.com
psql: GSSAPI continuation error: Unspecified GSS failure. Minor code may provide more information
GSSAPI continuation error: Server not found in Kerberos database
What are the missing steps?

"Server not found in Kerberos database" means the GSSAPI trying to reach the KDC and attempting to login using SPN instead of UPN.
This can be avoided by specifying "isInitiator=false" in JAAS config. Doing this, the incoming token will be decrypted on client side itself (Postgres).
If there is a delegation involved here (which I don't think is), then "isInitiator=true" needs to be set in JAAS config, and SPN must be equal to the UPN of the account to which the SPN is attached.
Check ktpass on windows, it creates Keytab file and also changes user's UPN to the SPN value specified. Similar thing should be done on your setup.

Related

psql: FATAL: PAM authentication failed for user " " aws rds Postgresql

I want to connect to aws rds POSTGRESQL in dev from my own computer.
I followed all the steps on how to do it from bunch of articles:
https://aws.amazon.com/premiumsupport/knowledge-center/rds-postgresql-connect-using-iam/
https://aws.amazon.com/blogs/database/using-iam-authentication-to-connect-with-pgadmin-amazon-aurora-postgresql-or-amazon-rds-for-postgresql/.
The problem is if I create the database in aws console interface, I am able to log in ONLY once.
psql -h database.xxxxxxxx.us-west-2.rds.amazonaws.com -U user_name -d database
Other times I try to log in with the same any other command, I get
psql: FATAL: PAM authentication failed for user "user_name"
First and only time I login, I create a user
CREATE USER user_name WITH LOGIN;
GRANT rds_iam TO user_name;
All other attempts including the other steps logging with the iam token etc, I get an error:
psql: FATAL: PAM authentication failed for user "user_name"
If I delete the database from aws console interface and then create a brand new one, I am able to log in only ONCE and and then get the error no matter what I do.
nc Command gives me Connection succeeded at all times I run it:
nc -zv DB-instance-endpoint port
The commands I am using :
export RDSHOST="database.xxxxxxxx.us-west-2.rds.amazonaws.com"
export PGPASSWORD="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --region us-west-2 --username user_name)"
I get the error if I use the PGPASSWORD in pgAdmin window.
Also, I am trying to connect from the the terminal either mine or ssh into ec2, I use this command:
psql "host=$RDSHOST port=5432 sslmode=verify-full sslrootcert=./rds-combined-ca-bundle.pem dbname=database user=user_name"
and I still get the same error
psql: FATAL: PAM authentication failed for user "user_name"
or
If I use another command, without the .pem certificate
psql --host=database.xxxxxxxx.us-west-2.rds.amazonaws.com --port=5432 --username=user_name --password --dbname=database
Then it asks me for a password and Then I get this error
psql: error: FATAL: PAM authentication failed for user "user_name"
FATAL: pg_hba.conf rejects connection for host "222.22.22.22", user "user_name", database "database", SSL off
"222.22.22.22" is My Ip, I changed it of course.
I attached all the required and all the RDS access Policies to my user and still getting this error.
I am just no sure what to do at this point as I went through every single article and cannot find a solution.
I had a similar problem and after some playing around with psql utility I found the reason for these errors. You shall export your temporary database password/token to shell of the machine/service etc where the connection will be initiated from.
So, if psql connection is initiated from Bastion, the below command should also be run on the same Bastion server.
export PGPASSWORD="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --region us-west-2 --username user_name)"
or generate it elsewhere and export its value as
export PGPASSWORD="temporary_token_generated_for_user_name"
With this exported $PGPASSWORD variable, it psql should connect straight away, without promting for any additional passwords
I found the solution finally. So if anyone has the same issue and goes nuts about it, here is the solution:
If everything is working as I described above and the only error you get is PAM.. then:
your config file is not properly set up. It does not have the username you are trying to connect, the region, and the keys.
~/.aws/config
[profile PROFILE_NAME]
output=json
region=us-west-1
aws_access_key_id=foo
aws_secret_access_key=bar
Here is the link to the question on how to set it up:
AWS : The config profile (MyName) could not be found

Connecting to Cloud SQL using an IAM user

I'm failing to test the ability to use an IAM user in Google Cloud's PostgreSQL offering.
Here's my thinking process:
I've set respective flag on my PostgreSQL instance on Google Cloud:
$ gcloud sql instances describe [MY_DB_INSTANCE] --format json | jq '.settings.databaseFlags'
[
{
"name": "cloudsql.iam_authentication",
"value": "on"
}
]
$
I have an IAM user, which I've created in the database instance:
gcloud sql users create [MY_EMAIL] --instance=[MY_DB_INSTANCE] --type=CLOUD_IAM_USER
$ gcloud sql users list --instance [MY_DB_INSTANCE] | grep CLOUD_IAM_USER
[MY_EMAIL] CLOUD_IAM_USER
$
I get an authentication error when I try to connect to the DB using either of commands below. In both cases I use the output of gcloud auth print-access-token as my password:
this method adds my IP to allowlist:
$ gcloud sql connect [MY_DB_INSTANCE] --database=[DB_NAME] --user=[MY_EMAIL]
Allowlisting your IP for incoming connection for 5 minutes...done.
Connecting to database with SQL user [MY_EMAIL]. Password:
psql: error: FATAL: Cloud SQL IAM user authentication failed for user "[MY_EMAIL]"
FATAL: pg_hba.conf rejects connection for host "100.200.300.400", user "[MY_EMAIL]", database "[MY_EMAIL]", SSL off
$
May or may not be related to the failure, but the error message is confusing here. The last line states ...database "[MY_EMAIL]", while clearly I am not attempting to connect to the database of the same name as my email; I am connecting to a database with a very specific name, e.g. [DB_NAME].
Upd. As of right now the "Known issues" page lists acknowledgement of this:
The following only works with the default user ('postgres'): gcloud sql connect --user
this method uses Cloud SQL Proxy:
$ gcloud beta sql connect [MY_DB_INSTANCE] --database=[DB_NAME] --user=[MY_EMAIL]
Starting Cloud SQL Proxy: [/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/bin/cloud_sql_proxy -instances my-project-id:europe-west1:[MY_DB_INSTANCE]=tcp:9470 -credential_file /Users/eugene/.config/gcloud/legacy_credentials/[MY_EMAIL]/adc.json]]
2021/01/26 16:35:03 Rlimits for file descriptors set to {&{8500 9223372036854775807}}
2021/01/26 16:35:03 using credential file for authentication; path="/Users/eugene/.config/gcloud/legacy_credentials/[MY_EMAIL]/adc.json"
2021/01/26 16:35:04 Listening on 127.0.0.1:9470 for my-project-id:europe-west1:[MY_DB_INSTANCE]
2021/01/26 16:35:04 Ready for new connections
Connecting to database with SQL user [MY_EMAIL].Password:
psql: error: FATAL: Cloud SQL IAM user authentication failed for user "[MY_EMAIL]"
$
If I check the access logs from Cloud Console, for both login attempts I see the same error message:
2021-01-26 14:20:11.988 UTC [594848]: [2-1] db=[DB_NAME],user=[MY_EMAIL] DETAIL: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
At this point I am quite lost.
Perhaps my expectations are not aligned with how connecting to a DB should work. I expected that:
the would be no need to enter a password (e.g. the value of gcloud auth print-access-token) at all in the first place, as gcloud would generate and use a password for me automagically,
in case entering the password manually (by copy-pasting the output from gcloud auth print-access-token command from the paste-buffer) is necessary it would work (while it doesn't).
I was hoping that by relying on the IAM auth mechanism of authenticating to the DB, I would be able to avoid the necessity to create a user and set him with a password using psql (or similarly using gcloud sql users create ... --type=BUILD_IN).
What is it that I am possibly missing?
Upd. I am able to successfully connect if, instead of using gcloud sql command, I run the proxy and use the command directly:
$ cloud_sql_proxy -instances my-project-id:europe-west1:[MY_DB_INSTANCE]=tcp:9470
2021/01/26 17:29:56 Rlimits for file descriptors set to {&{8500 9223372036854775807}}
2021/01/26 17:29:56 Listening on 127.0.0.1:9470 for my-project-id:europe-west1:[MY_DB_INSTANCE]
2021/01/26 17:29:56 Ready for new connections
$ env PGPASSWORD=(gcloud auth print-access-token) psql --host 127.0.0.1 --port 9470 --username=[MY_EMAIL] --dbname=[MY_DB]
psql (13.1, server 13.0)
Type "help" for help.
[MY_DB]=>
I was having the same issue. The key piece of information that is not well documented is that the Cloud SQL Proxy tool will automatically request fresh tokens for you behind the scenes. So you don't need to pass the token in manually, you just need to point whatever client you want to use at the Cloud SQL Proxy service.
To activate this mode, you need to specify the -enable_iam_login command line option, like so:
./cloud_sql_proxy -instances=[project]:[zone]:[server]=tcp:5432 -enable_iam_login
It will generate access keys for whatever user is currently authenticated using gcloud auth login
Be sure to disable sslmode when connecting to the Cloud SQL Proxy service. It handles its own encryption so if the postgres client is also trying to encrypt the connection will timeout. Since the Cloud SQL Proxy service is handling authentication, you only need to specify the user in your postgres client.
psql "host=127.0.0.1 dbname=postgres user=[the IAM email account] sslmode=disable"
It shouldn't ask for a password. If it does, just leave it blank.
I found the Cloud SQL Proxy readme more useful than the official documentation: https://github.com/GoogleCloudPlatform/cloudsql-proxy/blob/main/README.md
After playing around with it, was able to pick up the proper command for connection. Here it is:
env PGPASSWORD=(gcloud auth print-access-token) gcloud beta sql connect [MY_DB_INSTANCE] --user=[MY_EMAIL] --database=[MY_DB]
The key thing here, it seems, was specifying the PGPASSWORD variable for the process and then, when prompted to enter the password, just hit enter 🤯
What I also tried, and what appears to be a bug in gcloud sql, is connecting via a non-beta gcloud sql connect:
$ env PGPASSWORD=(gcloud auth print-access-token) gcloud sql connect [MY_DB_INSTANCE] --user=[MY_EMAIL] --database=[MY_DB]
Allowlisting your IP for incoming connection for 5 minutes...done.
Connecting to database with SQL user [MY_EMAIL].Password:
psql: error: FATAL: database "[MY_EMAIL]" does not exist
$
Note how it says database "[MY_EMAIL]" does not exist, while the database is specified as a command line flag --database=[MY_DB]. Seems like a bug to me.

pgbouncer: user,password per pool

I'm trying to setup a pgbouncer pool that connects to the database using a pool definition that includes a user and password.
Subsequently each client application should connect using a different user and password. The idea is that one pool is shared by multiple client users.
Is that possible?
Here's my setup:
pgbouncer.ini
[databases]
testpool = host=testpool.mycompany.com dbname=db1 port=544 user=company_dbo password=company123 max_db_connections=20
[pgbouncer]
auth_type = plain
auth_file = /etc/pgbouncer/users.txt
users.txt
"test_user" "test123"
When I try to connect I get below error
$ export PGPASSWORD='test123';psql -h localhost -U test_user -d db1 -p 5442
psql: ERROR: password authentication failed for user "test_user"
And the logs say
2019-03-03 16:04:02.668 1 LOG C-0x2022000: db1/test_user#172.17.0.1:33204 login attempt: db=db1 user=test_user tls=no
2019-03-03 16:04:02.719 1 LOG S-0x2026fd0: db1/test_user#10.1.0.118:5442 new connection to server (from 172.17.0.2:58920)
2019-03-03 16:04:02.762 1 WARNING server login failed: FATAL password authentication failed for user "test_user"
It appears that pgbouncer tries to login to the database using the client user and password, rather than the user and password specified in the [databases] section.
auth_file is used to authenticate the user with pgBouncer, not to provide a different password for use with the database. pgBouncer will use the password it received from the client to log into PostgreSQL.
I don't know what problem you are trying to solve this way, but perhaps you can use trust authentication between pgBouncer and PostgreSQL and leave the burden of authentication entirely with pgBouncer.
There is no way to “change identity” in pgBouncer.

PAM authentication + pgAdmin fails remotely, but locally works

I've been trying to configure postgresql with PAM on a Red hat server so that I can get remote access to the server via pgAdmin and use local (server) authentication with PAM.
I have edited the pg_hba.conf file and changed the appropriate line:
host postgres all 0.0.0.0/0 md5
and added this one:
host pam_testing all 0.0.0.0/0 pam pamservice=postgresql95
Moreover I created database user with the same username as I use to log in with putty (no password, simply create user xxx)
When I try to log in remotely with pgAdmin to postgres database (using md5) with my database user everything works smoothly.
But When I try to connect (also remotely, with pgAdmin) to pam_testing database with my server username (to which I log in via ssh using putty) and give the password I get the following error:
Error connecting to the server: FATAL: PAM authentication failed for
user XXX
BUT! When I log in locally to pam_testing while connected via putty it works! My system user gets logged in and authenticated without any problems. And it only happens for users, which I added to the database using create user.
I'm guessing it must be some kind of authentication issue (with the server maybe? It belongs to company and I don't know what other authentication methods it uses) but I'm not sure. Any ideas?
System: Red hat 6.8,
Postgresql: 9.5
Thanks in advance!
Do systemctl | grep unix_chkpwd and if you see lines like these
unix_chkpwd[13081]: check pass; user unknown
unix_chkpwd[13081]: password check failed for user (<username>)
then you've encountered the same problem I did.
To solve it you need to give postgres user read permissions to /etc/shadow file. You can do this via acl: setfacl -m g:postgres:r /etc/shadow, or by creating some group, giving it this permission and then adding postgres to it. Then do systemctl restart postgresql.service.
The underlying mechanics of authenticating with pam is described in this post. The key moment is the following: unix_chkpwd runs under the uid of the process which wants to authenticate someone, so if it's not root (and /etc/shadow is used which I believe is the common case), it can't do its job.

psql: FATAL: Peer authentication failed for user "dev"

when i create a new user, but it cannot login the database.
I do that like this:
postgres#Aspire:/home/XXX$ createuser dev
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
then create a database:
postgres#Aspire:/home/XXX$ createdb -O dev test_development
after that, I try psql -U dev -W test_development to login, but get the error:
psql: FATAL: Peer authentication failed for user "dev"
I tried to solve the problem but failed.
Try:
psql -U user_name -h 127.0.0.1 -d db_name
where
-U is the database user name
-h is the hostname/IP of the local server, thus avoiding Unix domain sockets
-d is the database name to connect to
This is then evaluated as a "network" connection by Postgresql rather than a Unix domain socket connection, thus not evaluated as a "local" connect as you might see in pg_hba.conf:
local all all peer
Your connection failed because by default psql connects over UNIX sockets using peer authentication, that requires the current UNIX user to have the same user name as psql. So you will have to create the UNIX user dev and then login as dev or use sudo -u dev psql test_development for accessing the database (and psql should not ask for a password).
If you cannot or do not want to create the UNIX user, like if you just want to connect to your database for ad hoc queries, forcing a socket connection using psql --host=localhost --dbname=test_development --username=dev (as pointed out by #meyerson answer) will solve your immediate problem.
But if you intend to force password authentication over Unix sockets instead of the peer method, try changing the following pg_hba.conf* line:
from
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
to
# TYPE DATABASE USER ADDRESS METHOD
local all all md5
peer means it will trust the identity (authenticity) of UNIX user. So not asking for a password.
md5 means it will always ask for a password, and validate it after hashing with MD5.
You can, of course, also create more specific rules for a specific database or user, with some users having peer and others requiring passwords.
After changing pg_hba.conf if PostgreSQL is running you'll need to make it re-read the configuration by reloading (pg_ctl reload) or restarting (sudo service postgresql restart).
* The file pg_hba.conf will most likely be at /etc/postgresql/9.x/main/pg_hba.conf
Edited: Remarks from #Chloe, #JavierEH, #Jonas Eicher, #fccoelho, #Joanis, #Uphill_What comments incorporated into answer.
Peer authentication means that postgres asks the operating system for your login name and uses this for authentication. To login as user "dev" using peer authentication on postgres, you must also be the user "dev" on the operating system.
You can find details to the authentication methods in the Postgresql documentation.
Hint: If no authentication method works anymore, disconnect the server from the network and use method "trust" for "localhost" (and double check that your server is not reachable through the network while method "trust" is enabled).
When you specify:
psql -U user
it connects via UNIX Socket, which by default uses peer authentication, unless specified in pg_hba.conf otherwise.
You can specify:
host database user 127.0.0.1/32 md5
host database user ::1/128 md5
to get TCP/IP connection on loopback interface (both IPv4 and IPv6) for specified database and user.
After changes you have to restart postgres or reload it's configuration.
Restart that should work in modern RHEL/Debian based distros:
service postgresql restart
Reload should work in following way:
pg_ctl reload
but the command may differ depending of PATH configuration - you may have to specify absolute path, which may be different, depending on way the postgres was installed.
Then you can use:
psql -h localhost -U user -d database
to login with that user to specified database over TCP/IP.
md5 stands for encrypted password, while you can also specify password for plain text passwords during authorisation. These 2 options shouldn't be of a great matter as long as database server is only locally accessible, with no network access.
Important note:
Definition order in pg_hba.conf matters - rules are read from top to bottom, like iptables, so you probably want to add proposed rules above the rule:
host all all 127.0.0.1/32 ident
While #flaviodesousa's answer would work, it also makes it mandatory for all users (everyone else) to enter a password.
Sometime it makes sense to keep peer authentication for everyone else, but make an exception for a service user. In that case you would want to add a line to the pg_hba.conf that looks like:
local all some_batch_user md5
I would recommend that you add this line right below the commented header line:
# TYPE DATABASE USER ADDRESS METHOD
local all some_batch_user md5
You will need to restart PostgreSQL using
sudo service postgresql restart
If you're using 9.3, your pg_hba.conf would most likely be:
/etc/postgresql/9.3/main/pg_hba.conf
This works for me when I run into it:
sudo -u username psql
I simply had to add -h localhost
The easiest solution:
CREATE USER dev WITH PASSWORD 'dev';
CREATE DATABASE test_development;
GRANT ALL PRIVILEGES ON DATABASE test_development to dev;
ALTER ROLE dev CREATEROLE CREATEDB;
In my case I was using different port. Default is 5432. I was using 5433. This worked for me:
$ psql -f update_table.sql -d db_name -U db_user_name -h 127.0.0.1 -p 5433
For people in the future seeing this, postgres is in the /usr/lib/postgresql/10/bin on my Ubuntu server.
I added it to the PATH in my .bashrc file, and add this line at the end
PATH=$PATH:/usr/lib/postgresql/10/bin
then on the command line
$> source ./.bashrc
I refreshed my bash environment. Now I can use postgres -D /wherever from any directory
pg_dump -h localhost -U postgres -F c -b -v -f mydb.backup mydb
Try in terminal:
>> psql -U role_name -d database -h hostname.<domain>.com -W