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.
Overview