Back at KubeCon North America 2017, many speakers declared that 2018 would be “The Year of the Service Mesh”. Just a year later, in the 2019 CNCF Survey1, it was reported that 18% of surveyed organizations were using a service mesh in production, and by 20202 (the most recent survey published at the time of this writing) that number rose to 27%. Moreover, the 2020 survey showed an additional 19% of organizations planning to implement a mesh in production within 12 months and 23% more evaluating. Clearly, service meshes are hitting the mainstream and becoming a necessary element of a cloud-native approach.
One of the major reasons for this shift is the ability to take code out of (or never put in) a business service and instead leverage features of the platform. This has a couple of benefits to organizations. First, this allows organizations to reduce the amount of internal libraries to “glue” systems together and instead focus more on business logic. At a previous organization I worked for, we used three different languages and no less than a half dozen frameworks within those languages, causing us to have dozens of internal “glue” frameworks each with a unique set of bugs. The second benefit with using service mesh, is that it helps separate business logic from non-business logic. Logic to validate certificates, retry service calls, service discovery and service level tracing are examples of logic that add no business value to your service. Being able to separate these from your business logic enables applications to be simpler making them easier to understand and test.
While we see this massive shift to implement service mesh, the issue of authorization still remains. We can further simplify our applications by separating the authorization logic using Open Policy Agent (OPA). OPA is a completely agnostic technology that works across your tech stack, from modern microservices (and not so modern monoliths) to Kubernetes admission control to vetting Terraform plans. In this case OPA allows you to codify your access policies and externalize them from your business services. Add in Styra Declarative Authorization Service (DAS) and you can do this at scale across all of your business services. This setup generally looks like Figure A. When placed within a Kubernetes context and when paired with an Envoy proxy it may look like Figure B.
Styra DAS and service mesh
Styra DAS has long had the ability to tie into Envoy using the External Authorization filter. This type of integration means that the business service doesn’t even need to know that the authorization is happening. This frees up the business service to concentrate on the business logic, thus simplifying the business service and making it easier to test. This setup, specifically running both Envoy and OPA as sidecars, also keeps everything local, reducing any latency and availability concerns. It also scales very naturally with your service, as whenever you need to add pods to handle incoming requests, instances of Envoy and OPA are added along with.
Service meshes will have their own proxy and more often than not, they are based on Envoy, thus superseding the need for the Envoy sidecar (Figure C). In the past Styra DAS could accommodate these types of setup generally with custom configurations using the Envoy System. But with a recent update to Styra DAS, first class support was added for Kong Mesh, Kuma and Istio. With this support there are now specific system types for each mesh, along with configuration scripts that will integrate OPA and Styra DAS into the mesh.
Kong Mesh adds native support for OPA
Earlier this year, the great people at Kong Mesh went even further than most service meshes by adding native support for OPA as a part of it’s proxy. This makes request level authorization a first class feature in Kong Mesh and lets us drop the OPA sidecar in favor of directly integrating Styra DAS with the Kong Proxy. This is shown in Figure D. Also, for those Kong Mesh users, Kong also added native support of OPA into their API Gateway, Kong Gateway.
In a recent article entitled “Getting Started with Kong Mesh and Open Policy Agent,” Cody De Arkland explains how the Kong and OPA integration could work by using CRDs to configure the policy. In the remainder of this article we will explore how we can simplify and improve upon Cody’s example by utilizing Styra DAS.
I am running Kong Mesh 1.4.0 on a local minikube cluster V1.21.2. Into the kuma-demo namespace I’ve installed the kuma demo application. Installing the app is as simple as “kubectl apply -f https://bit.ly/demokuma”. This application consists of four components: Vue frontend UI, Node backend API, PostgreSQL, and Redis. We will write rules targeted at the backend API and view the results in the running UI. The UI was not written to gracefully handle 403 errors, but it will show us a nice 403 message.
Here is the view of the setup in the Kong Console.
And a view of the demo app viewing reviews.
Configure Kong Mesh to utilize Styra DAS
At this point we are ready to configure Kong Mesh to utilize Styra DAS to manage our policies. But this is also a good time to pause and discuss some benefits of using Styra DAS. First and foremost, Styra DAS gives you a proper authoring platform for your policy code. The same way you wouldn’t want to author Python code in YAML, you don’t likely want to edit your Rego code there either. But beyond syntax checking and code completion, Styra DAS also gives you the ability to share code across multiple deployments of OPA or importing libraries of rules. Styra DAS also gives you the ability to log all of the decisions that are made to a central location. This gives the obvious ability to audit your decisions, but it also allows you to use those previous decisions for impact analysis of policy changes.
We’ll see more benefits as we move along, but for now let’s start getting this setup. In Styra DAS we will add a new system of type Kong Mesh, give it a name, and click “Add System”.
This will create the system and give us a set of install scripts.
The first script applies the CRDs to modify the default mesh in order to use Styra DAS to manage the embedded OPA, then restarts the mesh for the configuration to take effect. The second script labels the namespace for Kong Mesh proxy injection, but since we are using the demo application the namespace is already labeled and we can skip applying this script. The third will install the Styra Local Plane (SLP), this allows for a local cache of configuration/data and decisions in the event of loss of network conductivity with Styra DAS. This will also cut down on internet traffic between your cluster and Styra DAS.
One additional setup step, since we had a running mesh with services in before we configured the mesh to use OPA for authorization, we will need to restart the services in order for them to pick up these changes.
That’s all that we have to do for the install/setup, we can now easily add policy for our services from within Styra DAS. We can now see from the Kong Console that the OPA is configured and also see the additional SLP service running.
We could edit the system to enforce our authorization policies, but for now we will just default to allowing all the traffic into the services. This will allow us to send some traffic through the system that we can use to author our policy.
We can choose to replay a decision, this will load it up into our editor and let us preview this request in our draft changes.
Not only that, but Styra DAS will also use that input document to give us code completion ensuring that we are not making simple structure mistakes.
The demo application seems to have two main endpoints that it calls. The first one is for the list of items which is structured something like “/items?q=”. And the second one to get the reviews “/items/34/reviews/”. Let’s add the following policies to allow traffic to just these two URIs:
The underscores (_) in the arrays indicate that there should be a value present in that position but we don’t care what it is. The trailing slash in the reviews URI causes the fourth element in the array.
Before we apply this policy it’s good practice to try to understand the impact the change may have. Styra DAS lets us do that by rerunning prior decisions through our draft policy. We do this by clicking the validate button.
This shows us a couple of things, first I didn’t write any unit tests for the new policies, shame on me. Second, the decision replay feature was able to replay 110 previous decisions and two have changed. Apparently there is another endpoint that needs policy. Given those two issues, let’s add the following:
Normally I would code at least one unittest for each “apply”, but for brevity I’m just including one. Also, for brevity I’m including the unit test in the rules file, this would normally be in another file.
This looks more like what we were expecting. Now we can apply the policy by hitting the “Publish” button on the top of the screen. This will bundle up the new policy and let the OPA pull it into it’s memory. By using Styra DAS all of your policy changes can be this easy, no need to mess with YAML and a custom CRD to get your policies updated. In a production deployment I would suggest to store your policies in a Git repository, in that case all that changes is that instead of a “Publish” button, there would be a “Push” button that would push your changes into a review branch. When the review branch gets merged into the main branch then Styra DAS will get it to the OPAs.
We can now test the demo app and see that everything is still working as expected. So, let’s update the policy so we can see some denials. Let’s change the first “apply” policy so that we can just see the reviews for one item.
I intentionally used the id that was setup in the unittest so as to not break the test. But now we see a large percentage of changed decisions. This is exactly the behavior we are looking for so let’s apply the change and see what the demo app looks like.
We see 403s for all of the reviews except for when we view item 12.
We can more clearly see that from the decision logs within Styra DAS.
But let’s say we have a dataset somewhere that has a set of restricted reviews. We can update the rule to utilize this data during rule evaluation. First we must get the data to Styra DAS so it can include it in the rule bundle for OPA. There are several ways to automate this but they are beyond the scope of this blog, for now we will just add it through the Styra DAS UI.
We can now update the rule to use this dataset.
This rule saves the item_id in a variable called item_id and then uses it to look up that value by key and check the restricted property. After we apply this rule then we can read the reviews of all but items 0 and 4.
So let’s take one more step in our journey, what if we needed a rule that was more global than this one system. Let’s say we wanted to allow all “superadmin” to perform any GET request across all of our systems (let’s also pretend for a minute that we could get this past auditors). We could do this with a library, but that would require each system policy author to remember to include that rule. The better way in Styra DAS to do this would be to create a stack and add the rule there. Stacks work with the concept of labels and label selectors. Each system would have one or more labels and stacks would have a selector that would select these labels. Then, any rule defined in the stack would be automatically applied to the system(s).
All systems have a default to having a system-type label, in the case of Kong Mesh it is kong-mesh. After adding the stack with the correct selector we see that it selects all the Kong Mesh systems in our environment.
Now let’s add the following policy to the stack and apply it.
We can see that we get the bearer token from the authorization header and validate it then return the claims (and yes, you should secure your secret instead of hardcoding it). We use the roles claim to see if the user has the rule of “superadmin” and if so we all GET requests. Since the demo app has no login screen, I used a browser extension to inject a bearer token that I generated. The result is I can now view all item reviews including the reviews for items 0 and 4.
Kong Mesh and Styra DAS – decouple access policy from business code
To summarize, Kong Mesh makes it very easy to plug in Styra DAS to manage your request level authorization. By doing so, you have far more capabilities when creating access policies including the ability to use external data and apply policies across systems. At the same time, it will reduce your overall effort in deploying policy and understanding the impact of your changes before you make them.
Using Kong Mesh and Styra DAS together will give you a quick, low maintenance way to decouple your access policy from your business code. Give it a try today with Styra DAS Free!