SSLHandshakeException when connecting to Wiremock with my own self-signed cert - wiremock

I'm running a stand-alone instance of Wiremock for mocking in JUnit tests. This works fine with http and if I use the wiremock self-signed cert with the switch --https-port 8443. If I specify --https-keystore server_keystore.jks however, any attempt to communicate with Wiremock e.g WireMock.reset(); throws a javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake. Connecting to the admin page https://localhost:9093/__admin/ in a browser shows a similar error about the connection being closed.
The keystore was generated as follows;
keytool -genkey -keyalg RSA -keysize 2048 -alias server -keypass secret -storepass secret -keystore server_keystore.jks
If I enable logging for all traffic in Wiremock I see;
Problem decoding network traffic
java.nio.charset.MalformedInputException: Input length = 1
I've added System.setProperty("javax.net.ssl.trustStore", "server_keystore.jks"); in my calling code prior to attempting to communicate with Wiremock with no success.

Since you've set a password on your keystore you'll need to provide this to WireMock via the --keystore-password parameter.

Related

Apache NiFi with MongoDB over SSL

I've faced the problem with SSL connection to MongoDB (SSLContextService processors).
all certificates I've generated (Root, Server and Client). Server and Client certificates I've signed with my root certificate. Since my MongoDB-Sever has more then one IP-Address, I've include all IP-Addresses in the server certificate.
MongoDB is also configured for ssl connections (tls), the old version of tls (1.1, 1.2) are not disabled in MongoDB.
SSL-Connection with mongo-shell works without problems. I've also checked everything with openssl s_client and connection was there and also worked properly.
For Apache NiFi I've created keystore (PKCS12)
openssl pkcs12 -export -name client -in client.crt -inkey client.key -certfile ca.crt -out client.p12
and also truststore with server certitiface
openssl pkcs12 -export -name server -in server.crt -inkey server.key -out server.p12
and I've also tried
openssl pkcs12 -export -name server -in server.crt -inkey server.key -certfile ca.crt -out server.p12
ca.crt is my root certificate. client.crt and server.crt were sigend with this ca.crt.
I've used both services in NiFi:
StandardSSLContextService and StandardRestrictedSSLContextService. In the parameter Keystore I've put client.p12 and in truststore parameter server.p12. Both types PKSC12. TLS protocoll just TLS.
But anyway I get an error "PKIX path building failed".
I'm not sure what I've missed, but may be someone had such problem already.
Thanks in advance.
P.S. forgotten:
If I set in MongoDBControllerService parameter "Client Auth" to "NONE" then it works.
PKIX path building errors mean that NiFi cannot construct the trusted "path" between the certificate that is presented by the other endpoint (in this case MongoDB) and any of the certificates which are loaded in the respective truststore to identify trusted certificates.
If I am watching my niece tells me she's allowed to have all the candy she wants, I am not likely to agree. However, if she has a signed note from her parent confirming that, she gets candy. If she has a note signed by herself in crayon, not so much.
The likely solution is to concatenate the root public certificate and the node certificate into a single file (literally just cat server.pem ca.pem > combined_server.pem; make sure the node cert is first). That command assumes the certificate files are in PEM-encoded ASCII format (i.e. starts with -----BEGIN CERTIFICATE-----) and I prefer using .pem for the extension here, though .crt files can also contain this data. You can then verify that the chain is correct with
openssl verify -verbose -purpose sslserver -CAfile ca.pem combined_server.pem
For consistency, I'd repeat the process with the client cert and CA as well (use -purpose sslclient in the verification command). Then regenerate the PKCS12 keystore & truststore and load them into NiFi.
I am slightly confused by the fact that you say disabling client authentication in NiFi allows this to work, as NiFi should be acting as the client, and clients don't get to determine the client authentication level (the setting is literally ignored when acting as a client). It should only matter if NiFi is somehow acting as the server and MongoDB is the client. What version of NiFi and MongoDB are you using?
NiFi uses its own truststore which is either jks or pfx (p12) format, not concatenated pem files and not system files under /etc/pki/ca-trust/. As far as I can tell, you are not allowed to pass the tlsCAFile url parameter from a nifi processor which is confusing.

How to make client accept the server SSL certificate

I am trying to make REST calls to server from a client.
Server Side
I am using Flask as web server. I have generated the certificate(cert.pem) and public key(key.pem) using the following command.
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
Following is the server side code.
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
#app.route('/someroute/<arg1>,<arg2>', methods=['GET'])
def fn1(arg1,arg2):
res = fn2(arg1, arg2)
return str(res)
def fn2(un,pwd):
#Do something and return a number
return num
if __name__ == '__main__':
context = ('cert.pem', 'key.pem')
app.run(host="ip", port=port1, debug=True, ssl_context=context)
Client Side
I have a flask application from which I need to make REST calls to the above server. Following is the code I am using to do so.
import requests
# Below is the part of a function which gets called upon hitting a route in Flask.
ret = requests.get("https://<ip>:<port1>/<someroute>/arg1,arg2", verify=True)
print ret.text
This is throwing the following error.
requests.exceptions.SSLError: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
This error is expected as the certificate is not known to the client. Everything is working perfectly fine if I skip the certificate verification (verify=False).
How do I make the client trust this unknown server SSL certificate? I have seen solutions where I need to use Nginx on the client side. Can we not do some changes on flask(client side) itself to make it trust my server? If yes, what is that exact change I should be making in Flask? Also, suggest if urllib is better than requests.
UPDATE 1
I have another query here. From above, I understood that requests.get verifies the certificate every time we make a REST call (Please correct me if I am wrong). But, this looks like an extra load. Can we not have an encrypted connected established in the beginning and exchange the data by encrypting it with a private key? So, how to implement the beginning part - Send private key by encrypting it with the public key to the server and then start exchanging data by encrypting the data with the private key.
OC (original comment):
Server Side
I am using Flask as web server. I have generated the certificate(cert.pem) and public key(key.pem) using the following command.
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 36
If you read man req it says,
-out filename
This specifies the output filename to write to or standard output by default.
-keyout filename
This gives the filename to write the newly created private key to. If this option is not specified then the filename present in the configuration file is used.
Here, cert.pem could be referred to as the public certificate and key.pem really is your private key (Keep it safe and well, private). FTFY.
OC (original comment):
This error is expected as the certificate is not known to the client. Everything is working perfectly fine if I skip the certificate verification (verify=False).
How do I make the client trust this unknown server SSL certificate? I have seen solutions where I need to use Nginx on the client side. Can we not do some changes on flask(client side) itself to make it trust my server? If yes, what is that exact change I should be making in Flask? Also, suggest if urllib is better than requests.
I'll answer this backwards, but first a little background. I found these links really useful to understand - on a high level - how the SSL/TLS handshake happens and how authentication is carried out
IBM: An overview of the SSL or TLS handshake
IBM: How SSL and TLS provide authentication
Now, coming back to your question,
requests > urllib (Personal opinion, but requests does have a good support and is mature - not implying that urllib isn't)
It looks like you want to do server authentication only, for that your client needs the server's public certificate. From How SSL and TLS provide authentication:
The certificates required are as follows, where CA X issues the certificate to the SSL or TLS client, and CA Y issues the certificate to the SSL or TLS server:
For server authentication only, the SSL or TLS server needs:
The personal certificate issued to the server by CA Y
The server's private key
and the SSL or TLS client needs:
The CA certificate for CA Y
Use it in requests.get referring this from requests, which says,
You can pass verify the path to a CA_BUNDLE file or directory with certificates of trusted CAs:
requests.get('https://github.com', verify='/path/to/certfile')
Once you do that and have good certificates, it should work.
NOTE: The openssl command in the OC does not show any subject for the key/cert pair, this would still fail cert verification, refer documentation that shows how to generate self-signed certs. There's a requirement to provide SANs (SubjectAltNames) so providing just a CommonName (CN) in the subject won't future proof your process.
EDIT:
The CA talk in the IBM document can be confusing, but since this is a self-signed cert, you don't have to worry about this, just think of it as your Flask server being the SSL/TLS server, and any client of that server can do server verification using server's public key.
OC (original comment):
From above, I understood that requests.get verifies the certificate every time we make a REST call (Please correct me if I am wrong). But, this looks like an extra load.
That's true. It would perform verification each time. To avoid that you can use requests.Session() as mentioned in requests SSL Cert Verification
OC (original comment):
Can we not have an encrypted connected established in the beginning and exchange the data by encrypting it with a private key? So, how to implement the beginning part - Send private key by encrypting it with the public key to the server and then start exchanging data by encrypting the data with the private key.
This is explained really well in the IBM docs listed

Where to get a SAML certificate

I am new to this concept of SAML certificates.
I am currently working on configuring an SSO for a website and need to know how I can generate a SAML certificate? The setup I am using for this website is not via Azure, but directly from the vendor site and they are requesting my SAML certificate. Do I need a special tool to do this? and does it need to be registered before sending it out?
Run the command below to create the certificate
e.g:
keytool -genkey -alias saml -dname "CN=mydomain.com, C=NO" -keystore saml-keystore -keyalg RSA -validity 730 -keysize 1024
Send the public certificate to the SAML Consumer party
The SAML Consumer needs to know the public part of your certificate. You may export the public part of the certificate and send this.
keytool -export -rfc -keystore saml-keystore -alias saml -file saml-cert.public
Here is whole details also it, Also there is some other online tool which helps in create certificate online like samltool
There's no such thing as SAML certificate. SAML uses self-signed X.509 certificates that can be generated manually using the openssl. There are number of tutorials on the web how to create such certificate.
Some identity provider will generate the public key and certificate for you.
Keycloak does this and will allow to copy it in the Realms settings.

WSO2 EMM - Email configuration

I know this question is already answered, but I couldn't solve it for myself.
How can I configure email for emm?
Here is my config in general setting :
Host: smtp.gmail.com
Port: 25 (also I check it using 587)
Username: myusername#gmail.com
password: my email pass
Sender email address: myusername#gmail.com
Email template: You have been registered to the to EMM. Below is the link to enroll.
but no invitation email sent to users.
first I try sending invitation email to already registered user.
then I check adding new user and send invitation to him.
here is the log for port 25, here is the log for port 587, here is the log for new user with port 25 and here for port 587.
Also I turn off my firewall and try again but no invitation email sent to users.
More info:
server : windows 7 (wso2 v : 1.1.0) - localhost, database : mysql
I have done these configuration using tenant which I have created.
for solving the problem I change the emm\modules\user.js :
line 186: if(username.indexOf("#")<1) to if(username.toString().indexOf("#")<1)
and add yahoo certificate to the keystores (wso2carbon.jks, emm_truststore.jks and wso2emm.jks.)
to get yahoo certificate I run this :
openssl s_client -connect smtp.mail.yahoo.com:587 -starttls smtp
and save the Server certificate as yahoocertificate.cer.
and to add it to keystores I run this:
keytool -import -alias smtp.mail.yahoo.com -file yahoocertificate.cer -keystore "D:\EMM\Carbone_Home\repository\resources\security\wso2carbon.jks"
keytool -import -alias smtp.mail.yahoo.com -file yahoocertificate.cer -keystore "D:\EMM\Carbone_Home\repository\resources\security\emm_truststore.jks"
keytool -import -alias smtp.mail.yahoo.com -file yahoocertificate.cer -keystore "D:\EMM\Carbone_Home\repository\resources\security\wso2emm.jks"
Also I check it with gmail smtp server port 587.
Error shows that there's a connection timeout. Gmail SMTP might be blocking your authentication request. Usually it throttles 3rd party client requests unless you disable security from your mail account settings.
Thanks

Trying to get Basic Weblogic server authentication but i get this exception javax.net.ssl.SSLKeyException: [Security:090542]

i try to run one system test on Weblogic 10 with HTTPS basic server authentication but i recieve this exception:
com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLKeyException: [Security:090542]Certificate chain received from myserver - 141.73.205.173 was not trusted causing SSL handshake failure. Check the certificate chain to determine if it should be trusted or not. If it should be trusted, then update the client trusted CA configuration to trust the CA certificate that signed the peer certificate chain. If you are connecting to a WLS server that is using demo certificates (the default WLS server behavior), and you want this client to trust demo certificates, then specify -Dweblogic.security.TrustKeyStore=DemoTrust on the command line for this client.
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:149)
at com.sun.jersey.api.client.filter.HTTPBasicAuthFilter.handle(HTTPBasicAuthFilter.java:81)
at com.sun.jersey.api.client.Client.handle(Client.java:648)
.............................................
My authentication method is :
public static WebResource createWebResource(String path) throws IOException, NoSuchAlgorithmException, Exception {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
HTTPBasicAuthFilter authFilter = new HTTPBasicAuthFilter("REST_USER", "Supervisor");
client.addFilter(authFilter);
String serverUrl = findServerUrlFromJNDIProps();
return client.resource("https://myserver:8012/ERSrestServices/" + path);
}
Where is my mistake ?
The SSL certificate is not trusted by java so it is rejecting your attempt to access the server over https.
If this is a test server with a self-signed certificate, this would make sense. If it is not self-signed, then the CA is not trusted by your java install.
As per the exception:
If you are connecting to a WLS server that is using demo certificates (the default WLS server behavior), and you want this client to trust demo certificates, then specify
-Dweblogic.security.TrustKeyStore=DemoTrust on the command line for this client.
So, -Dweblogic.security.TrustKeyStore=DemoTrust should solve your problem.
Alternatively you can add your webserver's SSL certificate to your client's java certificate store:
keytool -importcert -file certificate.cer -keystore cacerts -alias "Your Alias"
Where keytool can be found at ${jdk_home}/bin and the cacerts file at ${jdk_home}/jre/lib/security