Talos – the expressive authorization engine
At some point or another, every application needs to handle authorization processes.
Most authorization engines require your application code to jump through loops to check and change access rights. You end up polluting your code with things that don't have anything to do with authorization.
Explain yourself
"Who are YOU?" said the Caterpillar.
This was not an encouraging opening for a conversation. Alice replied, rather shyly, "I-I hardly know, sir, just at present — at least I know who I WAS when I got up this morning, but I think I must have been changed several times since then."
"What do you mean by that?" said the Caterpillar sternly. "Explain yourself!"
"I can't explain myself, I'm afraid, sir" said Alice, "because I'm not myself, you see."
"I don't see," said the Caterpillar.
Talos provides expressiveness to authorization code. It looks almost like english. Sure, it's not buzzword-compatible, but it's clean. You can check access rights and change them in single-line commands, directly from the code, without dealing with external XML, policy files, and classpath. See for yourself.
Overview
The problem
Talos is an authorization engine designed for easy and efficient management of access rights. All the work is done using an intuitive API that ressembles a domain-specific language.
Authorization refers to the process of deciding if someone can do something on something:
- Bob wants to feed Mingau the cat
- Win32.mm wants to send and receive over the network.
- Email from tminc@uol.com.br wants to be stored on the inbox.
A fluent interface
Talos uses a Java API to store authorization data in a relational database. The sentences above translate to:
if (talos.withSubject("Bob")
.andObject("Mingau")
.isAllowed("feed")) {
// do stuff
}
At any time, we can allow or deny stuff on many objects and many subjects:
talos.withSubjects("Bob", "Maggie", "John", "Denise", "Andy")
.andObjects("Mingau", "Spotty", "Kitty")
.grant("feed");
talos.withSubject("Win32.mm")
.andObject("Network")
.revoke("send", "receive", "listen");
Of course, Talos needs to know these elements first. Let's say Lisa comes to live with Bob and the others. She also needs to feed the cats. I can do it all at once (not that I would always want to):
talos.createSubject("Lisa")
.andObjects("Mingau", "Spotty", "Kitty")
.grant("feed");
The Bouncer
If I have to check many permissions, I can use the bouncer:
Bouncer bouncer = talos.withSubjects("Lisa", "Maggie")
.andObject("Mingau");
if (bouncer.isAllowed("feed")) {
// feed the cat
} else if (bouncer.isAllowed("stroke")) {
// stroke the cat
}
Sometimes I need to ask Talos about the subjects (the who part) or the objects (the what part) that can do something with the permissions. Let's say I want to know who can feed or stroke Spotty and Kitty:
Collection<String> names = talos.withObjects("Spotty", "Kitty")
.andAnyPermissions("feed", "stroke")
.listNames();
Printing names would give me Bob, Maggie, John, Denise, Lisa, Andy.
I might also want to know which cats Maggie can stroke and feed:
Collection<String> names = talos.withSubjects("Maggie")
.andAllPermissions("feed", "stroke")
.listNames();
Categories
If a new cat comes along, I don't want to need to grant all permissions all over again. I will define a category and grant rights accordingly. Andy and John will be responsible for cats by default:
talos.createCategory("cats")
.addObjects("Spotty", "Kitty", "Mingau");
talos.withSubjects("Andy", "John")
.andCategory("cats")
.grant("feed", "stroke");
This means that if I add a new cat, they can feed it:
talos.createObject("Caramel")
.addCategories("cat");
Bouncer bouncer = talos.withSubjects("John")
.andObject("Caramel");
Collection<String> names = bouncer.listNames();
I know that names contains at least feed and stroke, and that bouncer.isAllowed("feed") will return true. When querying, I might also restrict objects by category, so I am sure I'm asking about which cats Maggie can take care of:
Collection<String> names = talos.withSubjects("Maggie")
.andCategory("cats")
.andAllPermissions("stroke", "feed")
.listNames();
Conclusion
Talos allows the programmer to express their authorization requirements concisely with minimal operational overhead. And that is, in our opinion, how access rights should be managed.