What do I
have to hide?
If you are dealing with an information system, you always have something
to hide. Maybe not at first, but as your system grows, it starts to accommodate
more users of various roles and positions inside or outside the organization. Perhaps
the types of information you store diversify as well. At some point, you're
going to need some boundaries to protect that information, or your data
management will end up looking like a Harlem Shake.
For instance, say you have a software system for managing scientific
experiments and results. Its purpose is to allow the public easy access to
research and to allow scientists to share their knowledge. So why hide
anything? It may seem at first sight that you would not need any security here,
but let us consider some example use cases:
- A general user who wants information about children's safe attachment
- A biologist wants to see the latest news about stem cell research
- A member of a cross-disciplinary research project wants to see its progress
You can see how all of these users are out for the same type of
information (results of research), but as the architect of the system, you
would want to give them different levels of access to it, since you wouldn't to
expose the details of an ongoing project to anyone but the team and if you're a
biologist you can probably see some partial and unverified results that perhaps
you wouldn't want to share with the general public at this point.
Let's try to describe a simple security layer to address those needs.
Building a protection layer
Unknown location
The easiest and simplest way to keep a secret. You want to hide
something? Don't tell anyone where it is. This is similar to how Google allows
you to share photo albums with "Anyone with the link". Given that the
link is random enough, it would be pretty hard for someone to locate it.
However, once the link is leaked you lose control over it. You give one
colleague the link to your research results and he sends it to his journalist
friend and you don't know what happens next.
Password protecting
So maybe just put a password on anything you want to keep safe? Again,
the password could be leaked, but even if it doesn't or you are able to change
it in time, this is problematic since now you need to manage a whole range of
passwords for all your data and remember everyone else's passwords. This is
very cumbersome and inefficient and doesn't provide real security.
User
identity
Why don't we approach this from a different angle and try to identify
the user first and then let him access the application? Let's assume our
program has some sort of login mechanism in which it identifies the user. The
user then tries to find the relevant information. This approach works better
than the previous ones since there is no need for user interaction after the
first identification (which can sometime be done automatically using Singe Sign On). Also,
the control is granular and dynamic per user, so we have lots of control.
But, as Uncle Ben once
said, with great control comes great complexity. We now have the
responsibility to assign (and maintain!) the different permissions for all
users and data which can amount to thousands or even millions of combinations.
A simple,
scalable solution
So we come to the conclusion that while using user based permissions is
secure enough, we need a way to treat the users as groups with common
properties rather than as individuals. If we could label the data in a smart
way, users will have an easier time accessing it.
How can we do this? There are several common ways:
- Flat labeling – marking pieces of data with some sort of label or tag is the basis of Web 2.0. We can mark each project with a unique label, if needed.
- User groups – we can assign the user to various groups according to his affiliation. For example, "biologists from Oxford" can be such a group if we want to allow them to share information only they will see. Another option is to separate "Biologists" and "Oxford" and use some sort of combination logic.
- Roles – If you wish to expose only some of the data to general users, this can be accomplished by assigning a hierarchy of roles and only allowing "scientists or above" to view it.
Accessing the data can be done via a (simplified) method such as:
[Secured(true)]
IEnumerable<ResearchData> GetResearchData()
{
return DAL.GetData<ResearchData>();
}
Notice a couple of things about this method:
- The DAL object is some object that allows fetching data from a DB or a service without being aware of security limitations. Don't allow direct access to it.
- It has a "Secured" attribute with the value set to true, which means it will trigger some code using an AOP technique.
This is what the implementation of "Secured" should look like:
public class SecuredAttribute : AOPAttribute
…
public override void OnSuccess(MethodExecutionArgs args)
{
Credentials creds = GetUserCredentials();
args.ReturnValue = creds.Filter(args.ReturnValue);
}
…
GetUserCredentials() gets a class that consists of the grouping of users
which we talked about before and has logic to filter the input data with.
Summary
In this post, I gave an example of a security layer implementation. Of
course, every system has its unique needs and should be considered
independently. However, I feel there are general principles which hold true for
all cases and they should be followed as guidelines:
- Keep your security flexible – you never know when a security level for data or users will change.
- Separate concerns – let your business logic do its thing, don't mix in security. Try to do as little as marking a method with an attribute, and perhaps not even that. Notice how in the example the logic of filtering by credentials is centralized in a single location, easy to understand and change. NEVER CHECK FOR USER CREDENTIALS IN DOMAIN CODE.
- Identify your roles – This is important because once you've managed to map credential types to use cases, you've solved the main logical challenge. Don't get stuck too much on this though, since if you separate concerns properly, you will be able to change this later on.
Good luck!
No comments:
Post a Comment