When my career was nascent many moons ago, I worked at a financial company as an intern, and since there was a good deal of work and too few occupied seats, every employee was expected to wear a few hats at any given time. In those first days of my service, the majority of my day was filled with the tedious work of testing our services as QA. Occasionally, I was allowed to participate in development, but most of my extracurricular activities (i.e., rewards for good behavior) constituted being an administrator for our development and QA machines.
Unsurprising to any seasoned developer, the knowledge attained from being a system administrator enhanced my general skillset by a magnitude or two, and those lessons were crucial to all code that I subsequently wrote in the years to come. In addition to being exposed to the awesome power of scripting and the idiosyncratic differences between different filesystems, one also learns the subtle complexity of something that seems initially simple: permissions. Whether it pertains to setting file permissions via ‘chmod 777’ or to allocating roles in a Windows domain, one can observe that authorization resembles an art form, where you learn to balance the needs of your users with the requirements of security policies.
However, even as a young apprentice, it wasn’t long before I wondered about the possibility of an even better solution to the various problematic scenarios encountered as an admin. After all, there are a number of situations where a simple permissions mask just doesn’t suffice. Could it be possible to build a more detailed solution, like setting permissions on sections of a file instead of the whole file? Before allowing an action, could this subsystem weigh levels of trust belonging to different users and their relativity to one another? What if such a subsystem could assign security policies to a user that took context into account, like a policy that allowed users to create a file but never update or delete them? Decades ago, it was just a passing thought of a cadet in training, but it would come back to the forefront of my conscience when we had to design an architecture that required something similar to just that.
When it became necessary to build the next iteration of our production system, we dove into the new specifications, and based on the various requirements and requests, we became aware of the dire need to reimagine just what was meant by the term permissions. In our situation, we needed to create a distributed architecture and the inherent software that would allow users familiar permission settings, for activities in our database (i.e., CRUD)…but that was only the surface level. Found pervasively throughout large-scale corporate environments, a fair amount of scrutiny is necessary in order to ensure that each submitted data point belongs within the system. In some cases, you can build customized solutions for a specific platform, much like Grzegorz Gogolowicz’s proposal regarding Sharepoint. Other times, though, you need a more abstract, granular approach where each section of a data record should have some level of clearance, just as when protection keys are used to secure memory pages in an operating system. In our situation especially, some sources (data vendors, stakeholders, etc.) were more considered more reliable than others when it came to accepting certain pieces of data, and the current context of the data only complicated matters further.
For example, Data Vendor Inc. could be relied upon to provide an initial price, but if stakeholder Bob Smith sends a subsequent price, we should overwrite the vendor’s submission with their data since we trust Bob Smith more. In this scenario, the architecture would then need to examine the context of the situation, taking into account various factors: the previous editor of a column, the current user, the current state of the data, the metadata about that column, etc. In the end, this permissions mechanism became a more intricate filter, one that required a number of provisions in order to make a proper evaluation.
We could have created a sophisticated set of libraries with accompanying configuration files, but it seemed too rigid and troublesome, especially when we thought about the disaster awaiting an eventual expansion of the system (additional columns, additional stakeholders, etc.). In short, we needed an approach to our resolution that could easily and deftly dodge any of these hurdles thrown at it, so that we could save ourselves the headaches of a potential security and auditing nightmare. And after some deliberation, we found our direction, and hopefully for readers, it will find an application outside of just our environment. We’ll find out with the publishing of Part 2.