Fernando Pereira got his Ph.D at the University of California, Los Angeles, in 2008. Since 2009 he is an associate professor at the Department of Computer Science of the Federal University of Minas Gerais, where he leads the Compiler’s Lab (http://lac.dcc.ufmg.br/).
Why another policy language?
The design and specification of access policies is an important aspect of the construction of distributed systems and services. Developers currently can use different approaches to fulfill this task. And yet, most of these approaches rely on general purpose data-description languages, such as YAML, JSON and XML. Such formats are employed in systems of vast importance, such as Amazon’s AWS CloudFormation, Microsoft’s Azure and Google’s Firebase. Yet, it is our understanding that such formats, not having been conceived to this particular domain, could be replaced with more expressive specification languages. Such is the goal of the Hapi Project.
What is HAPI?
Hapi (short for Hierarchical Access Policy Implementation), is a specification language that lets users define access policies. In a distributed system, an access policy defines the actions that each actor can perform on the available resources. Such policies are important because they ensure the preservation of the integrity and the privacy of personal information that users might store into remotely accessed databases. As an example, the specification below indicates that Bob can read all resources, Interns can read emails and credit card numbers, but Alice, who is an intern cannot read emails.:
main =
DENY
EXCEPT
ALLOW {
Actor = Bob
Actions = Reads
Resources
}
ALLOW {
Actor = Intern
Actions = Reads
Resources = EMAIL, CCN
}
EXCEPT
DENY {
Actor = Alice
Actions = Reads
Resources = EMAIL
}
Hapi is strongly based on Sen et al.‘s Legalease, a domain-specific language that supports the specification of hierarchies of access policies. In Hapi, Actors might have their rights either increased or decreased as they move down this hierarchy. Syntactically, the position of actors within this hierarchy is given by indentation; which like in Python, has semantic meaning in Hapi. Access hierarchies determine partial orders between actors and groups of resources. Thus, partial ordering emerges as a powerful metaphor to specify the access rights of groups and subgroups of users.
How does Hapi compare with other policy languages?
Legalease
Hapi extends Legalease in several different ways. Mostly, the original specification of Legalease is not sufficiently explicit about the language’s grammar and usability. Hapi fills a number of omissions along these directions. Additionally, Hapi also extends Legalease with a number of practical functionalities, namely, the ability to compose policies in multiple files, and a more concise syntax to specify conjunctions of access rights. Finally, Hapi provides users with syntactic extensions that let them define the so-called concept lattices. Concept lattices define the data types that are manipulated in a policy specification, namely, which actors, resources and actions can be referred to in that specification.
OPA/Rego
OPA/Rego is a tool focused on creating complex policy queries. Given a JSON with the policy rules, an OPA/Rego query can inform whether and which data could be accessed by some input. Then, here there is an auditing tool to check the policy properties. Using the OPA/Rego website’s example we can describe the boss order with the following Hapi policy:
main =
ALLOW
EXCEPT
DENY {
Servers
Ports
Network = public
Protocols = http
}
DENY {
Servers
Ports
Network
Protocols = telnet
}
With OPA/Rego, we must code the query to consult which servers are allowing the http protocol for some public network, then the JSON policy rules should be changed. The same fact will occur to check which servers have allowed telnet for any port and any network. The boss order can be coded by:
boss_order[servers] {
some i, j
server := input.servers[ _ ]
input.servers[ _ ].protocols[ _ ] = "http"
server.ports[ _ ] == input.ports[i].id
input.ports[i].network == input.networks[j].id
input.networks[j].public
}
boss_order[servers] {
server := input.servers[ _ ]
input.servers[ _ ].protocols[ _ ] = "telnet"
}
When the boss_order is called, then all listed servers must be changed in the JSON. But, when we are using HAPI, we just need to specify the data hierarchy describing the Servers, Networks, Ports and the Protocols concept lattices. After that, the policy can be written as well as shown above.
Actually, Hapi and OPA/Rego can be integrated. Our first approach is print an YAML file (that can be translated to a JSON) and using the OPA/Rego we can check any property of our rule description.
Use Cases
Specifying policies in Hapi almost feels like writing them in plain English. Below we provide a few examples of such specifications. Notice how indentation defines a hierarchy between policies, and how lower-level policies might either increase or constraint rights granted to higher-level policies. We start with a simple example: “Everyone can read emails. Bob can read and delete all data but only updates credit card numbers. Alice can perform all actions in emails“:
main =
DENY
EXCEPT
ALLOW {
Actor = Bob
Resources
Actions = Reads, Deletes
}
ALLOW {
Actor = Bob
Resources = CCN
Actions = Updates
}
ALLOW {
Actor
Resources = EMAIL
Actions = Reads
}
ALLOW {
Actor = Alice
Resources = EMAIL
Actions
}
Below we see another specification: “Bob, Alex and Jeff can read all resources, but Alex can’t read emails.” Notice how Hapi supports factoring out particular rules into a default behavior. Such rules can be compiled in different files, and merged into a single specification through Hapi’s module system:
alexCantReadEmails =
DENY {
Actors = Alex
Resources = EMAIL
Actions = Reads
}
main =
DENY
EXCEPT
ALLOW {
Actor = Bob, Alex, Jeff
Resources
Actions = Reads
Resources
Project Hapi is sponsored by Cyral and developed at UFMG‘s Compilers Lab, which exists as part of the Department of Computer Science. This project is fully open source, and the interested users can find all our code base in publicly available repositories.
- Comprehensive documentation is available in the language’s web-book, at cuda.dcc.ufmg.br/hapidoc.
- Hapi’s implementation is available at https://github.com/lac-dcc/hapi