Client certificates with AWS API Gateway - authentication

I am trying to implement mutual authentication for the communication between aws api gateway and my server. I want to use the client side certificates that amazon offers for authentication. I know that my server is configured correctly because previously I was using a lambda function and mutual authentication was working.
I have exported the (.PEM) certificate and added it into a truststore. I have configured my Jetty server to use that truststore for authentication. I have set client-auth to :need. I know my server is set up correctly because it was working with with my self-implemented mutual SSL. All I did was change the truststore. When I test my method gateway returns a 200:
{ "message": "Unknown endpoint error."}
Here is an excerpt from the server log files. It appears that the server side handshake completes, but there is an error with the client certificate.
pConnection#3a0a2e84{FILLING} server-side handshake completed
2015-09-28 13:04:29,856 DEBUG [qtp1980278840-19]
o.e.j.i.ChannelEndPoint - flushed 45
SelectChannelEndPoint#2c05eeb2{ec2-xx-xxx-xxx-x.compute-1.amazonaws.com/5x.xxx.xxx.x:43942<->4000,Open,in,out,-,-,0/200000,SslConnection}{io=0,kio=0,kro=1}
2015-09-28 13:04:29,856 DEBUG [qtp1980278840-19]
o.e.j.i.s.SslConnection -
SslConnection#50e2de43{NOT_HANDSHAKING,eio=0/0,di=-1} ->
HttpConnection#3a0a2e84{FILLING} flush exit, consumed 0 2015-09-28
13:04:29,856 DEBUG [qtp1980278840-19] o.e.j.i.s.SslConnection -
SslConnection#50e2de43{NOT_HANDSHAKING,eio=0/-1,di=-1} ->
HttpConnection#3a0a2e84{FILLING} unwrap Status = BUFFER_UNDERFLOW
HandshakeStatus = NOT_HANDSHAKING

I have solved this problem. The server logs I posted are misleading. No handshake occurs because the server certificate I was using was self signed, not signed by a trusted CA. As of 9/28/2015, aws api gateway requires a certificate signed by a trusted certificate authority. Because my cert was self signed, the server (and client) handshakes do not complete. Hopefully this problem will be solved in future versions.

Related

IBM App Connect error javax.net.ssl.SSLHandshakeException

I created a message flow having rest request node to connect to an API. API security enabled received the following error:
BIP3165S: An error occurred whilst performing an SSL socket operation.
Operation: connect. Error Text: javax.net.ssl.SSLHandshakeException:
com.ibm.jsse2.util.j: PKIX path building failed:
com.ibm.security.cert.IBMCertPathBuilderException: unable to find
valid certification path to requested target.
How do I solve this issue in my message flow?
I disabled SSL but still received the same error.
What is the SSL client and server endpoints? Assuming this connection is:
WAS (server) <------SSL------> API (Client)
In one-way SSL, the solution is to add the root or intermediate certificate (from the WAS server's chain) to the client's trust store.
"PKIX path building failed" usually indicates that the SSL client was unable to authenticate the SSL server (remote host). To authenticate the server, the client needs to have the server's root or intermediate certificate in its trust store.
If this is happening with traditional WebSphere as the client, we can try to add the signer certificate with retrieve from port.
If mutual authentication is enabled, the issue can be with the server being unable to authenticate the client.
Either way, an SSL exception should not occur with SSL disabled. Maybe the server wasn't re-started after disabling SSL? Maybe SSL wasn't disabled correctly (on both endpoints)? Maybe the API was still trying to use HTTPS with SSL disabled?

Is there any method in netty ssl client to know if server requested client certificate after completion of SSL Handshake process

I have a Netty HTTPS(SSL ENABLED) Client which communicates with both Mutual Authentication enabled servers and Mutual Authentication non-enabled servers.
Following is the code I use to Setup SSL Handler for Client.
TrustManagerFactory tmf= ...// Necessary Trust certs
KeyManagerFactory kmf = ...// Necessary Client certs
SslContext sslContext = SslContextBuilder.forClient().keyManager(kmf).trustManager(tmf).build();
SslHandler sslHandler = sslContex.newHandler(ByteBuffAllocator);
I use the above sslHandler in the pipeline. I know that providing keyManager(kmf) will provide client certificate to server if server requests. Everything works as expected.
MY NEED : I need to know if the Server requested Client certificate or not(ie. Mutual Auth enabled server or not) in SSL Handshake process. I need to know this after completion of Handshake process.
You could provide your own KeyManager implementation (that later calls the actual KeyManager). If getPrivateKey() is called you know that the server has requested the client certificate.

Cannot get mutual authentication with Keycloak and OpenLDAP working

I've been attempting to get mutual authentication working between Keycloak and OpenLDAP. I've configured the truststore on Keycloak under security realms, which works. I can view the certificate on requests. I've also configured OpenLDAP's truststore/keystore and set it to demand a client certificate. When using ldapsearch I can provide Keycloak's cert which allows me to connect. I've also verified that Keycloak accepts OpenLDAP's cert by changing OpenLDAP to not demand a client certificate, which allows Keycloak to connect (albeit after fixing the truststore). At this point, it appears everything is fine except Keycloak doesn't present it's certificate while acting as a client, and I get the following error in OpenLDAP.
TLS trace: SSL3 alert write:fatal:handshake failure
TLS trace: SSL_accept:error in error
TLS: can't accept: error:140890C7:SSL routines:ssl3_get_client_certificate:peer did not return a certificate.
Unfortunately I cannot share details about the configuration or environment beyond the above due to project constraints.

tomcat client authentication using clientAuth=want

My application requires client authentication for a specific URL, after client authentication succeeds the application itself also does some verification on the client certificate subject (using spring security x509 filter). I wanted to configure tomcat to force client authentication (clientAuth=true) for the specific URL, but based on this post it seems I can't do this only using tomcat - configure tomcat for client authentication only for specific URL patterns.
My question is, if I use clientAuth=want, will the following be as below when the server requests a certificate:
If device has an identity certificate but not trusted by the CA configured in tomcat truststoreFile, no certificate will be passed and the request will fail in the spring security filter (certificate will be null)
If device has an identity certificate trusted by the CA configured in tomcat truststoreFile, but is invalid (not sure what validations are done) or expired, either the authentication will fail in tomcat (before the security filter) or as in option 1 no certificate will be passed and the request will fail in the spring security filter (certificate will be null)
Is there a security hole I may be missing using this configuration of want + security filter? I guess the question is - if a certificate is eventually passed from the device to the server, the server will always validate it (not expired, trusted etc) even when using clientAuth=want and will not allow the client to continue if the certificate is invalid? The case where no certificate is passed is covered by the security filter that will check the certificate is not null..
Thanks!
Your assumptions in both 1. and 2. are correct. Tomcat will not allow untrusted or invalid certificates through to your application. If you get a null certificate, you can assume that either no certificate was passed, or an untrusted/invalid certificate was passed.
On the project I am working on we have the same requirement as you: client certificates for certain URLs only. We found out by experimentation how "clientAuth=want" works.

403.7 IIS 7.5 SSL client certificate authentication issue

I am testing a web service with an external partner using 2 way SSL under IIS 7.5. I am requiring SSL, requiring a client cert, and using one to one mapping to authenticate to a domain account. I have configured everything and it works fine on our network (I am able to provide a client cert, get authenticated and invoke the service from browser and test harness).
From outside of our network (in most cases, see below), I am getting a 403.7 error. I have gone through the machine level certificate store and made sure the certificates and CAs are trusted.
Here's the weird thing. I obtained a Type I cert to test from home (and got 403.7 like our intended partner is). So I setup Fiddler to debug SSL and send my certificate, and this works for some reason. I setup a test harness to pass the exact same certificate, and got 403.7. I test in my browser (IE 9), don't get a prompt for a client cert, and get 403.7.
Any help appreciated.
Bill
Last time I checked, IIS was using re-negotiation (by default) to get the client certificate: there is a first handshake where the server doesn't request a client certificate, followed by another handshake (encrypted this time) where the server requests the certificate (via a TLS CertificateRequest message). This will prevent you from seeing anything from Wireshark, unless you configure it to use the server's private key and decipher the traffic (note that this only works with some cipher suites).
One way to see the client-certificate negotiation is to configure IIS to use initial client certificate negotiation, using netsh and clientcertnegotiation=true (which is about initial negotiation). At least the CertificateRequest and the certificate will be sent in clear during the handshake, so you should be able to see this with Wireshark.
If the client isn't sending a certificate to the server as a response to the CertificateRequest, you'll still see an empty Certificate message from the client.
If you don't export the private key with the certificate to use with Fiddler or whichever other client, there is no chance that it will be able to use the certificate. It may at best try to send the certificate, but the handshake will fail (since the CertificateVerify message needs to be signed by the client's private key).
I guess you may encounter a problem whereby:
not presenting a certificate is accepted by the server (it's effectively optional),
presenting an invalid certificate makes it fail and causes this 403.7 status code (many servers and SSL/TLS stacks would implement this as a fatal error, but TLS specification doesn't say that unsupported_certificate, certificate_revoked, certificate_expired, certificate_unknown should be fatal, so this is at the server's discretion).
Are you using the same physical machine to test both the in-network and external-network connections? If not, are you sure that the external-network client has the private key accessible?
I have not configured Fiddler client authentication before. Does it read the client certificate and key from the standard certificate stores? Does it read directly from a PKCS12?
One other thing that may be helpful is inspecting the TLS handshake in WireShark. Specifically, check out the Server's "Certificate Request" message, as the data here clues the client (IE9) which client certificates it should display in the prompt. Compare this for the internal and external connections.