Three Challenges in Policy Implementation
Implementing policies in a Policy-as-Code framework presents a new type of complexity, one that many organizations are not well-prepared to address. Here are three of the most common challenges in adapting an organization to a Policy-as-Code orientation:
Pulling the policy enforcement logic out of internal software & services
Building a policy devops pipeline
Writing good, readable policy code
Refactoring Internal Software & Services
Updating your “legacy” software to use Policy-as-Code generally requires a paradigm shift in how the organization thinks about policy. Many software architects and developers will be (naturally) skeptical of anything that challenges their fundamental assumptions about building enterprise software. Here are some of the types of pushback you can expect:
Migrating the policy decisions to an external agent affects performance
It will be more difficult to know if our software is correct
The policy logic is too deeply embedded in the software to be easily removed
Performance
It is almost impossible that changing to an external agent does not result in at least a modest performance penalty. However, with thoughtful network architecture and the smart deployment of agents, this penalty can indeed be a modest one, and often immaterial to the overall performance of the system. See also: Architectural Concerns with Policy
Software Correctness
This argument is one that comes from not fully embracing the concept that the functionality of the software is orthogonal to the policies. If you accept that “deciding if a certain person is able to do a certain action” is not part of the core purpose of the software, you actually make it easier to validate that the software is correct.
Deeply Embedded Policy Logic
Having been on both sides of this argument, we are sympathetic to it. On the other hand, consider the trap that you might find yourself in:
We can’t extract the policy logic, because it’s too deeply embedded in our software
We can’t change the policy logic, because it’s too deeply embedded in our software
In other words - if it is too deeply embedded to extract, it is also most likely too deeply embedded to change, and that makes your organization brittle. If your policy changes are driven by regulatory compliance, this brittleness could have a significant long-term cost.
Building the Policy Pipeline
Once the decision has been made to migrate to a separate software repository for policy logic, this has two ramifications:
The team that is now in charge of the policy logic needs to have some way to review, test and deploy changes
The team that no longer implements policy logic still needs to be able to develop and implement code, and work around the separated policy engine.
Policy Logic Development Lifecycle
This change is relatively straightforward for groups that are already comfortable with the software development lifecycle. Repositories such as Git or Subversion already provide mechanisms for reviewing. Some of the policy systems have built-in testing, and third-party test frameworks are also available. Lastly, deployment is straightforward with existing tools, such as Github Actions, or Jenkins, etc.
The implicit assumption here is that the new team that is responsible for this work is familiar with building software pipelines. If not, this is an area where some mentoring/oversight may be necessary.
Workarounds
The team that used to be in charge of embedded policy now has the luxury to remove that logic, and all of the testing and analysis associated with it. However, calling out to an external policy agent is something that needs to be properly modelled/simulated during testing.
For unit testing, this is typically a straightforward use of mock implementations. But for integration testing and staging, the organization will need to set up agents which can be used in a way that is consistent with the production use. This is a somewhat complicated process, that may require some careful assessment and mentoring to get right.
Good Policy Code
The last big challenge is writing good policy. The key to good policy is making it readable, because if it’s hard to follow, it’s going to be hard to maintain, hard to audit and hard to co-develop with non-technical people. Too often, readability is sacrificed for other goals:
Sacrificing readability for cleverness
Sacrificing readability for elegance
Sacrificing readability for speed
Cleverness
The developers behind the common policy languages (such as Rego) are often extremely skilled at building language interpreters. This results in a variety of very ‘cool’ capabilities that are added to simplify code that would otherwise be cumbersome and verbose. In the software space, this is called ‘syntactic sugar’.
There are times when using syntactic sugar can make your code more readable. However, there are a lot of times where it will only make it more readable to other people who are already experts at your policy language. “Too clever by half” policy logic ends up being harder to maintain and update, confuses new developers and baffles the non-technical business user.
We’re not saying you should never use clever features. Just use them thoughtfully, when they aid in clarity for ‘normal’ people.
Elegance
Related to cleverness, but not always the same, is elegance. In software development, elegance is often something for which one should strive. This is because the audience for most software is other software developers, and elegant solutions are easy for other software developers to understand.
But this needs to be balanced by the fact that most of the policy you will need to implement is created by non-technical people. For them, software elegance is often incomprehensible inside jargon that makes no sense. (For example, if you are not a lawyer, and listen to lawyers talk about the tactics and motions involved in trying to win a case).
As with cleverness, there are times when elegant policy implementations are easier for a non-technical consumer to follow. In our opinion, this is a fairly rare occurrence - most of the time, elegance makes things more abstract and more conceptual, which just makes it that much harder for the business people to understand.
Speed
The last excuse for hard-to-read policy code is performance.
And to be sure, some applications and services are critically dependent on fast responses to policy decision queries. And where that is the ‘hard’ requirement on the implementation, speed should be the primary concern.
In our experience, developers will often optimize for speed more ruthlessly than they should. If you can implement something that is only 0.1% less performance, but 5x more readable, the legibility of the code is worth that trivial reduction in performance in almost all situations.
And if that’s not possible, if the requirement for performance is absolute, that should never stop you from:
Using clear names
Explaining the speed optimizations - why they work and what they are doing
Providing comments that explain the entire policy decision tree in easy-to-follow language
Conclusion
Thank you for taking the time to read this. Do you have thoughts or comments you want to share? Do you think we missed some key challenges, or that our advice misses the mark? Please contact us, we would love to hear from you: info@paclabs.io