How to connect to PostgreSQL from Phoenix Web App via SSL? - postgresql

When trying to run Elixir (Phoenix) Web Application using PostgreSQL Database hosted 3rd party "Database-as-a-Service" (Azure Database for PostgreSQL).
We attempt to start the app with mix phoenix.server we see the following error:
[info] Running Pxblog.Endpoint with Cowboy using http://localhost:4000
[error] GenServer #PID<0.247.0> terminating
** (FunctionClauseError) no function clause matching in Postgrex.Messages.decode_fields/1
(postgrex) lib/postgrex/messages.ex:339: Postgrex.Messages.decode_fields("")
(postgrex) lib/postgrex/messages.ex:344: Postgrex.Messages.decode_fields/1
(postgrex) lib/postgrex/messages.ex:344: Postgrex.Messages.decode_fields/1
(postgrex) lib/postgrex/messages.ex:131: Postgrex.Messages.parse/3
(postgrex) lib/postgrex/protocol.ex:1842: Postgrex.Protocol.msg_decode/1
(postgrex) lib/postgrex/protocol.ex:1816: Postgrex.Protocol.msg_recv/3
(postgrex) lib/postgrex/protocol.ex:560: Postgrex.Protocol.auth_recv/3
(postgrex) lib/postgrex/protocol.ex:475: Postgrex.Protocol.handshake/2
(db_connection) lib/db_connection/connection.ex:134: DBConnection.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: nil
State: Postgrex.Protocol
Insight: "Enforce SSL" was Enabled on the Azure DB ...
Through investigation we realised that the error is cause because the Azure PostgreSQL Service had Enforce SSL Connection set to Enabled (by default):
We think having "Enforce SSL" to Enabled is good for Security, but we aren't able to get it working with Phoenix ...
(Temporary) Solution: Disable "Enforce SSL"
So, we have (temporarily) disabled SSL for now:
But we would much prefer a "permanent" solution to this issue.
Preferred Solution: Use SSL when Connecting to PostgreSQL
If anyone can clarify (or point us to) how to connect to PostgreSQL over SSL from Phoenix/Ecto
we would be super grateful! :-)
Does the Application (Phoenix) Server need to have an SSL Certificated configured in order to connect from the App server to the DB Server...?
e.g: http://www.phoenixframework.org/docs/configuration-for-ssl ?
Microsoft has the following help guide:
https://learn.microsoft.com/en-us/azure/postgresql/concepts-ssl-connection-security
It seems to suggest we need OpenSSL on the App Server ... can anyone confirm?

Background
I was experiencing the same problem connecting Phoenix/Ecto/Postgrex to Azure Database for PostgreSQL server. Even after setting ssl: true in my Repo configuration, I was still not able to connect to the database with Postgrex even though connecting using psql "postgresql://...?sslmode=require" -U ... on the same machine succeeded. The error returned with ssl: true was:
[error] Postgrex.Protocol (#PID<0.1853.0>) failed to connect: **(DBConnection.ConnectionError) ssl connect: closed
** (DBConnection.ConnectionError) connection not available because of disconnection
(db_connection) lib/db_connection.ex:926: DBConnection.checkout/2
...
After digging through the source code, I discovered that the failing call was actually the ssl.connect/3 call from the Erlang ssl module:
# deps/postgrex/lib/postgrex/protocol.ex:535
defp ssl_connect(%{sock: {:gen_tcp, sock}, timeout: timeout} = s, status) do
case :ssl.connect(sock, status.opts[:ssl_opts] || [], timeout) do
{:ok, ssl_sock} ->
startup(%{s | sock: {:ssl, ssl_sock}}, status)
{:error, reason} ->
disconnect(s, :ssl, "connect", reason)
end
end
Doing some snooping with Wireshark, I was able to see that when connecting successfully with psql, I could see packets with TLSV1.2 as the protocol, but when postgrex was connecting with ssl: true I was seeing packets with SSL as the protocol before failing to connect.
Looking at the Ecto.Adapters.Postgres options docs, you'll see there's an ssl_opts configuration option which ends up getting passed to :ssl.connect/3 in which you can set versions to override the TLS version(s) used to connect.
Solution
I was able to connect to the database by adding the following to my Repo configuration:
ssl_opts: [
versions: [:"tlsv1.2"]
]
My full configuration ended up looking like this:
config :myapp, Myapp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "myapp#dev-db",
password: "...",
database: "myapp_dev",
port: 5432,
hostname: "dev-db.postgres.database.azure.com",
pool_size: 10,
ssl: true,
ssl_opts: [
versions: [:"tlsv1.2"]
]
I'm not really sure why the TLS version needs to be set explicitly, perhaps someone with more expertise in this area can shed some light on this.

You might also need to add your ip (or ip range) to the postgres firewall in azure. It's right under the SSL settings.

Erlang is usually built with OpenSSL, and does require it for several libraries. You haven't posted the error you get with ssl: true, but if your erlang was built without OpenSSL it might be the cause. From the build/install guide:
OpenSSL -- The opensource toolkit for Secure Socket Layer and
Transport Layer Security. Required for building the application
crypto. Further, ssl and ssh require a working crypto application and
will also be skipped if OpenSSL is missing. The public_key application
is available without crypto, but the functionality will be very
limited.
What output do you get if you run :ssl.versions() in an iex shell?

Here is my Database init() connection code using ssl and certificates. Check your ssl_opts settings, maybe.
def init() do
case Postgrex.start_link(
hostname: App.Endpoint.config(:dbhost),
username: App.Endpoint.config(:username),
database: App.Endpoint.config(:dbname),
port: App.Endpoint.config(:dbport),
ssl: true,
ssl_opts: [
keyfile: "priv/cert.key",
certfile: "priv/cert.crt"
]) do
{:ok, postgrex} ->
postgrex
_ ->
:error
end
end

To add to the above answers, here is my ssl_opts block when using self-signed certificates and auth-options set to clientcert=verify_full in your pg_hba.conf. My connection is using TLSv1.3.
ssl_opts: [
verify: :verify_peer,
versions: [:"tlsv1.3"],
ciphers: :ssl.cipher_suites(:all, {3,4}),
cacertfile: Path.expand("priv/certs/ca-cert.pem"),
certfile: Path.expand("priv/certs/client-cert.pem"),
keyfile: Path.expand("priv/certs/client-key.pem")
],

Related

MongoDB SSL Replica setup issues - Unsupported Certificate

Trying to set up a 3 node mongodb server replica on Ubuntu 18.04, mongo version 4.0.18
gl1 192.168.1.30
gl2 192.168.1.31
gl3 192.168.1.33
Using an internal CA on the same network to create certs, I have created 2 certs, one for the server mongo is installed on (GL1, GL2, GL3) for PEMKeyFile and one for the clusterFile (mongo1, mongo2, mongo3). Each CAFile is set listing the respective RSA key, PEMKeyFile and RootCA for each server. I have mongo services running (according to systemctl) fine using the individual certs (PEMKey and clusterFILE).
net:
port: 27017
bindIp: 0.0.0.0
net:
ssl:
mode: requireSSL
PEMKeyFile: /opt/ssl/MongoDB.pem
CAFile: /opt/ssl/ca.pem
clusterFile: /opt/ssl/mongo.pem
allowConnectionsWithoutCertificates: true
#replication
replication:
replSetName: rs0
Getting the following error when I try to rs.add("192.168.1.31:27017") I get the following error
"errmsg" : "Quorum check failed because not enough voting nodes responded; required 2 but only the following 1 voting nodes responded: 192.168.1.30:27017; the following nodes did not respond affirmatively: gl2.domain.com:27017 failed with stream truncated",
"code" : 74,
"codeName" : "NodeNotFound",
In the mongod.log on node 192.168.1.31 the following is logged:
2020-05-22T18:20:48.161+0000 E NETWORK [conn4] SSL peer certificate validation failed: unsupported certificate purpose
2020-05-22T18:20:48.161+0000 I NETWORK [conn4] Error receiving request from client: SSLHandshakeFailed: SSL peer certificate validation failed: unsupported certificate purpose. Ending connection from 192.168.1.30:55002 (connection id: 4)
I have read on an old Google groups post: https://groups.google.com/forum/#!msg/mongodb-user/EmESxx5KK9Q/xH6Ul7fTBQAJ that the clusterFile and PEMKeyFile had to be different. However, I did that and it still is throwing errors. I have done a lot of searching on this and I'm seeing much to support that this how it's done, but it is the only place I've found that has a similar error message and it seems logical that it should work. However, I'm not sure how I can verify that my clusterFile is actually being used. It is indeed a separate certificate with a FQDN for each node. All three nodes have host files updated to find each other (gl1, mongo1, etc). I can ping all nodes between themselves, so networking is up. I've also verified the firewall (ufw and iptables) is not blocking 27017 or anything at this point. Previously I tried the self-signed CA and certs but kept running into errors since those were self signed certs, so that is why I went the internal CA route.
The "purpose" is also known as "extended key usage".
Openssl x509v3 Extended Key Usage gives some example code for setting the purposes.
As pointed out by Joe, the documentation states that the certificates must either have no extended key usage at all, or the one in the PEMKeyFile must have server auth, and the one in the cluster file must have client auth.

No suitable servers found (`serverSelectionTryOnce` set): [TLS handshake failed: error:14090086:SSL routines:ssl3_get_server_certificate

i`m trying to connect mongodb to php application from compose to local,but get this error.
but i can remote using mongo chef
No suitable servers found (serverSelectionTryOnce set): [TLS handshake failed: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed calling ismaster
I think you have 3 options to solve this problem.
1. Disable SSL on your server
Find mongod.conf, if you're using linux, then normally it should locate at /etc/mongod.conf, use # to comment these lines under net. Finally, you need to restart mongodb for making change works.
net:
ssl:
mode: requireSSL
PEMKeyFile: ./mongodb.pem
...
2. Use the option called weak_cert_validation on your client
This is not a safety solution, but this is definitely one of the simplest one.
For example, if the mongoDB server has enable SSL but without (or did't) offering CA certificate(means self-signed certificate), then set weak_cert_validation as true in the client side, a example for C client:
mongoc_ssl_opt_t ssl_opts = {0};
ssl_opts.weak_cert_validation = true;
mongoc_client_set_ssl_opts(client, &ssl_opts);
3. Follow configure-ssl to create a certificate and get it signed for your program.
Here some provider: https://en.wikipedia.org/wiki/Certificate_authority#Providers

SQLSTATE[08006] [7] expected authentication request from server, but received _

I configured my application (laravel 5.3) with travis-ci to work with postgresql database, but I got error in matrix build:
SQLSTATE[08006] [7] expected authentication request from server, but received _
I tried to change pgsql version to 9.4, with no success.
When SSL Mode is set to "prefer", build throws:
SQLSTATE[08006] [7] received invalid response to SSL negotiation: _
On mysql driver works fine and build passes.
Personally, I prefer postgresql rather than mysql, so I asking for help how to resolve this problem.
Thanks.
Had the same error.
In laravel config for Postgresql by default it hase port 3306,
The correct one is 5432.
Or check your system

Need help setting up MongoDB for SSL

I am trying to configure mongodb for ssl. I have the two certs within a directory on Ubuntu, but when I try to restart the service with the mongodb.conf set up correctly, the service will not start. If I comment out the lines in the mongodb.conf file that I added, I can then start mongodb. I think the syntax is wrong, and not the certs them self.
#SSL options
sslMode = requireSSL
#Enable SSL on normal ports
#sslOnNormalPorts = true
# SSL Key file and password
sslPEMKeyFile = /path/to/cert
sslPEMKeyPassword = password
sslCAFile = /path/to/cert
I get this error when I try to start the server with these lines not commented out
stop: Unknown instance:
mongodb start/running, process 7725
If i try to get into mongo shell i get this(assuming this is because I could not restart the service properly)
Thu Jul 21 14:32:07.660 Error: couldn't connect to server 127.0.0.1:27017 at src/mongo/shell/mongo.js:145
exception: connect failed
The mongodb.conf file is a YAML file so you need to format it as such. Meaning you can't use tabs. Also it does look like the syntax you're using isn't correct.
Try this:
net:
#SSL options
ssl:
mode: requireSSL
# SSL Key file and password
PEMKeyFile: /path/to/cert
PEMKeyPassword: password
CAFile: /path/to/cert
Also, I know it's commented out but just wanted to mention, the sslOnNormal ports option is deprecated. See here: https://docs.mongodb.com/manual/reference/configuration-options/#net.ssl.sslOnNormalPorts

ADMU0509I: The Application Server "server1" cannot be reached. It appears to be stopped

I have setup a WebSphere Application Server on my RHEL 7 virtual machine. When I start the server, it starts fine and I can access the admin console but when I try to stop or get the status of the server using the script
sh stopServer.sh -server1 / sh serverStatus.sh server1
It gives the following message,
ADMU0509I: The Application Server "server1" cannot be reached. It appears to be stopped.
My wsadmin scripts are not working, when I run the script
sh wsadmin.sh -user wasadmin -password Password
I get the following error
WASX7023E: Error creating "SOAP" connection to host "localhost"; exception information: com.ibm.websphere.management.exception.ConnectorNotA
vailableException: [SOAPException: faultCode=SOAP-ENV:Protocol; msg=; targetException=java.net.MalformedURLException]
WASX7213I: This scripting client is not connected to a server process; please refer to the log file /opt/IBM\WebSphere/AppServer
/profiles/AppSrv01/logs/wsadmin.traceout for additional information.
I can access the console on the browser without any issue.
To expand on this more specifically. The file ssl.client.props looks like this typically around the com.ibm.ssl.protocol property:
$ grep -i tls -C 2 /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/properties/ssl.client.props
#-------------------------------------------------------------------------
com.ibm.ssl.alias=DefaultSSLSettings
com.ibm.ssl.protocol=SSL_TLS
com.ibm.ssl.securityLevel=HIGH
com.ibm.ssl.trustManager=IbmPKIX
--
#-------------------------------------------------------------------------
#com.ibm.ssl.alias=AnotherSSLSettings
#com.ibm.ssl.protocol=SSL_TLS
#com.ibm.ssl.securityLevel=HIGH
#com.ibm.ssl.trustManager=IbmX509
This property can take a number of values:
This property is the SSL handshake protocol that is used for this SSL
configuration. This property attempts Transport Layer Security (TLS)
first, but accepts any remote handshake protocol, including SSLv3 and
TLSv1. Valid values for this property include SSL_TLS, SSL, SSLv2
(client side only), SSLv3, TLS, TLSv1, SSL_TLSv2, TLSv1.1, and
TLSv1.2.
These values are described in this table:
References
ssl.client.props client configuration file
Appendix A: Protocols and Cipher Suites
For me this problem came when the security level of the WAS was not consistent.
In the IBM console, it was set to TLSv1.2 and in ssl.client.props file it was set to SSL_TLS. Once they were changed to the same value my console could connect to WAS.