title: Attribute Based Access Control (ABAC) in a microservices architecture for lists of resources
body: <p>I am investigating options to build a system to provide "Entity Access Control" across a microservices based architecture to restrict access to certain data based on the requesting user. A full Role Based Access Control (RBAC) system has already been implemented to restrict certain actions (based on API endpoints), however nothing has been implemented to restrict those actions against one data entity over another. Hence a desire for an Attribute Based Access Control (ABAC) system.</p>
  
  <p>Given the requirements of the system to be fit-for-purpose and my own priorities to follow best practices for implementations of security logic to remain in a single location I devised to creation of an externalised "Entity Access Control" API.</p>
  
  <p>The end result of my design was something similar to the following image I have seen floating around (I think from axiomatics.com)</p>
  
  <h2><a href="https://i.stack.imgur.com/j3ujX.png" rel="noreferrer"><img src="https://i.stack.imgur.com/j3ujX.png" alt="EAC API implementation concept"></a></h2>
  
  <p>The problem is that the whole thing falls over the moment you start talking about an API that responds with a list of results.</p>
  
  <p>Eg. A /api/customers endpoint on a Customers API that takes in parameters such as a query filter, sort, order, and limit/offset values to facilitate pagination, and returns a list of customers to a front end. How do you then also provide ABAC on each of these entities in a microservices landscape?</p>
  
  <p>Terrible solutions to the above problem tested so far:</p>
  
  <ul>
  <li>Get the first page of results, send all of those to the EAC API, get the responses, drop the ones that are rejected from the response, get more customers from the DB, check those... and repeat until either you get a page of results or run out of customers in the DB. Tested that for 14,000 records (which is absolutely within reason in my situation) would take 30 seconds to get an API response for someone who had zero permission to view any customers.</li>
  <li>On every request to the all customers endpoint, a request would be sent to the EAC API for every customer available to the original requesting user. Tested that for 14,000 records the response payload would be over half a megabyte for someone who had permission to view all customers. I could split it into multiple requests, but then you are just balancing payload size with request spam and the performance penalty doesn't go anywhere.</li>
  <li>Give up on the ability to view multiple records in a list. This totally breaks the APIs use for customer needs.</li>
  <li>Store all the data and logic required to perform the ABAC controls in each API. This is fraught with danger and basically guaranteed to fail in a way that is beyond my risk appetite considering the domain I am working within.</li>
  </ul>
  
  <p>Note: I tested with 14,000 records just because its a benchmark of our current state of data. It is entirely feasible that a single API could serve 100,000 or 1m records, so anything that involves iterating over the whole data set or transferring the whole data set over the wire is entirely unsustainable.</p>
  
  <p>So, here lies the question... How do you implement an externalised ABAC system in a microservices architecture (as per the diagram) whilst also being able to service requests that respond with multiple entities with a query filter, sort, order, and limit/offset values to facilitate pagination.</p>