I will soon be testing the connectivity between two servers. Both involve self-signed certificates that are shared in one another's trust store. There are many details that factor in to a successful connection between two servers. If you're not using a CA certificate chain, you need to make sure that you have exported valid public certificates and then installed peer certificates in the server's trust chain. If signing is used, what ciphers are your servers configured to use? Are your certificates expired? Does the DN value match the domain of the server's involved (host-name verification). Again, there are many factors.
A pragmatic approach to testing the ssl connection between two servers is to execute a series of tests in building block fashion. First, just make sure that you and your peer servers have adjusted one another's firewalls to allow access. Do this first without mixing in certificates or ssl. If there are proxies involved (load balancing?), resolve any issues there too. I'm not sure if there are proxies that can simply pass the https request along to the next destination; it feels like there might be some security issues there. I have seen examples where the proxies handle the SSL and then package up the attributes (as environment variables?) and pass them along to secondary servers. Once the two peer servers can issue commands to one another (e.g., web service), you're ready for the next step.
One-way ssl can be thought of as a client verifying the server, but the server doesn't care didley-squat about who the client is.
- Client knocks on the server's door
- Server opens the door without asking who's there and hands them a copy of a key to their garage (their public key), waves goodbye, and closes the door
- Client opens the garage, drops off some boxes of clothes and grabs a soda from the outside fridge
- Client keeps Server's key on keychain for the next visit; no big deal if he loses it. He can always knock on the door again and get another copy from the Server
Two-way ssl involves two people who are more reserved. This server has a more cynical view on life and won't hand out keys to just any guy on the street.
- Client knocks on the server's door
- Server asks the Client for his name, driver's license and another form of photo id.
- He calls up the DMV to verify that there is such a person and that their license was issued from the DMV.
- He may check to see if the Client is on the list of people he is expecting to stop by if an appointment was made in the past
- If the Server doesn't trust the Client, he throws the Client's references out the mail slot in the front door; the door is certainly not opened.
- If the Server does trust the Client, he opens the door and gives him a key.
- Like with the other case, the Client then has access to designated rooms in the Server's house as the Server sees fit.
In preparation for running these tests, I wanted to make sure what configuration changes need to be made for each test phase. I ran tests and pulled together the following matrix:
Green == "can access" and Red == "rejected". Some rejection takes place before the client is even out of the starting block. This could be due to the fact that you don't have any certificates and the server is asking for one. This often times shows itself as an ugly and cryptic error message displayed in your browser or an exception that is thrown by your client code. If the client has a public certificate to hand to the server, if upon evalation of the client's certificate the server finds it untrustworthy, the client can be rejected that way too. These tend to represent themselves as return codes 401 or 403.
Many of the colored boxes have reference numbers in them. I have collected some screen captures to provide some context for the test results in the matrix.
Server Configuration
Our server is using Apache CXF to manage our web service behavior, including authentication. Important components in this configuration are:Apache Tomcat
- server trust store includes client's public key (required for two-way ssl only)
- tomcat/conf/server.xml
- tomcat/libexec/conf/tomcat-users.xml
The Tomcat server must be listening on an ssl-enabled port. Whether to set clientAuth to 'true' or 'false' is determined by whether the server will use one-way ssl or two-way ssl.
If two-way ssl is configured, users will be authorized once they have been authenticated. A 'user' entry is made, associating the full DN value from a client certificate with a role. The role will then be used later on to determine if a user is authorized to access a resource.
Web Service Application
- webapp/src/main/webapp/WEB-INF/web.xml (example)
One-Way SSL (Server)
Our server can establish one-way ssl by:- web.xml: remove the security-constraint, login-config and security-role
- server.xml: ensure that clientAuth="false"
Two-Way SSL (Server)
Our server can establish two-way ssl by:- web.xml: include the security-constraint, login-config and security-role
- server.xml: ensure that clientAuth="false" (yes, still false; CXF is handling the authentication and authorization)
- tomcat-users.xml: ensure the client's DN has been included in the list of authorized users and the correct role(s) has been applied. The DN must be identical to how it appears in the client's public certificate.
Client Configuration
SOAP Client Application
- client trust store includes servers's public key (for both one-way and two-way ssl)
- ws-ucidm/src/main/java/xxx/xxx/idm/UCIDMServicesClient.java (snippet)
- ws-ucidm/src/main/resources/ClientConfig.xml (example)
Apache CXF uses Spring xml configuration files to authenticate the server. The client code pulls in this configuration file and automatically handles the ssl handshaking required to establish a secure connection. I believe it also verifies the signature and handles the encryption/decryption of the SOAP body. With the Spring xml configuration in place, the Java client need only include 4 lines of code to automatically handle encryption and signing for you.
One-Way SSL (Client)
The burden of determining one-way or two-way ssl lies primarily with the server. In either case, the client code will need to include the server's public certificate in it's own trust store. This means the client must have an unexpired certificate to go along with his trust store, although in the case of one-way ssl, the server won't even ask for the client's public certificate.Two-Way SSL (Client)
The client must provide a public certificate to the server that is trusted by the server. Now a particular certificate must be used, not just any one.Surely there are lots of things that could go wrong in this test, factors that weren't even mentioned here. But I hope this overview provides enough to understand what's going on so that troubleshooting can be more easily accomplished.
No comments:
Post a Comment