jruby/activerecord-jdbc-adapter

How to specify trusted authentication method for Postgresql?

keithrbennett opened this issue · 2 comments

I am porting a Rails 6 Postgres app to JRuby and am getting the following error when trying to perform a DB operation such as rails db:reset:

rails aborted!
ActiveRecord::JDBCError: The server requested password-based authentication, but no password was provided.
arjdbc/jdbc/RubyJdbcConnection.java:529:in `initialize'
/home/kbennett/.rvm/gems/jruby-9.2.13.0/gems/activerecord-jdbc-adapter-60.2-java/lib/arjdbc/abstract/core.rb:21:in `initialize'
...
/home/kbennett/.rvm/gems/jruby-9.2.13.0/gems/railties-6.0.3.3/lib/rails/commands.rb:18:in `<main>'
bin/rails:9:in `<main>'

Caused by:
Java::OrgPostgresqlUtil::PSQLException: The server requested password-based authentication, but no password was provided.
org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:545)
...

In MRI Ruby it works fine. For MRI, in database.yml I specify postgresql as the adapter; for JRuby, jdbcpostgresql. That is the only change I made in database.yml.

default: &default
  adapter: jdbcpostgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: my_database

I think this configuration results in Postgres using "trust" (or is it "peer"?) authentication in MRI, but "password" authentication in JRuby? Why is this, and is there a way to specify "trust" (or "peer"?) authentication with JRuby?

(A description of Postgresql authentication methods is at https://www.postgresql.org/docs/9.1/auth-methods.html.)

Poking around it seems like you should be able to just pass a blank password and it will work, but you will need to make sure the database is set up to trust local IP connections. I believe by default trust is only allowed on local unix sockets.

I think this is more a question of how to do pg "trust" authentication with JDBC, so look around from that perspective.

Thanks, Charlie. For my purposes, I think I'd prefer to specify the username and password rather than change DB settings.

I have this in my Gemfile:

IS_JRUBY = (RUBY_PLATFORM == 'java')
if IS_JRUBY
  ruby '2.5.7'
  gem 'activerecord-jdbc-adapter', '>= 60.2'
  gem 'activerecord-jdbcpostgresql-adapter'
else
  ruby '2.7.1'
  gem 'pg', '>= 0.18', '< 2.0'
end

...and this in my database.yml:

<% IS_JRUBY = (RUBY_PLATFORM == 'java') %>

default: &default
  adapter: <%= IS_JRUBY ? 'jdbcpostgresql' : 'postgresql' %>

and this in my database.yml development and test environment sections:

  <% if IS_JRUBY %>
  username: <%= `whoami` %>
  password: <%= ENV.fetch('POSTGRES_PW') { 'password' } %>
  <% end %>

Does that seem like a reasonable solution? (I do have to rerun bundle when switching Ruby implementations.) Is there a better way to do this?