How do I connect to MongoDB with SSL in Scala? - mongodb

I'm trying to set up an ssl connection to a mongodb instance I have running in a container on my machine and keep running into,
nioEventLoopGroup-2-4, fatal error: 46: General SSLEngine problem
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I created a self signed .pem for mongo with,
openssl req -x509 -newkey rsa:4096 -keyout mongo.key -out mongo.crt -days 365 -nodes
cat mongo.key mongo.cert > mongo.pem
Moved those into a folder, mounted it as a bind volume in my container and added
--sslMode requireSSL --sslPEMKeyFile /etc/boundfolder/mongo.pem
to the mongo startup. I can connect to this with the mongo client.
I am setting up my mongo client in scala like so,
val hostConf = ClusterSettings.builder().hosts(List(new ServerAddress(hostName)).asJava).build()
val clientSettings = MongoClientSettings.builder()
.streamFactoryFactory(NettyStreamFactoryFactory())
.clusterSettings(hostConf)
val withTLS = clientSettings.sslSettings(
SslSettings.builder()
.enabled(true)
.invalidHostNameAllowed(true)
.build())
MongoClient(withTLS.build())
Lastly, I created a keystore with,
keytool -importcert -trustcacerts -file mongo.crt -keystore mongo.keystore
and am starting the application with the following parameters,
-Djavax.net.ssl.keyStore=/path/to/mongo.keystore -Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.debug=SSL
I'm pretty sure the issue is either what, or how, I'm adding the self signed cert to the keystore. Thanks for any help you can give.

Related

Self signed SSL certificate generated by New-SelfSignedCertificateEx isn't trusted in Ubuntu

I used this tool in this link to generate a self-signed certificate for a Windows webserver.
The command to generate the cert is like following
New-SelfSignedCertificateEx -Subject "CN=192.168.56.111" -SAN "192.168.56.111" -IsCA $true -EKU "Server Authentication", "Client Authentication" -KeyLength 2048 -KeySpec "Signature" -KeyUsage "DigitalSignature" -FriendlyName "192.168.56.111" -NotAfter $([datetime]::now.AddYears(5)) -StoreLocation "LocalMachine" -Exportable
After installing the certificate with IIS, and add the certificate to the trusted root CA store in a Windows 10 client, I was able to browse the website with no certificate errors.
However when I try to do the same in a ubuntu 18.04 client by installing the cert to the CA certs store and test using cURL, it doesn't work
Install cert to Ubuntu ca-certificates
openssl s_client -connect 192.168.56.111:443 -showcerts > out.txt
#then use vim to edit out.txt and save the cert to 192.168.56.111.crt
sudo cp 192.168.56.111.crt /usr/local/share/ca-certificates
sudo update-ca-certificates
Test the connection using cURL
curl https://192.168.56.111
And got the error message
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
When adding the cert to the Chrome Certifiates store, Chrome shows NET::ERR_CERT_INVALID
So my question is, why does it work in Windows client but not in Ubuntu 18.04? I can't see any error indicating what's wrong with the certificate in Ubuntu so I'm stuck at the moment.
Your openssl command is not correct:
jonathan.muller#jonathan-muller-C02ZC4EPLVDQ$ openssl s_client -connect drylm.org:443 -showcerts
CONNECTED(00000005)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = blog.drylm.org
verify return:1
---
Certificate chain
0 s:/CN=blog.drylm.org
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
-----BEGIN CERTIFICATE-----
MIIFUzCCBDugAwIBAgISA0xYp5ZHU+NGF1EW/RcUuV0fMA0GCSqGSIb3DQEBCwUA
...
you have a lot of noise in the output.
Here is how to extract the certificate:
echo | openssl s_client -connect 192.168.56.111:443 2>/dev/null | openssl x509 > 192.168.56.111.pem
and you can copy this pem file to the truststore.
Edit:
I just made the exercise by creating a self sign certificate on this website
in my shell:
john#kona$ curl https://test.drylm.org
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
then
john#kona$ echo | openssl s_client -connect test.drylm.org:443 2>/dev/null | openssl x509 > test.drylm.org.crt
sudo cp test.drylm.org.crt /usr/local/share/ca-certificates/
john#kona$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
Adding debian:test.drylm.org.pem
done.
done.
and finally:
john#kona$ curl https://test.drylm.org
Path : ~
No more error message with curl.

"sun.security.validator.ValidatorException: PKIX path building failed: Exception: unable to find valid certification path to requested target"

I am trying to get response code for this site "https://www.ssfcu.org/en-us/Pages/default.aspx".
The code snippet is:
try{
HttpURLConnection connection = pingUrl(location);
responseCode = connection.getResponseCode();
}catch(Exception e) {
}
public HttpURLConnection pingUrl(String url) throws Exception{
int count = 0;
HttpURLConnection conn = null;
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(2000);
conn.setInstanceFollowRedirects(false);
conn.setReadTimeout(10000);
conn.connect();
Thread.sleep(1000);
return conn;
}
But I am getting an exception:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
How can I resolve this?
An old COMODO root certificate expired on May 30.
https://www.reddit.com/r/linux/comments/gshh70/sectigo_root_ca_expiring_may_not_be_handled_well/
https://support.sectigo.com/articles/Knowledge/Sectigo-AddTrust-External-CA-Root-Expiring-May-30-2020
Don't know if this affects www.ssfcu.org, but you might try importing updated certs to your java keystore:
Fetch https://crt.sh/?d=1720081 and https://crt.sh/?d=1199354
Convert crt files to der files: openssl x509 -in 1720081.crt -outform der -out 1720081.der
keytool -import -file 1720081.der -keystore your-keystore -alias Comodo (or alias UserTrust for 1199354)
Your keystore is in your JRE_HOME directory in the file lib/security/cacerts. You'll need root privilege to edit the cacerts file.
Edit: I looked closer and Comodo isn't involved in www.sfcu.org's certificate chain, but the instructions above are correct as long as you can identify the root or intermediate certificate that has expired. We coincidentally ran into an issue with linkedin.com today. Like www.ssfcu.org, they too use a certificate chain from DigiCert, so perhaps they had some certs expire recently, too.

Authenticate against MongoDB using DelphiMongoDB from Grijjy

I am using DelphiMongoDB from Grijjy (DelphiMongoDB) which is working pretty cool so far. But I can't find any functions to authenticate against a MongoDB. Did anybody getting this work or figured out how to do it?
Thanks and best regards
Update: The most up to date version of the Grijjy driver now supports TLS, X.509 client certificate authentication, SCRAM SHA-1 and SHA-256 authentication. We have also tested it against MongoDB Atlas instance at Azure.
Here is a simple example of how to use the authentication.
var
Settings: TgoMongoClientSettings;
Client: IgoMongoClient;
Database: IgoMongoDatabase;
Collection: IgoMongoCollection;
Doc: TgoBsonDocument;
begin
Settings := TgoMongoClientSettings.Create;
Settings.Secure := True;
Settings.AuthMechanism := TgoMongoAuthMechanism.SCRAM_SHA_1;
Settings.AuthDatabase := 'admin';
Settings.Username := 'username';
Settings.Password := 'password';
//Settings.QueryFlags := [TgoMongoQueryFlag.SlaveOk];
Client := TgoMongoClient.Create('my.mongodb.server.com', 27017, Settings);
Database := Client.GetDatabase('mydatabase');
Collection := Database.GetCollection('mycollection');
for Doc in Collection.Find() do
Writeln(Doc.ToJson(TgoJsonWriterSettings.Pretty));
end;
Legacy: Yes, the published Grijjy driver does not support authentication, but we have tested it internally and may add this ability in the near future to Github. You are also welcome to make a pull request if you want to adapt the following changes:
MongoDB currently supports 2 types of authentication, SCRAM and x.509 Certificate Authentication. Internally we have tested the x.509 Certificate Authentication, but the current driver on Github does not reflect this ability. We have not experimented with SCRAM yet.
To make it work with the MongoDB driver we published on Github, you may have to make a couple of changes.
You need to create a self-signed CA and certificate for your MongoDB server.
You need to configure your MongoDB server to use certs.
You need to create a self-signed certificate for your MongoDB client or clients. You can use the same cert for all clients.
You need to enable SSL/TLS connections and use your client certificate with the MongoDB driver.
1 To create all the certificates, you need an existing CA or create a self-signed CA. You can use the openssl.exe binary to do most of this:
Create root certificate authority (ca.pem and privkey.pem):
openssl req -out ca.pem -new -x509 -days 3650 -subj "/C=US/ST=California/O=Company/CN=root/emailAddress=root#domain.com"
To create a self-signed certificate for your MongoDB server (server.pem):
openssl genrsa -out server.key 2048
openssl req -key server.key -new -out server.req -subj "/C=US/ST=California/O=Company/CN=db.myserver.com/emailAddress=user#domain.com"
openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAcreateserial -out server.crt -days 3650
type server.key server.crt > server.pem
openssl verify -CAfile ca.pem server.pem
2 To configure MongoDB to use certs on the Windows version (similar on other versions), edit the c:\data\mongod.cfg:
systemLog:
destination: file
path: c:\data\log\mongod.log
storage:
dbPath: c:\data\db
net:
port: 27017
bindIp: 127.0.0.1
ssl:
mode: requireSSL
PEMKeyFile: c:\data\server.pem
CAFile: c:\data\ca.pem
{allowConnectionsWithoutCertificates: true }
{allowInvalidHostnames: true }
You may need allowInvalidHostnames to True if you are using a self signed certificate.
3 To create a self-signed certificate for your MongoDB client (client1.pem):
openssl genrsa -out client1.key 2048
openssl req -key client1.key -new -out client1.req -subj "/C=US/ST=California/O=Company/CN=client1/emailAddress=user#domain.com"
openssl x509 -req -in client1.req -CA ca.pem -CAkey privkey.pem -CAserial ca.srl -out client1.crt -days 3650
type client1.key client1.crt > client1.pem
openssl verify -CAfile ca.pem client1.pem
Note: You will also need to use the client certificate in whatever tool you are using to admin the MongoDB server.
4 To enable SSL/TLS connections for MongoDB driver you may have to change the source files. Our unit Grijjy.Http shows how to enable the driver for ‘https’. Essentially you need to do 2 things to the Connection inside the Grijjy.MongoDB.Protocol unit probably within the method TgoMongoProtocol.Connect :
Set Connection.SSL := True;
Set the Connection.Certificate to the client1.pem you created.
You will have to do some testing, but I hope it points you in the correct direction to make it work. Would love your contribution to the open source project if you can.
As far as I can understand the sources, https://github.com/grijjy/DelphiMongoDB/ doesn't support authentication.
Also from the source, https://github.com/stijnsanders/TMongoWire doesn't either.
FireDAC Mongo uses the C Mongo client library, which supports authentication.
Our Open Source SynMongoDB.pas supports authentication, FPC and almost all Delphi versions (even pre-Unicode). Using variant late-binding to access the BSON/JSON content, it is pretty easy to work with it. Just check the corresponding documentation pages. You can write for instance:
var doc: variant;
...
doc := Coll.FindOne(5);
writeln('Name: ',doc.Name);
writeln('Number: ',doc.Number);
or
var docs: TVariantDynArray;
...
Coll.FindDocs(docs);
for i := 0 to high(docs) do
writeln('Name: ',docs[i].Name,' Number: ',docs[i].Number);
The TMongoClient.OpenAuth method supports both old/deprecated MONGODB-CR method, and the new SCRAM-SHA-1 method:
Client := TMongoClient.Create('localhost',27017);
try
DB := Client.OpenAuth('mydb','mongouser','mongopwd');
...
Note that even if it is part of the mORMot framework, this unit is stand-alone: you don't need to use the ORM, SOA, or MVC parts of the framework - even if it works very well with the ORM, and is able to convert SQL-like statements into MongoDB pipelines, which is a unique very powerful feature. Another unique feature is proper Decimal128 support.
Over a network, also ensure that you use a TLS connection to the server. SynMongoDB.pas can do that under Windows, with no external OpenSSL library needed (it uses the raw Windows SO API).

keytool -import failed with the error "failed to establish chain from reply"

I have a keystore, which contains only 1 keypair (foo). From that keypair, I generated a csr, which was signed by a CA using the certificate bar (bar is the issuer of foo). The issue I have is that I'm unable to import back the certificate foo in my keystore with this command
keytool -importcert -alias foo -file foo.p7b keypass 123456 -keystore keystore.jks -storepass 123456
It failed with the error
Failed to establish chain from reply.
If add the public certificate bar in my keystore, then it is working fine.
Therefore, one will simply think that I absolutely need to insert the public certificate bar in my keystore, but what is bugging me here is that if I use KeyStore Explorer to import the certificate foo in my keystore (which is only containing the keypair foo), then it is working fine. In other word, I able to import the certificate with KeyStore Explorer ("Import CA reply"), but not keytool.
Is anyone have an idea what I'm doing wrong ?

EJBCA adminweb Authorization denied

I am currently testing with EJBCA while having a problem in accessing the administration page.
The EJBCA-4.0.13 is running on CentOS 6.2, with apache-ant-1.8.4, jboss-5.1.0-GA, mysql and mysql-connector-java. Installation is OK and no error occured in the jboss server log and I can access the EJBCA public web page with the url: https://:8443/ejbca. While I cannot access the administration page(https://:8443/ejbca/adminweb) with this information:
Authorization Denied
Cause: Your certificate is revoked or cannot be located in the database.
Any idea will be appreciated!
This is done in LocalCertificateStoreSessionBean.authenticate method. This could mean that you have not properly generated SuperAdmin certificate, or it is revoked, timed out or is issued by another CA that EJBACA's AdminCA.
Check your superadmin.p12 with:
openssl pkcs12 -nokeys -in ./superadmin.p12 -out superadmin.pem
openssl x509 -in ./superadmin.pem -text