For JBoss AS7, JBoss EAP 6 and subsequently WildFly the approach taken for authentication has been very much making use of the authentication checks performed by JBoss Remoting 3, here authentication is performed as the connection between the client and server is established. Authentication is performed using SASL which allows us to offer a set of supported authentication mechanisms for the client to choose from, possibly trying different mechanisms to identify which ones it can actually use. The identity of the authenticated user is then used for any requests processed over that connection.
For authentication over HTTP we have been able to take advantage of being able to see the address of the resource being accessed before authenticating, this means that authentication does have the opportunity to be more specific to what is accesses. Similar to SASL clients can be offered multiple mechanisms to choose from selecting the mechanism they can handle.
The drive to minimise the number of ports in use by an installed server is leading us to a point where almost all traffic would be routed over a single Remoting connection, with the addition of support for HTTP Upgrade even HTTP invocations quickly delegate everything to Remoting leaving Remoting to handle the authentication.
Various limitations have been found with using an authenticate on connection approach, this article is to capture them all.
Per Request Identity Switching
This has probably been the most complained about issue affecting applications clients making calls to deployed EJBs. By using JBoss Remoting multi-threaded clients are able to use a single connection to the server to send multiple requests concurrently, even single threaded clients re-use an existing connection - the authentication on connection approach means that all requests over this connection are executed as the same user.
Previous AS releases would send the username and password in the clear with each request, this would mean that each EJB invocation could be executed as a different user - however for WildFly we are looking to avoid any clear password propagation where it can be avoided.
So far one solution has been provided in the form of a quick start, client side and server side interceptors can be added combined with a 'Trust' login module to request that an individual request is switched to run as a different user. Passwords are not exchanged in the clean but instead the login module verifies that the user that opened the connection has the permission to allow it to execute requests as the user it specifies.
A more complete solution is being discussed where we introduce an 'authentication service' - essentially this is a service that can be called after a successful connection is established to perform an additional SASL based authentication. The SASL authentication will support both authentication involving credential validation e.g. DIGEST and also run as type authentication where the user that established the connection is asking permission to run requests as a different user. The result of this authentication to the authentication service will be an authentication token which is tied to the connection - subsequent requests over that connection can use the token to request the previously authenticated identity can be used. Replays are protected against by binding the token to the connection.
The quick start solution previously provided is very much specific to EJB invocations, the authentication service will be more tightly integrated with the Remoting communication and so allowing it to be used for all services available over the remoting connection - this will be especially beneficial where different services are accessed over the same connection - as an example JMX and the management API.
This is closely related to the identity switching issue, as requests are processed on one server - where it results in a request being passed onto another server it is desirable for the identity of the user to be propagated to the second server.
In previous AS releases as the users username and password were received in plain text these can just be forwarded over to the next server.
The quick start mentioned in the previous section is also the current solution for this, as the client server has established a connection to the second server it's user is trusted to request that requests are processed as users it specifies.
As we move to the authentication service solution instead of relying on EJB interceptors the client server will be able to use the authentication service to request an authentication token which is subsequently uses for the actual invocation.
Host Controller (And AS Instances)
The management of AS7 / EAP6 / WildFly is also performed using connections over JBoss Remoting - where we have indivudal server processes and slave host controllers in domain mode these all establish connections to their master host controller over JBoss Remoting. As a result of this they all make use of the standard authentication mechanisms already in use over these connection.
This introduces it's own problems as host controllers need to have an account within the security realm configured for the connection and the server instances need to use a specially created on-demand account. With the introduction of access control we know these connections are established for a specific purpose so it may be appropriate to introduce additional SASL mechanisms specific to their use. This would allow these processes to be registered independently of the realm used to authenticate the real users.
A second area to address here is how complex it is to configure a slave host controller to authenticate against it's master. Whilst we should always support unzipping with a valid config I believe there is also an opportunity for a guided connection process a couple of options could be: -
- A slave attempts to connect to the master but is not recognised, an administrator logs into the admin console for the master and sees the failed connection attempt and clicks on 'trust' to allow that slave to connect - updates to configuration will automatically be made so that slave is always allowed to connect.
- The administrator runs a wizard on the slave, connects to master and authenticates, the wizard then runs through steps making config changes to master and slave simultatneously so that when the slave starts it can connect to master.
This is closely related to the authentication as firstly is provides a way to encrypt any sensitive tokens exchanged between the client and the server and secondly it provides a way for the clients to authenticate and also verify the process they are connected to is trusted.
Shipping with a default key would not be practical, all users would be able to obtain the private key from the distribution making the key redundant as anyone would be able to decrypt anything encrypted by it.
Dynamically generating these on start up would not be practicle for two reasons: -
- Increased start up time on first boot - this server is supposed to be even @#$%ing faster.
- The name of the key needs to be tied to the host name used to connect to the server, this is not always trivial to detect and the first boot may not have had the network interfaces correctly configured yet.
Instead I would suggest a second wizard, the admin console can display a warning somewhere 'TLS/SSL Is Not Enabled, Would You Like Help Enabling It?' this can then guide the process including asking the required questions - could even go to the point of creating certificate signing requests and import of signed certificates.
Kerberos is also regularly requested and should be added as an additional supported mechanism, JBoss Remoting and Undertow both support it now so the remaining task is configuration within the security realms and the integration of JBoss Remoting and Undertow to actually enable it.
Where possible any authentication mechanisms should be configured to support mutual authentication / verification of the server. i.e. if a client connects to a rogue domain controller it should be possible to detect this,