How to securely connect to PostgreSQL database, with Ruby? - ruby

I feel uncomfortable saving my password in a file:
require 'pg'
conn = PG::Connection.open(host: 'server.example.com', password: 'hello_everyone')
Also, is there a way to determine or ensure that the transmission is encrypted? I am just worried about the implications of running my app locally, when it must connect to a remote database (I am worried about all the data, including the authentication credentials, being sent in the clear).

Regarding the password:
I would recommend setting it in an ENV variable. Take a look at dotenv gem. Basically, you are going to be able to do something like:
require 'pg'
conn = PG::Connection.open(host: ENV['database_host'], password: ENV['database_password'])
The values that are loaded into ENV will be stored in a file (.env) which you should not commit.
Regarding data encryption
You should take a look at SSH tunneling to connect to the remote DB.

Related

Connect to Heroku Postgres through external application

I have a Heroku Ruby app, and I want to access the DB through Navicat, or pgAdmin, or similar. However, the thing that Heroku gives me as a DB URL doesn't seem to be a valid URL.
Heroku tells me to use: heroku config:get DATABASE_URL -a your-app However, that gives me something of the form
postgres://HUGE:STRINGOF#GIBERISH.compute-1.amazonaws.com:5432/MORECHARACTERS
which doesn't look like a valid URL to me, and both Navicat and pgAdmin fail to connect.
How can I use this value to connect to my database?
That "huge string of gibberish" is a completely valid URL.
postgres is the scheme, just like https is a scheme.
What you have marked as HUGE is your username and what you have marked as STRINGOF is your password. Together, they make up the userinfo subcomponent.
GIBERISH just is part of the domain, 5432 is the port, and MORECHARACTERS is the name of the database.

ORA-12541 TNS :no listener on 1 specific remote database, but not on others

Some context: I'm setting up an environment to run some Ruby code our Lead wrote to connect to some remote Databases. I'm using Win10 and have WSL installed. I have installed SQL*Plus, docker, and Ruby, and am sure I have installed all the dependent gems (actually at this point I know for a fact its not a ruby problem). I'm using Docker to use a pre-built image of an Oracle Database, and I have populated it with data.
Obfuscated company DB information:
'Broken' DB (TNS no listener)
Username: W-WORK-DEV
Password: password
Host: host1
Port: 999
SID: W-WORK-DB.tech.company
'Working' DB (can connect just fine)
Username: C-OLD-DEV
Password: password
Host: host2
Port: 999
SID: C-OLD-DB.tech.company
Please note the names I have provided here are purely for obfuscation, they do not represent anything about age or even config. They are essentially the same, just different databases on different hosts. Also note this is a corporate company and would have a lot of base infrastructure for their internal network.
The issue I am having is that with the specific database I am working on, I cannot connect to it. I connect to the company intranet via a VPN (I work offsite) and have issues connecting to WORK-DB.tech.company, though I can connect to C-OLD-DB.tech.company. Methods I have tried to connect with:
Oracle SQL Developer
I have inputted all the correct jdbc strings and username / password. Have even asked other people to attempt to connect (at least 3 others). They can all access C-OLD-DB as well as W-WORK-DB. When using this method, I get The network adapter could not establish the connection.
Side note: I'm fairly sure I have connected to the DB just fine in the past, though I can't be certain because I'm fairly new to this team and have only accessed it once, if that.
SQL*Plus via WSL
I installed SQL*Plus because I think Ruby was accessing it in some capacity when running the script. I got to the point where the script was able to connect to my local docker Database, but when it tried to connect to the remote database, it would return TNS: no listener. I attempted this using sqlplus as well and got the same error.
Example:
sqlplus C-OLD-DEV/password#host2:999/C-OLD-DB.tech.company
This command works and connected to the DB jsut fine.
sqlplus W-WORK-DEV/password#host1:999/W-WORK-DB.tech.company
This command gave me TNS: no listener.
During my research I had found mentions about tnsnames.ora, sqlnet.ora, and listener.ora. I have found relevant files around the company intranet and attempted to use them in my own personal environment to no avail (one of the sqlnet.ora files actually stopped me from being able to connect to any) I found mention about a config/database.yml file related to ruby, but our code already has the database information set up and I seem to be getting to the same solution as the script when trying to manually connect via sqlplus.
Here are some relevant environment variables I have set up when doing these installs. I'm thinking that at some point when trying to set up my environment, I messed up some config that changed the way sqldeveloper or sql plus would connect to that database.
$ echo $ORACLE_HOME: /usr/lib/oracle/12.2/client64/
$ echo $TNS_ADMIN: /usr/lib/oracle/12.2/client64/network/admin
$ echo $LD_LIBRARY_PATH: /usr/lib/oracle/12.2/client64/lib
I hope I have provided all the information I have come across and have explained clearly what my issue is, if you have any questions feel free to comment about it so I can clear it up. Thank you for any and all your help.
So my problem ended up being a 'firewall/port' issue. In the end i found out that specific port I was connecting to was blocked, but I thought it was only on my system. Turns out the VPN I'm using was the issue blocking that port. Company has a Primary Data Center and a Secondary one, and apparently the SDC VPN was blocking that port from me. I switched to using the PDC VPN and it worked.
Are you using the 64 bit jdbc drivers?

Setting Pakyow for local development with Postgres

In the blog post about connection to postgres, http://notmagic.org/2015/04/10/pakyow-sequel, how do you deal with Postgres setup and required password errors?
I've been developing in Nitrous.io but now setting up local development. So I set the DATABASE_URL as in the post but trying to run pakyow server it gives an error about: "pg::connectionbad: fe_sendauth: no password"
The only user in Postgres is 'postgres' and it has a password associated. It wouldn't let me install without creating a password.
Also, is it bad practice to not have a Postgres password for local dev? Articles about it weren't clear (and were related to Rails) and mentioned database.yml storing the password, which Pakyow doesn't seem to have.
If you follow the post, you'll want to include the password in the DATABASE_URL environment variable (in your local .env file). The url should be structured like: postgres://user:password#host/database.
It's best to always have a password for your Postgres user, be it locally or in production. You want to make it as difficult as possible for someone to see your data :-)

How to connect to Postgres database through Ruby's pg gem (outside of Rails)

I've been using Postgres without issue within Rails and have also been running psql without issue. However, I'm running into a problem trying to connect to the database with the pg gem.
The following code:
PG.connect
generates the error/output:
PG::ConnectionBad: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/pgsql_socket/.s.PGSQL.5432"?
The result is the same whether I specify various dbname: values or not or just let this default.
When I click on the little elephant icon at the top of my screen, it says "Running on port 5432" and, as I said, I can connect with psql without a problem.
I found the very similar cannot connect to Postgres (pg) database from my Ruby Script using gem "pg"(This is not rails, just pure ruby), but the answer simply said Rails works fine.
Any guidance would be appreciated. (Note: I realize I haven't entered any name/password info, but I don't have to enter than when I run psql and I gather it's not getting to the point of authentication).
You need to specify a host. It's trying to connect on a unix domain socket. The PG app doesn't listen on a unix socket (unless you configure it to) but runs on localhost:5432.
conn = PG.connect( host: 'localhost' )
It is quite likely that the actual problem is that your 'pg' gem has linked to an older version of a libpq dynamic library. See this post for more details and a possible solution.

Ruby -> PostgreSQL connection with pg_hba.conf set to "ident sameuser" instead of "trust"

I've tried every Google search term I can think of but everything I dig up keeps saying to set local connections to trust in pg_hba.conf (seems like a security hole if anyone locally can log in and access the DB as anyone they say they are).
In pg_hba.conf local connections are set to ident sameuser. The script should be running as that user, but I get this error:
A database error occurred:
fe_sendauth: no password supplied
The Ruby code is pretty generic:
conn_str = "DBI:pg:dbname=mydb;host=" + localhost
#connection = DBI.connect(conn_str, "myuser", '')
I can work around this by creating a ~/.pgpass file as described here,
but I'd prefer being able to let users log in and just access the DB server.
Anyone ever been able to get PostgreSQL's ident sameuser to work properly for local scripts?
I suspect this:
In pg_hba.conf local connections are set to ident sameuser. The script should be running as that user, but I get this error [...]
conn_str = "DBI:pg:dbname=mydb;host=" + localhost
#connection = DBI.connect(conn_str, "myuser", '')
Please note that a "local" connection is not the same as a connection to "localhost". As soon as you mention "localhost" in the connection URL a TCP/IP socket is created. These are managed by the host rules in `pg_hba.conf.
To use a real "local" connection Unix Domain Sockets must be used. But I don't know whether or not the Ruby DBI connector supports them.
The ident setting works for me for local system users and PostgreSQL 8.4. You may have to adjust your pg_hba.conf settings.
Check your database log files to see where the connections come from exactly and whether the system user name matches the database role name. You may have to activate log_connections in your postgresql.conf for that.
The manual really does a nice job explaining authentication methods.
If system user name and database role name don't match, you'll have to use a .pgpass file. But your passwords should still be safe. Only the system user postgres gets to read it. I quote the manual:
On Unix systems, the permissions on .pgpass must disallow any access
to world or group; achieve this by the command chmod 0600 ~/.pgpass.

Resources