0
votes

I am designing the authentication system for a piece of software and need some guidance on how SASL and Kerberos services interact.

Here is the situation:

I have a client/server application that is itself pretty standard: only registered users can use perform actions. As an MVP I would typically implement a pretty standard solution:

  • Database stores username + salted hash of passord
  • Authentication attempt from client over HTTP includes username/password over TLS
  • Backend checks that username/password are valid and returns a bearer token that can be used for the duration of the session

In this case, however, there is a complicating factor. Some users of our system use Kerberos internally for user authentication for all internal services. As a feature, we would like to integrate our software with Kerberos so that they don't have to manage an additional set of users.

A more senior engineer recommended I look into SASL so that we might support several auth protocols simultaneously; standard customers can authenticate their users with the PLAIN method (over TLS), for instance, while other customers could limit authentication to only the GSSAPI method.

Up to this point, I have a clear idea of how things might be set up to achieve the desired goals. However, there is one more complicating factor. Some of the customers that want our system's auth to support Kerberos have other resources that our system will rely on (like HDFS) that also require authentication with Kerberos.

My understanding of Kerberos is this:

  • A client authenticates with Kerberos's ticket granting server
  • Upon successful authentication a TGT is returned that can be used for any future interaction with any Kerberos service in the system

Now to the point: How can I make all of these technologies work in harmony? What I want is: - Client logs into my server - My server authenticates client using customer's Kerberos system - Client is given the OK - Client asks for something from my server - My server needs access to customer's HDFS, which requires Kerberos auth - Server authenticates without asking the client to authenticate again

One possible solution I see to this is the following:

  • Make my server itself a Kerberos user
  • When the server needs to perform an action on HDFS, have it authenticate using its own credentials

There is a big downside to this, though: pretend the customer's Kerberos system has two realms: one with access to HDFS and one without. If users of both reals are allowed to use my system, but only one set can use HDFS, then I will need my own logic (and potentially objects in a DB) to determine who can perform actions that will require access to HDFS and who cannot.

Any pointers are going to be super helpful; in case it isn't obvious, I am quite new to all of this.

Thanks in advance!

1

1 Answers

1
votes

It's not clear exactly what your question(s) are, but I'll do my best to address everything I think you're asking.

Firstly, I just want to clear this up:

Upon successful authentication a TGT is returned that can be used for any future interaction with any Kerberos service in the system

That's not quite correct. The TGT enables the user to request service tickets from the KDC for specific services. The service ticket is what gives the user access to a specific service. The TGT is used to prove the user's identity to the KDC when requesting a service ticket.

Client asks for something from my server - My server needs access to customer's HDFS, which requires Kerberos auth - Server authenticates without asking the client to authenticate again

This is a common enough problem and the Kerberos solution is called delegation. You should try to use Kerberos delegation in preference to coming up with your own solution. That said, how well supported it is depends on the technology stack you're using.

There are 2 kinds of delegation supported by Kerberos. The first kind is just called "delegation" and it works by sending the user's TGT to the service along with the service ticket. The service can then use the TGT to get new service tickets from the KDC on behalf of the user. The disadvantage of this approach is that once a service gets a user's TGT, it can effectively impersonate that user to any service that the user would be able to access. You might not want the service to have that level of freedom.

The second kind of delegation is called constrained delegation (also known as services4user or S4U). With this approach, the client doesn't send it's TGT to the service, but the service is allowed to ask the KDC for a service ticket to impersonate the user anyway. The services that can do this have to be whitelisted on the KDC, along with the services that they can request tickets for. This ultimately makes for a more secure approach because the service can't impersonate that user to just any service.

A more senior engineer recommended I look into SASL so that we might support several auth protocols simultaneously; standard customers can authenticate their users with the PLAIN method (over TLS), for instance, while other customers could limit authentication to only the GSSAPI method

Yes this is a good idea. Specifically, I'd recommend that you use the exact same session authentication mechanism for all users. The only difference for Kerberos users should be the way in which they get a session. You can set up a Kerberos-protected login URL that gets them a session without challenging them for credentials. Any user that hits this URL and doesn't have Kerberos credentials can just be redirected to a login page, which ultimately gets them the same session object (once they log in).

On the back end, the credential checking logic can use SASL to pass Kerberos users through to the KDC, and others through to your local authentication mechanism. This gives you a seamless fallback mechanism for situations when Kerberos doesn't work for the Kerberos users (which can happen easily enough due to things like clock skew etc.)

There is a big downside to this, though: pretend the customer's Kerberos system has two realms: one with access to HDFS and one without. If users of both reals are allowed to use my system, but only one set can use HDFS, then I will need my own logic (and potentially objects in a DB) to determine who can perform actions that will require access to HDFS and who cannot.

This kind of thing is exactly the reason that you should use Kerberos delegation instead of coming up with your own custom solution. With Kerberos delegation, the KDC administrator control who can access what. If your service tries to impersonate a user to HDFS, and they are not allowed to access it, that authentication step will just fail and everything will be ok.

If you try to shadow the KDC's authorization rules in your own application, sooner or later they'll get out of sync and bad things will happen.