Reimagining authorization
Using policies with OPA
If you have worked on ASP.NET MVC (core) for some time you will be familiar with the way roles are authorized in the code. There is some amount of flexibility in terms of the framework you use to enforce policy, customize thee return value, define attributes which supply further context to such authorization activities etc. But this is how it will have appeared –
[Authorize(“Administrator”)] |
public void AssignUserToRole(string userId, string roleId) |
[Authorize(Policy=”DepartmentRelatioinship”)] |
public void AssignUserToRole(string userId, string roleId) |
There is nothing odd or weird that stands out in this code yet. The first snippet is application of Authorization policy to determine if the authenticated user has the role of Administrator, and if so the method / controller AssignUserToRole can be called by that authenticate user. The second snippet has the same effect but checks for a Policy instead of a specific role. The policy could be a custom code that is typically defined in the Startup.cs or could have been defined externally in a class.
This nuances in this style could vary from language to language or from framework to framework but the bottom line remains the same which can be articulated as –
Authenticated user is allowed to access a resource only if few conditions are satisfied.
Let us post you this question – Are such conditions (e.g., the role being of administrator or bunch of conditions defined in a policy) constant in the business? Have you seen them change?
We have seen the change over a period of time always. Let us take the example of role-based authorization where the role of administrator is always expected. We have seen business after using the software for some time might undergo strategic change and demand separation of roles where one single administrator is not sufficient anymore. They want a role separation where they need a functional administrator and operational administrator. The act of assigning user to a role being claimed by operational administrator should now not allow the functional administrator to call.
Such changes are unavoidable and probably predictable or may be not predictable. But one thing that is certain is over time such demands do come across. Now as designer and developer we might instantly flag such requests as big change which does require code to be modified and re-deployed.
The question to all of us is – Can this be managed better?
Enter the world of Policy Administration. Defining policy for authorization is a concept that exists in almost all the mature frameworks in use today. But most of them require the policy to be defined in a format that is specific to their framework to ease evaluation. However, a pattern where such decisions are externalized also have been existing for long time. But haven’t been used for the case of authorization innovately for a long time now. Reasons could have been diverse in fact major rules engine like drools could have been put to use but we haven’t witnessed such usage yet.
Open Policy Agent (OPA pronounced as opah) by design claims to address this need. We will not wrestle with the English differences between rule engine and policy engine here. But we will definitely emphasis the decision to whether a person should be allowed to perform an operation or not is a rule. However, in the real-world authorization such implementations quickly take a ghastly shape and requires complex validations before one determines if a person is allowed to perform such operation or not.
The example we defined above can used as launch board to demonstrate the growing complexity. E.g., we started with simple rule that a user needs to be administrator to map user to a role. Next, after some time let us say we had to refine the rule to say a policy of sort where user can only assign role for individuals belonging to her department. In future owing to the growth of business panning continents there could be rules that factor geographical information.
This immediately leads to the scenario where one needs to define access policy with relevant considerations. Such policies evolve at different pace than the core software which offers much different functionality. Frameworks and libraries like OPA offer to address this spot with factoring the evolution and with ports for governance of policy definitions.
Developers use a rule definition language called Rego to define such policies. The policy for the example we took above will look like this –
default allow = false |
allow = true { |
input.method = “POST” |
input.path = [“AssignUserToRole“] |
input.subject.roles[_] = “Administrator” |
} |
The policy can be experienced by the developer using the CLI that comes packaged with OPA installation using the following command
opa eval -i input.json -d rolePolicy.rego
|
Before your run this you will be needed to define the input.jsonwhich contains the details required for the OPA to operate
{ |
“roles”: [“Administrator”] |
} |
Save this as file input.json and the rego definition above as rolePolicy.rego
The same can be externalized in a server and invoked using a HTTP client with these parameters
opa run –server ./rolePolicy.rego
|
The use the following simple curl request to check
curl localhost:8181 -i -d @input.json -H ‘Content-Type: application/json’
|
Outcome of all these operations can be either Boolean (being used as rule/decision engine) and JSON (being used as evaluation engine with complex context). If your imagination has taken flight and yes in an ecommerce application discount applicability and such scenarios could also be realized using OPA.
Recent post
Archives
- November 2024
- October 2024
- September 2024
- August 2024
- July 2024
- June 2024
- October 2023
- June 2023
- March 2023
- February 2023
- January 2023
- December 2022
- November 2022
- October 2022
- September 2022
- August 2022
- July 2022
- June 2022
- May 2022
- April 2022
- March 2022
- February 2022
- January 2022
- December 2021
- November 2021
- October 2021
- September 2021
- August 2021
- July 2021
- June 2021
- May 2021
- April 2021
- January 2021
- December 2020
- October 2020
- August 2020
- June 2020
- May 2020
- April 2020
- March 2020
- February 2020
- January 2020
- December 2019
- November 2019
- October 2019
- September 2019
- August 2019
- July 2019
- June 2019
- May 2019
- April 2019
- March 2019
- February 2019
- January 2019