Having just spent the best part of the morning debugging this behaviour, I thought it was worthwhile sharing with the community.
Let me first describe the situation I was finding:
- I had previously created lots of APIs with mutual SSL on the GW (require SSL with client certificate authentication).
Typically the client certs are self signed certs generated by the consumers of the APIs - the public cert being stored in a FIP and compared in the policy to allow access to a particular client.
I've done tons of these for various customers.
To test with SOAPUI, add the p12 key to the SSL options, etc and all is well - GW prompts for client cert on testing a mutual SSL API - soapui sends cert, job done.
If any of above is new to you - plenty of info on internet about setting soapui up to send client certs, etc.
Now, with a new customer, I had another mutual SSL requirement for an API - so did it again. BUT suddenly soapui is not working anymore - it is not sending the cert.
OK, that's enough background - I won't go into the 4 hours of debug - just present solution now:
- SOAPUI 5.3.0 (all all previous version afaik) has the following weird behaviour:
- If the SSG is set to allow TLS1.0 only (the default until I believe v9.0 of the GW), then SOAPUI works fine - it does the handshake, gets asked for client cert, provides it, GW verifies in policy and all is good.
-If the SSG is set to allow any other versions (1.1 only, 1.2 only, 1.1+1.2, 1.0+1.1, 1.0+1.2, 1.0+1.1+1.2) soapui will fail to work. It will not send the client cert at all and your policy will therefore fail since no client cert was received.
Now this is not strickly speaking just a soapui issue, but an interpretation it is making for RFC 2246:
When the server (the GW) asks for a cert it tells the client what cyphers it likes, and what CAs it PREFERS:
certificate_authorities A list of the distinguished names of acceptable certificate authorities. These distinguished names may specify a desired distinguished name for a root CA or for a subordinate CA; thus, this message can be used both to describe known roots and a desired authorization space.
Now, by default if there are no CA capable keys in the GW private key store, this will be (wrongly imho) the server's SSL key (which in almost all cases is not a CA capable key).
IF there are CA capable keys in the GW private key store, it is set to a list of those.
What soapui seems to do ONLY honor this when it doesn't negotiate TLS1.0. If it's TLS1.0 - all is well.
NOTE: it does this even when TLS1.0 is still supported since it does 'support' TLS1.1 - so it effectively breaks itself by choosing 1.1 if it's available on the server.
From a client point of view I don't know how many clients/consumers this behaviour effects - it depends on their implementation of RFC2246 frankly.
- you have mutual SSL protected APIs developed with self signed certs now - working fine with your SSL settings configured at the default of TLS1.0 only (I know this is terrible - but it WAS the default until v9.0). If a pen test, etc points out this as bad (as it should) and you disable TLS1.0 and enable 1.1 and/or 1.2 - there is a possibility that some/all of your clients will not be able to connect to your mutual SSL APIs anymore IF their client code/libraries implement RFC2246 in the same way as soapui (i.e. it's asking for cert signed by CA 'bob.com' - the one I have is a self signed cert - so I won't send it)
- your clients all hard send the certs anyway, and effectively ignore the CA list in the servers client cert request. This is the case with command line tools for example - like wget and curl which still work fine.
NOTE: This is not a GW bug. I am simply pointing out that the vagaries of client authentication in the RFC will mean that a variety of implementation are out there consuming any mutual SSL APIs you have - so IF/when you turn off TLS1.0 expect to have to do some regression testing to determine if you are affected by the above.
OK - so you've tested - and it IS worst case - your callers code isn't sending the certs anymore. What can you do ?
Well, you need to do the following:
1. create a CA capable cert of the GW (see docs)
2. ask your customers to generate a CSR for their current client cert and send you it
3. sign the CSR in the GW PM with the new CA capable cert you have created.
4. give customers the signed cert and tell them to replace the cert chain of their key with that.
5. customer now can use same client key (but now it's signed with CA)
NOTE: no policy changes should be required since it's the same client key still - so still valid in any FIP you have it in, will still authenticate with whatever code you had in there to do that previously, etc.
Now, when the SSL handshake starts, the GW will ask the client for a cert, and will tell it that it would prefer one signed by the CA capable cert CN you just created.
Since the client cert IS now signed by a CA in that list, it will send it and all will be well.