Saturday, May 19, 2012

The Case for Service Accounts

It's a common question when writing an application.  Should the application access the database (and other services) as each individual user, or as a single application-specific service account?  This is an especially important question in any multi-tier service-oriented system.  There are pros and cons to either approach, of course.  But for my entire career I've always preferred the service account approach.  This is for a number of reasons.

First of all, you may not have an internal authentication/authorization context for every user.  The application may, for example, be a public-facing web application.  (I have actually heard someone suggest that user registration for a public website be handled through Active Directory.  Too bad I didn't get to see them try to implement that, it would have been a blast.)

Second, in multi-tier environments, passing that context from machine to machine is hard.  Have you ever had to maintain Kerberos in a Windows environment?  It's not only really bloody terrible, but from a more concrete business perspective it will devour operational expenses both in terms of downtime for users and constant support from IT staff who would be better off doing other things.

But there's a more pressing concern with the difference between user contexts and service accounts.  And it's one that's probably most often used as a reason for user contexts, even though it's really a reason for service accounts... Auditing.

"We want to maintain the user context throughout the system so that we can audit the user's actions throughout the system."

Are you sure that's a good idea?  Let's think about it for a minute...

When a user (we'll call her Mary) performs an action in the application, you definitely want to audit the action she performed.  But what was that action?  Did Mary edit a record in a database?  Did Mary call a web service?  What did Mary actually do?

The last time I saw this kind of user auditing in place, every record in the database had an audit log attached to it indicating a history of what changes were made (inserts, updates, and deletes) and which user made the change.  So the business can say with confidence that at 1:37:14 PM on May 17th 2012 Mary edited this record in the database.

Mary did no such thing.  Your audit trail is wrong.

Mary didn't edit a record in the database.  Mary performed an action in the application.  The application edited the record in the database.  Or perhaps even called a web service (which is another application entirely) and that application edited the record in the database.  Mary was completely removed from this action.  What Mary did in the application may have translated directly to a database record edit.  She may have even thought that she was directly editing a record in a database, like in old Access applications.  But the application actually performed that action.  Mary merely performed a request.

What if the application does more things unknown to Mary?  Maybe Mary told the application to update the record for a patient in a medical system.  The application updates the record, performs some other business logic on the new data, updates some other records, kicks off some tasks, etc.  Mary isn't aware of any of this.  And, more importantly, Mary didn't tell the application to do any of this.  All she did was tell the application to update some patient data.  So why should all of these other things be attributed to Mary?

Worse, what if the application has a bug in it?  What if this medical application accidentally updates the wrong patient's data?  Why would you want to blame Mary for that?  The audit trail would be very wrong, arguably criminally wrong.  Mary performed a request to update the data for her patient.  The application received that request, but did something completely different.  Mary certainly didn't do this.  The application did it.  Arguably even the developer did it.

If Mary opens up SQL Server Management Studio and directly edits data, then that should definitely use her personal credentials to audit those changes.  But that's not what's happening here.

What should be audited is the actual request Mary made to the application.  And any request that application makes of other systems in response to Mary's request.  Database edits, service calls, etc.  Each should be audited in its own right.  That audit trail can link these requests together for reporting purposes, so that one can easily determine which application requests were made in response to a user's request.  But the user's request should be the only thing attributed to the user, and that attribution should be as close to the user's actual actions as possible (that is, as close to the UI as possible) to reduce the risk of bugs changing the requests before the audit occurs.

No comments:

Post a Comment