Skip to main content
View all authors

Open Policy Agent 2021 Survey Summary

OPA 2021 community survey results banner

…happy OPA 2021 survey from Cal [credit: @eileen_kemp]

Last month we surveyed the OPA community to learn more about user adoption and help us plan and improve the project. We received over 300 responses from users across financial services, healthcare, public sector, automotive, cloud technology providers and more. This post highlights some of the survey results.

Use Cases and Adoption

OPA adoption driven by authorization use cases across the stack

Like last year, we used the survey to gauge use case adoption among respondents. We're interested in understanding where and why companies are deploying OPA because it helps us steer the project's long-term roadmap in the right direction. This year we asked respondents about the high-level goals they're trying to achieve by using OPA. We found that implementation of internal compliance and governance rules was the most common goal, however, nearly 60% of respondents indicated two or more goals being highly relevant.

Goal% of Respondents
Internal compliance/governance64%
Operational excellence49%
Implementing end-user IAM44%
External compliance (e.g., PCI)28%

In terms of use cases (e.g., Kubernetes admission control, Microservice authorization, etc.), the results were similar to the previous year with 50% of respondents indicating they use OPA for two or more use cases:

# of Use Cases% of Respondents
148%
234%
313%
4+3%

Kubernetes admission control continues to be the most common use case for OPA with 54% of respondents indicating they run OPA or OPA Gatekeeper to enforce various policies on their clusters:

Use Case% of Respondents
Kubernetes admission control54%
Application authorization39%
Microservice authorization39%
Terraform validation25%
Other5%

From experiments to production in 6 months (or less)

The survey showed the distribution of respondents OPA usage maturity was roughly equal:

Stage% of Respondents
Experimentation33%
Pre-production & QA32%
Production35%

What was more interesting was that about half of respondents indicated they had only been using OPA since January 2021. Of those users, nearly 40% had already reached production. Furthermore, the survey results show that most respondents reached production within 6 months. Beyond that, the percentage of users that are still in experimental stages drops to single digits:

ExperimentationPre-prod/QAProduction
< 3 months54%28%14%
3-6 months22%54%25%
6-12 months4%38%58%
Over 12 months7%15%76%

These results are encouraging and also give us high-level metrics to improve on — ideally the time to production with OPA will continue to decrease as we improve the user experience and harden the project.

The survey results also highlighted a range of deployment sizes for production users. The following chart breaks down the deployment size responses by use case:

Use Case<1010-5050-200>200
Kubernetes admission control42%31%13%12%
Terraform validation43%25%18%12%
Microservice authorization37%37%12%11%
Application authorization44%32%10%11%

Policy library adoption is growing

The survey asked users about various features in OPA and one of the most encouraging bits of information was that policy library adoption is growing within platform authorization use cases, like Kubernetes admission control and Terraform plan validation. Specifically, we found that nearly 60% of Kubernetes admission control users rely on the official gatekeeper-library policies that implement various best practices as well as PSP. We also found that nearly 30% of users that run OPA to validate Terraform plans rely on various open source policy libraries.

OPA Feedback

In addition to gauging adoption we also used the survey to solicit feedback about the project.

Debugging needs some love

After poring over the feedback comments, we found that the most common area for improvement is debugging. As with all surveys, some comments were non-specific, however multiple respondents requested better tracing modes and explanation presentation formats. Improved debug output support was another common request, and respondents also mentioned a desire for an interactive debugger similar to what you find in typical programming languages.

SDKs for various languages

Aside from debugging, the next most common request was better SDK support for OPA in various languages. Several respondents indicated interest in Wasm-based SDKs for OPA, and others requested regular SDKs for Java, NodeJS and other languages. One of the reasons we haven't developed SDKs for OPA yet is because the OPA API is extremely simple (e.g., you can query OPA for decisions with a single HTTP POST request). However, with the Wasm compiler in OPA improving with every release, and the Wasm ecosystem growing rapidly, it feels like it's time to invest into language-specific integration libraries.

Wrap Up

Thanks to everyone who completed the survey! The OPA t-shirts for completing the survey will be shipped soon. If you have not filled out the survey but would like to do so, you can still complete the OPA survey. As always, if you have questions or feedback, we're available on Slack, GitHub, etc.

Enhanced Type Checking for OPA with JSON Schema Annotations

Enhanced type checking for OPA with JSON schema

IBM Research & Styra

What's happened?

In a previous Medium blog, a feature released in OPA v0.27.0 was introduced that lets OPA's static type checker take JSON schemas for input documents into account, improving how errors from misused data are caught during policy authoring.

The article explains that opa eval can take a schema for the input document via the --schema(-s) flag, applied globally across the module, allowing OPA's checker to catch issues like undefined objects.

What's new?

This section covers extending type checking to support multiple JSON schema files for both input and data documents.

Example Rego code (based on a Kubernetes admission review input) is shown with a typo bug:

package kubernetes.admission

deny[msg] {
input.request.kind.kinds == "Pod" # This line has a typo, should be input.request.kind.kind
image := input.request.object.spec.containers[_].image
not startswith(image, "hooli.com/")
msg := sprintf("image '%v' comes from untrusted registry", [image])
}
input.request.kind.kinds

which should be:

input.request.kind.kind

Running:

% opa eval --format pretty -i admission-input.json -d policy.rego -s schemas/admission-input.json

returns:

1 error occurred: policy.rego:4: rego_type_error: undefined ref: input.request.kind.kinds
input.request.kind.kinds
^
have: "kinds"
want (one of): ["kind" "version"]

The article notes that a similar typo in input.request.object.spec.containers[_].image would go undetected, since the admission review schema leaves input.request.object generically typed.

To solve this, opa eval now supports a directory of schema files via the same --schema (-s) flag, while still supporting single schema files. New Rego Metadata blocks allow specifying schema annotations and scope, improving bug detection for undefined fields.

An override feature is also introduced, described as letting users merge existing schemas and subschemas "for more precise type checking."

Additionally, schema loading is enabled for opa eval — bundle, supporting type checking of data documents across a bundle — useful for "batch type analysis of Rego policies as part of any CI/CD pipelines."

These features are available in OPA v0.28.0.

What's the big deal you say?

Example policies and schemas are available in the opa-schema-examples repository.

The Kubernetes Admission Review example is revisited to demonstrate annotations and schema overriding. The object field in an Admission Review can contain any Kubernetes resource, and its schema leaves that field generically typed.

Annotations associate a Rego expression with an input or data schema loaded via opa eval -s, within a given scope.

Annotations use METADATA comment blocks in YAML syntax, where "every line in the block must start at Column 1."

Example schema directory structure:

mySchemasDir/
├── input.json
└── kubernetes
└──────pod.json

Loading the schema directory can be done via:

% opa eval data.kubernetes.admission --format pretty -i opa-schema-examples/kubernetes/input.json -d opa-schema-examples/kubernetes/policy.rego -s opa-schema-examples/kubernetes/mySchemasDir
% opa eval data.kubernetes.admission -format pretty -i opa-schema-examples/kubernetes/input.json -b opa-schema-examples/bundle.tar.gz -s opa-schema-examples/kubernetes/mySchemasDir

In this example, input is associated with the Admission Review schema (input.json), and input.request.object is set to the Kubernetes Pod schema (pod.json), with the second annotation overriding the first. The order of annotations is stated to matter "for overriding to work correctly."

Notes on schema reference syntax:

  • Relative paths inside mySchemasDir are used, omitting the .json suffix
  • The global variable schema represents the top level of the directory
  • schema.input is valid; schema.pod-schema is invalid due to the hyphen — the correct syntax is schema["pod-schema"]

Combining annotations and overriding allows catching type errors in input.request.object.spec.containers[_].image:

package kubernetes.admission

# METADATA
# scope: rule
# schemas:
# - input: schema["input"]
# - input.request.object: schema.kubernetes["pod"]
deny[msg] {
input.request.kind.kinds == "Pod" # This line has a typo, should be input.request.kind.kind
image := input.request.object.spec.containers[_].images # This line has a typo, should be input.request.object.spec.containers[_].image
not startswith(image, "hooli.com/")
msg := sprintf("image '%v' comes from untrusted registry", [image])
}
2 errors occurred:
policy.rego:9: rego_type_error: undefined ref: input.request.kind.kinds
input.request.kind.kinds
^ have: "kinds"
want (one of): ["kind" "version"]
policy.rego:10: rego_type_error: undefined ref: input.request.object.spec.containers[_].images
input.request.object.spec.containers[_].images
^ have: "images"
want (one of): ["args" "command" "env" "envFrom" "image" "imagePullPolicy" "lifecycle" "livenessProbe" "name" "ports" "readinessProbe" "resources" "securityContext" "stdin" "stdinOnce" "terminationMessagePath" "terminationMessagePolicy" "tty" "volumeDevices" "volumeMounts" "workingDir"]

A second example checks whether an operation is allowed for a user, given an ACL data document. In the first allow rule, input uses input.json and data.acl uses acl-schema.json; an invalid expression like data.acl.typo would trigger a type error.

package policy

import data.acl

default allow = false

# METADATA
# scope: rule
# schemas:
# - input: schema["input"]
# - data.acl: schema["acl-schema"]
allow {
access = data.acl["alice"]
access[_] == input.operation
}

allow {
access = data.acl["bob"]
access[_] == input.operation
}

The article clarifies that this annotation "does not constrain other paths under data" — only the type of data.acl is statically known.

The second allow rule in the same example has no schema annotations, so it isn't type-checked against any loaded schema. Different rules in the same module can use different input schemas.

Annotations can also apply at different scopes via the scope field in Metadata, defaulting to the following statement if omitted. Supported scope values:

  • rule - applies to the individual rule statement
  • document - applies to all of the rules with the same name in the same package
  • package - applies to all of the rules in the package
  • subpackages - applies to all of the rules in the package and all subpackages (recursively)

More details: Annotation scopes documentation

What's Next?

The article closes by noting future plans to extend schema support to additional JSON Schema features such as additionalProperties, with more updates promised in upcoming OPA releases.

Further reading: OPA schemas documentation

Type checking your Rego policies with JSON schema in OPA

Diagram illustrating JSON schema type checking for Rego

IBM Research & Styra

The Open Policy Agent (OPA) is an open-source engine that unifies policy enforcement across the cloud native stack. It provides a query language called Rego that lets the user specify policy as code and an engine that evaluates the queries given input data.

Rego is a powerful declarative language that does not require the user to specify a query strategy. This is achieved by the OPA runtime, leaving users free to reason about policies at a higher level.

Rego has a gradual type system meaning that types can be partially known statically. For example, an object could have certain fields whose types are known and others that are unknown statically. OPA type checks what it knows statically and leaves the unknown parts to be type checked at runtime. However, the input handed to OPA could by design be any JSON value and hence gradual type-checking has no way of catching policy authoring mistakes, even when the policy author knows the intended schema.

In this article, we introduce a new feature that enhances OPA's ability to statically type check Rego code by taking into account schemas for input documents. This improves programmer productivity and helps Rego programmers catch errors earlier.

To achieve this, we enable opa eval to take the schema for the input document, specified in JSON Schema format. The input schema is passed with the flag --schema (-s). Armed with this information, OPA's enhanced type checker can detect bugs stemming from incorrect usage of the input.

This feature is now available in OPA v0.27.0. Let's check it out!

Rego type checking demo

Rego type checking demo

Consider the following Rego code, which assumes as input a Kubernetes admission review. For resources that are Pods, it checks that the image name starts with a specific prefix.

package kubernetes.admission


deny[msg] {
input.request.kind.kinds == "Pod"
image := input.request.object.spec.containers[_].image
not startswith(image, "hooli.com/")
msg := sprintf("image '%v' comes from untrusted registry", [image])
}

Notice that this code has a typo in it: input.request.kind.kinds is undefined and should have been input.request.kind.kind.

Consider the following input document:

{
"kind": "AdmissionReview",
"request": {
"kind": {
"kind": "Pod",
"version": "v1"
},
"object": {
"metadata": {
"name": "myapp"
},
"spec": {
"containers": [
{ "image": "nginx", "name": "nginx-frontend" },
{ "image": "mysql", "name": "mysql-backend" }
]
}
}
}
}
% opa eval -format pretty -i admission-review.json -d pod.rego
[]

The empty value returned is indistinguishable from a situation where the input did not violate the policy. This error is therefore causing the policy not to catch violating inputs appropriately.

If we fix the Rego code and change input.request.kind.kinds to input.request.kind.kind, then we obtain the expected result:

[
"image 'nginx' comes from untrusted registry"
"image 'mysql' comes from untrusted registry"
]

With this feature, it is possible to pass a schema to opa eval, written in JSON Schema.

Consider the Kubernetes admission review input schema. We can pass this schema to the evaluator as follows:

% opa eval -format pretty -i admission-review.json -d pod.rego -s admission-schema.json

With the erroneous Rego code, we now obtain the following type error:

1 error occurred: pod.rego:5: rego_type_error: undefined ref: input.request.kind.kinds
input.request.kind.kinds
^
have: "kinds"
want (one of): ["kind" "version"]

This indicates the error to the Rego developer right away, without having the need to observe the results of runs on actual data, thereby improving productivity.

With this new feature, Rego developers will be able to provide JSON Schemas for their input documents and get the most out of static type checking. If you don't have a JSON Schema handy, you can easily obtain one from a sample JSON file using online tools (see links below). In the future, we will add to this feature the support to allow users to specify a directory of schemas and assign schemas to data documents, as well. This will be done via annotations (global, rule-level, rule output) that will indicate what schema is associated with what Rego path expression.

Happy Rego type checking!

For more information and limitations, see documentation and examples.

Open Policy Agent graduates in the Cloud Native Computing Foundation

OPA graduates in the Cloud Native Computing Foundation banner

We're excited to announce that Open Policy Agent (OPA) is now a graduated project in the Cloud Native Computing Foundation (CNCF)! Graduation reflects the maturity of the project in terms of adoption, diversity of contributions, community and overall quality.

The growth over the last year has been phenomenal. The number of users on slack.openpolicyagent.org has grown by 3x (to over 3,600 users) and the number of Docker image downloads surpassed 39M (a 1000% increase!) We attribute much of this growth to the need for a robust policy-as-code solution in the cloud native ecosystem.

In the last year, the project shipped a number of powerful new features such as signed bundles, improved data fetching capabilities, parser and evaluator optimizations, as well as expanded support for WebAssembly-based execution environments. OPA Gatekeeper reached GA and added several features including multi-pod scalability, semantic logging, fine-grained metrics, dry-run support, and more. The popular Conftest tool (which helps you write tests against structured configuration files) became an official OPA subproject. Finally, support for IntelliJ users landed with the OPA IDEA plugin.

Graduation is a huge milestone for the project, and we wanted to take a moment to thank everyone involved in making OPA a successful, graduated project:

  • First, we'd like to thank the CNCF for their partnership and for all their support over the years. We would particularly like to thank Chris Aniszczyk, Amye Scavarda Perrin, Ihor Dvoretskyi for the excellent support they provided along the way.
  • We'd also like to thank all of the maintainers and core contributors to the OPA project: Ash Narkar, Boran Seref, Craig Tabita, Gareth Rushgrove, John Reese, Lennard Eijsackers, Max Smythe, Oren Shomron, Patrick East, Rita Zhang, Sertaç Özercan, and Stephan Renatus.
  • Lastly, we'd like to send a HUGE thank you to the entire OPA community. All new OPA features and partnerships were driven by your feedback and contributions. We also want to recognize certain people whose feedback, contribution, and support has been invaluable: Anders Eknert, Jasper Van der Jeugt, Joe Searcy, and Vincent Gramer.

Going forward we'll continue to focus on improving all aspects of OPA while solving real problems around policy and authorization in the cloud native ecosystem. We look forward to continuing to work with the amazing OPA community that started nearly five years ago. But, for today, let's all celebrate (socially distanced, of course) together on this great milestone!

Open Policy Agent Survey Summary (Spring 2020)

OPA Spring 2020 user survey summary banner

Last month we surveyed the OPA community to learn more about user adoption and help us plan and improve the OPA project. We received 204 responses (up 175% from the last survey in April 2019) from over 150 organizations, with 91% of respondents indicating they are in some stage of OPA adoption (i.e., experimentation, pre-production, production.) This post highlights what we learned from the survey results.

Use Cases and Adoption

Most organizations use OPA for multiple use cases

OPA's general-purpose, domain-agnostic architecture is paying off — 51% of respondent organizations use OPA for at least two use cases, with 29% using it for three or more use cases, such as Kubernetes Admission Control, Microservice API Authorization, Application Authorization, Cloud Security and so on. Similarly, only 15% of respondent organizations indicated they only use OPA for Kubernetes Admission Control.

This data supports our own experience from working with users — the typical adoption path involves identifying OPA as a good solution for a specific problem. From there, users realize they can apply it elsewhere, across the stack. Going forward we will continue to focus on features and improvements that help solve a broad set of use cases.

# of Use Cases% of Orgs Using OPA
139%
221%
317%
47%
5 or more6%

Application Authorization is becoming a dominant use case for OPA

43% of respondent organizations indicated they are in some stage of OPA adoption for Application Authorization. In the next survey, we will dedicate a larger section to this use case as it's clearly becoming another pillar for OPA (the other two being Kubernetes Admission Control and Microservice API Authorization). It's unsurprising that OPA is quickly being adopted for Application Authorization because the policies you need to enforce at the top of the stack are typically more sophisticated than those you enforce at the service/transport layer. Going forward, we will continue to add features that improve support for Application Authorization like data fetching, data filtering and UI preflight checks.

Use Case% of Orgs Using OPA for X
Kubernetes54%
Application Authorization43%
Microservices36%
Terraform25%
Data Stores7%
Other17%

Production usage continues to grow

56% of respondent organizations use OPA in production for Kubernetes Admission Control and 47% use OPA in production for Microservice API Authorization. This is not particularly new, but it reinforces the fact that OPA is being used to solve policy, authorization and security use cases across the stack, in production. Going forward we will continue to focus on work that improves stability and performance. We also plan to define a support policy that clarifies what to expect in terms of backporting (e.g., we will guarantee to backport fixes to N-M releases when asked; backports to older requests will be best-effort.)

Stage% of Orgs Using OPA
Production47%
Pre-production20%
Experimenting24%

Microservice API Authorization requires scalable policy authoring

35% of respondent organizations use OPA to enforce (or plan to enforce) policies across more than 100 distinct microservices. This makes sense given that microservice architectures often align with organization boundaries. This implies that policy authoring and distribution need to be scaled across many teams. Going forward we will continue to develop tooling that helps scale the authoring and distribution process (e.g., code generating Rego boilerplate from Open API specifications, the new "opa build" command for producing bundles, etc.).

# of Microservices% of Orgs Using OPA for Microservices
1-1013%
11-2524%
26-5021%
51-1006%
more than 10035%

Policy and runtime portability are important. The survey results showed that 57% of respondents use OPA for more than one Microservice API Authorization use case category (i.e., ingress, egress, or service-to-service) and 45% of respondents use more than one kind of OPA deployment architecture (e.g., library, sidecar, service). Moving forward, we will continue to invest in providing strong support for multiple deployment architectures.

Microservices Use Case% of Orgs Using OPA for Microservices
egress40%
ingress68%
service to service81%
OPA Deployment Type% of Orgs Using OPA for Microservices
Go Library37%
Service42%
Sidecar65%

OPA Feedback

In addition to soliciting use case feedback, we also asked users to provide feedback on OPA features, Rego, gaps in the OPA ecosystem and so on. The results were positive and reinforce our effort to improve content on openpolicyagent.org.

The Rego playground and testing support should be more prominent

65% of respondents said they use the Rego playground or features like policy testing that accelerate policy authoring. 10% were not aware that features like policy testing and coverage exist. Ideally, 100% of users would leverage the test framework, so moving forward, we'll focus on making testing more prominent and drive more users to try out playground and VS Code features, like interactive evaluation, that are invaluable during debugging.

Rego's learning curve

52% of respondents said they are comfortable with Rego or "okay" with their skill level. 27% said they need occasional help. 16% say they struggle. 68% say they were able to learn Rego in under a week. Given that Rego is based on programming language paradigms that are foreign to most developers, these numbers are understandable.

Going forward, we will continue to invest in answering questions on Stack Overflow and improving examples and documentation on the website. Interestingly, the number of people who struggle with Rego was twice as high among those that use OPA for Kubernetes and Terraform compared to Application Authorization. Perhaps this is (at least partially) due to the complex deeply-nested data structures that policies have to be expressed over within those environments.

Examples are the biggest gap in the docs

The survey asked users: "how can we improve the tutorials and documentation in OPA?" By far, the most common request is for more policy examples. Going forward we plan to focus on curating and organizing examples across a range of use cases, as well as building out dedicated sections for specific use cases like application authorization and IAM.

Wrap Up

In the future, we plan to run the survey on a more regular basis with more consistent questions, so that we can compare historical results and observe trends over time. If you filled out the survey, thank you! We know you're excited to receive the t-shirts, and we're working on sending them your way! Due to the current situation, it might take a bit longer than we had expected. If you have not yet filled out the survey, you can still fill out the survey. As always, if you have any questions or additional feedback, we're available on the Slack, GitHub, etc.

…even doggos love OPA [credit: @webbergs, idea: @the_dvorkin]

Open Policy Agent v0.19 Release

Open Policy Agent v0.19 release announcement banner

Last week we released OPA v0.19, containing 63 commits from 12 contributors (of which, 9 were external.) This release includes many important fixes and enhancements, as well as a new Rego parser written in Go that speeds up parsing time by ~100x in most cases. You can find more details on the GitHub releases page.

Community Updates

Since many in-person events have gone virtual due to the COVID-19 crisis, there have been several virtual events, webinars and podcasts featuring OPA over the last few weeks. Here's a quick roundup:

Since KubeCon 2019 in Barcelona, we have asked users to post Q&A style queries on Stack Overflow instead of slack.openpolicyagent.org. The reason is that most answers posted on Slack are not discoverable! If you have Q&A style questions (e.g., "How to test not deny?"), try posting on Stack Overflow and tagging with open-policy-agent.

Faster Parsing & Better Errors

The largest change in v0.19 is the new Rego parser, which is written from scratch in Go. Previously, OPA relied on a generated parser that was defined using PEG (Parsing Expression Grammar [wikipedia]). Over the years, as the grammar has grown, and larger inputs have been thrown at it, the generated parser became a bottleneck (e.g., it could take about 10x longer to parse an input than compile and evaluate the query.

Inside OPA we were able to workaround the performance problems with caching, using Go's "encoding/json" package and manually converting to AST ("Abstract Syntax Tree") values when possible, etc. However, new users embedding OPA as a library would (understandably) make mistakes and wonder why performance was poor. The majority of the performance problems in the generated parser were due to a significant amount of heap allocations required to parse any input.

In addition to performance, we also struggled with usability around parser error messages. If the parser was not able to match an input, you would be presented with an error like "policy.rego:19: no match found". No match? Tell me more!

Rather than attempt to continue incrementally improving the existing parser, we decided to rewrite it from scratch in Go. The result is a new parser that allocates significantly less memory (which improves performance by approximately 100x in most cases) and has better error messages. One important requirement for the new parser was backwards compatibility — the new parser could not break existing policies OR programs that embed OPA as a library (e.g., the parser APIs and the AST types also had to remain the same). To ensure we did not break existing (valid) policies, we checked for differences in the output of the old and new parser for hundreds of thousands of Rego snippets (which deserves another blog post in the future.) Lastly, we also applied the wonderful go-fuzz project to the parser to help catch crashes and other bugs.

Since we no longer have a declarative representation of the language grammar in Go, please refer to the ENBF grammar in the OPA documentation as the authoritative source.

The chart below shows the difference in performance between the old (v0.18 and earlier) and new (v0.19 and later) parser (log scale):

The chart below shows the difference in performance between the old (v0.18 and earlier) and new (v0.19 and later) parser (log scale)

Overall, we are happy with the process. In the future we plan to continue optimizing performance in the parser and looking for ways to improve error messaging and usability.

man(1) pages, http.send, and Emacs support

In addition to the new parser, v0.19 includes dozens of bugfixes and feature enhancements. @olivierlemasle contributed code to generate OPA man pages from the OPA CLI definitions. The man pages are automatically available if you:

brew install opa

Install OPA with homebrew and use &#39;man opa&#39; to learn about it.

Install OPA with homebrew and use 'man opa' to learn about it.

@jpeach submitted a number of patches that improve testing and support for the http.send built-in function. For example, policies can now explicitly set TLS server names as well as certificates and keys when invoking the built-in function (previously they could only come from the environment or local files). This is useful if you want to specify those values in data or as local variables inside the policy itself.

Lastly, the release also includes a pointer to the new rego-mode Emacs package developed by @psibi. The package provides syntax highlighting, formatting and more. In the future, the package could be extended to support many of the same features as the OPA extension for VS Code.

WebAssembly Update

At KubeCon 2019 in San Diego we announced support for compiling OPA policies into WebAssembly (Wasm). Wasm enables OPA policies to execute in new environments like CDNs, service proxies and more without requiring an out-of-process RPC call to query OPA.

This week we are excited to release further support for Wasm in OPA with the new golang-opa-wasm project! This project wraps the wasmerio/go-ext-wasm runtime library to provide convenient APIs for policy execution and more. The golang-opa-wasm SDK is still work-in-progress but feedback and contributions are welcome.

Rego Playground: New Features

This time last year we launched the Rego Playground. The playground provides an online interactive environment where users can experiment with and share OPA policies.

Today, we are excited to release features in the playground that will help new users get up and running with OPA even quicker than before. Let's have a look.

Feature: Examples for Kubernetes, Envoy and more

Anyone who designs user interfaces (or perhaps any software project/product) is probably familiar with the "blank slate" problem: all of the designs assume the system is loaded with data. However, when new users arrive that data does not exist and the system feels empty.

Since the beginning of OPA we have focused on providing detailed documentation so that new users (a) have something to look at and (b) can figure out whether OPA will solve their problems. Of course, this assumes people want (or have time) to read the docs! Ain't nobody got time for that.

Rather than trying to tell everyone to RTFM, we have decided to preload the playground with a catalogue of examples for common use cases like Kubernetes admission control, API authorization with Envoy and more:

Rego Playground examples catalogue

The catalogue is searchable and filterable. Over time we plan to continue to curate the catalogue to ensure they demonstrate common use cases and patterns in policy language.

Feature: Kick the tires with OPA bundles

Once you have written a couple policies or modified existing ones, the next thing you often want to see is how OPA can be deployed and have policies distributed to it.

OPA supports a feature called "bundles" that enable policy discovery and distribution. Bundles are just gzipped tarballs containing policy and data files. When bundles are enabled, OPA continually tries to download and activate the latest version of policy and data that control its decision-making. Bundles are designed to be CDN compatible so that policy distribution can scale easily. All you have to do is set up a webserver to host your bundles (or rely on services like AWS S3), however, this is often more work than people want to embark on while they kick the tires.

To help users get up and running with bundles, we have extended the playground to serve published policies as bundles. All you have to do is click "Publish".

Rego Playground publish bundle workflow

Once you publish your policy, the playground displays the steps to:

  • Download and run OPA locally
  • Configure OPA to use your published policy
  • Test the policy with the input from the playground

Any edits to the policy that are published from the same browser window will propagate to OPAs configured to use the playground bundle. This lets you exercise OPA's dynamic policy update capability (aka "hot reloading").

Feature: Improved support for context-aware policies

When software systems query OPA for policy decisions they can supply arbitrary JSON data as input. This data drives policy decision-making, however, in many cases, it's not sufficient — more information about the state of the world is required to render a decision. In OPA, we often refer to this information as "context". There are various ways to load context into OPA, however, one of the most common ways is to cache data in-memory alongside the policies.

When context is cached in-memory it's referenced under the data global variable. If you have used OPA for Kubernetes admission control, you may have seen policies that refer to the cached state of the Kubernetes cluster maintained inside of OPA in admission controller deployments (e.g., data.kubernetes.ingresses).

In the initial version of the playground, we did not provide support for loading arbitrary external JSON values under data. This was primarily to keep the UI as simple as possible and also because technically you can just define any JSON values you want inside of the policy itself — references to JSON defined in the policy are identical to references to raw JSON that would be cached in OPA.

So while it was possible to experiment with context-aware policies inside the playground, it was a bit non-obvious. In the latest release, there is now an empty "Data" panel (along with "Input" and "Output") that lets you load arbitrary JSON values under data:

Rego Playground Data panel

KubeCon US 2019 Recap

Banner image for the KubeCon US 2019 recap post

A few weeks ago San Diego hosted the largest KubeCon ever with nearly 12,000 attendees. Let's take a look at some OPA highlights!

OPA Summit 2019

OPA Summit 2019

Day-0 (the day before the Kubecon main event) marked a big milestone for the project: we held our first-ever OPA summit!

Tim Hinrichs shows off the new website to 100+ attendees at the event.

The goal of this summit was to showcase a variety of use cases from companies running OPA in production. We received around 20 submissions to the CFP and then selected a handful of talks that demonstrated impressive scale or new applications for OPA in production.

During the talk about how Pinterest uses OPA, Jeremy Krach and William Fu shared how they architected policy distribution and management for authorization on bare EC2 instances and multi-tenant Kubernetes clusters at Pinterest. Their talk walks through the entire policy lifecycle from authoring to distribution to enforcement. After covering the pipeline, they explained exactly how they offload policy decision-making from services. In terms of volume, their Kafka integration sees the highest traffic. At peak, OPA serves ~450K decisions/second across their clusters (and with caching that increases to ~8.5M decisions/second globally).

William Fu and Jeremy Krach from Pinterest share details on authorization scale at Pinterest.

William Fu and Jeremy Krach from Pinterest share details on authorization scale at Pinterest.

Michael Sorens from Chef spoke about how they use OPA to implement IAM in Chef Automate. Michael highlighted OPA's TDD-based approach to policy authoring and explained how they use OPA to implement pre-flight authorization checks that control which UI components are rendered based on user permissions. This use case is becoming more common as OPA is increasingly used higher up in the stack.

Michael speaks about applying TDD to policy.

Michael speaks about applying TDD to policy.

You can find other great OPA Summit talks from Atlassian, Trip Advisor, and Capital One on YouTube. We are looking forward to hosting the next OPA Summit in Boston at KubeCon US 2020!

Kubernetes: the guardrail enforcement point

At KubeCon after the day-0 summit, engineers from companies like Yelp, Goldman Sachs, Reddit, Adobe, Google, and Microsoft spoke about how they use OPA.

There were several excellent sessions about OPA Gatekeeper and admission control use cases in Kubernetes. OPA is used extensively to enforce guardrails over compute, network, and storage resources in Kubernetes and this was reflected at KubeCon.

Two talks that highlight how Kubernetes is becoming the defacto standard for managing desired state were from Rita Zhang (@ritazzhang) and Ivan Sim (@ihcsim) from Microsoft and Buoyant (respectively) and Sandeep Parikh (@crcsmnky) from Google. This is great for platform administrators because it means they can leverage OPA Gatekeeper to enforce guardrails across not just native Kubernetes resources (e.g., Pods, Services, etc.) but also service mesh resources (e.g., Linkerd, Istio), CI/CD resources (e.g., tekton.dev), cloud resources (e.g., crossplane.io), and more.

Miguel Uzcategui (Goldman Sachs) and OPA co-founder Tim Hinrichs (CTO of Styra) spoke about how Goldman Sachs uses OPA to do policy-based provisioning in Kubernetes. They explain how Goldman Sachs implemented Kubernetes controllers that offload decision-making to OPA so that when namespaces are created, resources like quotas, roles, and persistent volumes (and claims) are automatically instantiated (and then re-converged if something changes.) This is important for maintaining strict requirements around security and availability at Goldman Sachs. They also show why OPA is a good fit for this problem (e.g., easier testing, ability to use external context in decision-making, etc.) and how it has performed in production for nearly a year.

Miguel shares results from running the OPA in production for over a year.

Miguel shares results from running the OPA in production for over a year.

Outside Kubernetes: App configuration and Microservices

@garethr's talk about applying OPA policies earlier in application lifecycles highlighted OPA's general-purpose nature. His talk was filled with examples and demos that show how to use OPA and conftest to validate configuration files (e.g., Pipfiles, Dockerfiles, etc.) and plug into CI/CD systems.

Finally, on Thursday, Daniel Popescu and Ben Plotnick talked about how Yelp evolved their security infrastructure (using OPA and Envoy) as the company transitioned away from a monolith. Their talk highlights how perimeter-based security does not scale to microservice architectures and how development of custom policy languages is challenging. The talk provides a deep dive on how they leverage Envoy and OPA to implement mTLS and access control across a fleet of microservices. They also discuss the gradual migration off their custom policy language by transpiling to OPA.

Authorization - Service Mesh architecture diagram showing Service A and B, Envoy, ext_authz, and OPA

This post only highlights a few of the excellent talks from KubeCon about OPA so if you want to watch more check out this playlist on YouTube.

Conclusions

KubeCon San Diego demonstrated how many companies run OPA in production for a variety of use cases. After starting the project nearly four years ago it is very exciting to see it fulfilling the original goal of modernizing and enabling policy enforcement across the stack.

Last year we saw rapid growth in end-user adoption, the launch of OPA Gatekeeper, and promotion to the CNCF Incubating tier. In 2020 we plan to continue investing in performance and usability for the core of the project, new integrations leveraging the recent WebAssembly compiler feature, and better documentation of reference architectures.

See you all in Amsterdam and Boston!

OPA v0.15.1: Rego on WebAssembly

OPA v0.15.1 release banner for Rego on WebAssembly

We're excited to announce that with OPA v0.15.1 you can compile any Rego policy into WebAssembly. This release is the culmination of many incremental improvements to the WebAssembly compiler in OPA that we demonstrated with a proof-of-concept at KubeCon 2018 in Seattle.

What is WebAssembly?

From WebAssembly.org:

"WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications."

What does Wasm have to do with policy enforcement?

One of the principles behind OPA is that policy decision-making should be decoupled from policy enforcement. For people building software products, decoupling lets them avoid undifferentiated heavy lifting and get to market faster because they do not have to worry about implementing a policy or authorization engine from scratch. For operators running large-scale software systems, decoupling addresses fragmentation from siloed policy implementations enabling unified control and visibility across the stack.

Cloud native projects have embraced the idea as they matured. Today, projects like Kubernetes and Envoy have strong support for externalized admission control and authorization checks. However, it's not enough to just offer a plugin model for policy decisions. You need a component that can respond to policy queries with answers. This is where OPA comes in. OPA provides a lightweight general-purpose policy engine that can be embedded throughout your infrastructure. When your software needs to make decisions it can query OPA and OPA will reply with the answer based on the rules and data that you distribute to it.

While OPA is designed to be as lightweight as possible (e.g., by keeping all rules and data in-memory, not introducing any external runtime dependencies, etc.) the fact that the policy evaluation engine is written in Go means that library embedding can be difficult for software not written in Go. Moreover, requiring OPA be installed as a daemon inside (or near) the enforcement point comes with it's own set of challenges and may not always be feasible (e.g., if you are not the owner of the platform.)

This is where Wasm is relevant because it provides a safe, portable, efficient standards-based execution environment for arbitrary code and logic. In the past year Wasm-based extension mechanisms gained popularity: CDN companies like Cloudflare and Fastly allow you to execute software at the edge using Wasm, service proxies like Envoy have integrated Wasm runtimes, and even databases like Postgres can be extended with Wasm built-in functions.

OPA ecosystem diagram with WebAssembly integration points highlighted

With Wasm-based extension mechanisms becoming the norm and programming language support for Wasm runtimes maturing, Wasm will naturally become a standard mechanism for offloading policy evaluation from your software. At the same time, Wasm is only a low-level instruction format. The only data types at your disposal are 32/64-bit integer and floating-point numbers. This makes it impractical to use Wasm directly for any kind of policy specification. Enter OPA.

How does OPA work with Wasm?

OPA includes a compiler that accepts Rego policies as input and generates an executable Wasm program as output. This Wasm program can be loaded into any standard Wasm runtime and executed when policy decisions are needed. With the v0.15.1 release we have reached an important milestone in the compiler: with the exception of built-in functions, OPA can now compile any Rego policy into Wasm.

In the latest OPA release there are two ways of compiling Rego policies into Wasm:

  • On the command-line using the opa build CLI tool.
  • In Go by integrating with the github.com/open-policy-agent/opa/rego package.

Diagram of the Wasm compile-time and runtime workflow

The compilation process takes a Rego query and zero or more Rego files and generates an execution plan that is compiled into a Wasm module binary. The module binary can then be loaded into any Wasm runtime and executed with different input and data values to obtain decisions. The resulting Wasm module binary sizes are not too significant. The baseline size for a policy with a single statement is ~30KB on disk. A policy containing 300,000 statements consumes ~20MB on disk.

The initial benchmarks comparing policy evaluation time in Wasm versus the existing Go interpreter implemented in OPA are promising. For example, a relatively simple policy that searches over a large number of data items to decide whether an operation should be allowed (or not) evaluates ~20x faster with the Wasm compiled version. This is to be expected because the overhead of the interpreter in OPA has been completely removed.

package example

default allow = false

allow {
rule := data.rules[_]
rule.action == input.action
rule.resource == input.resource
rule.identity == input.identity
}

Benchmark results:

# of data.rules | Existing Go interpreter | Wasm compiled policy
----------------+-------------------------+---------------------
100 | 0.354ms | 0.0173ms
1,000 | 3.1ms | 0.145ms
10,000 | 30ms | 1.5ms
100,000 | 316ms | 15ms

If you are interested in more details about Wasm support in OPA see this page in the documentation and check out this example on GitHub.

What's Next?

We have reached an important milestone for OPA with Wasm and we are excited about Wasm's potential as it relates to policy enforcement. However, there is still a lot left to do.

The main gap (at the moment) is lack of support for the 50+ built-in functions from OPA proper. While you can implement these built-in functions yourself in the host language (e.g., NodeJS) and import them into the Wasm module, we want to make this smoother. Another area that needs work are the management APIs. The OPA daemon and Go library expose APIs that let you control policy distribution, decision logging, and more. In a Wasm-enabled enforcement point these functions do not exist yet.

In the coming months we are going to build out new integrations that leverage Wasm, create SDKs for languages/runtimes other than Go and NodeJS, and use this experience to harden and optimize the new implementation.

If you would like to get involved feel free to file issues on GitHub or join us on Slack.

v0.14 Release

We're excited to announce the v0.14.0 release of OPA. This release includes 147 commits from 17 authors across 9 organizations! For a detailed list of changes see the GitHub releases page. In this latest release we focused on the getting started experience for new users.

Community Updates

Docs, Docs, Docs

Earlier this year we launched The Rego Playground. The playground provides a way to evaluate and test policies from the browser. Based on positive feedback on the playground we decided to take it further. In the latest version of the docs, policy examples are interactive!

Live Docs!

In addition to "live docs", we have also re-organized and improved the core content. The docs had grown organically since the project launched and it was time for a rethink. The new structure and content aims to get users started with Rego as quickly as possible. We have also begun carving out dedicated sections for popular integrations like Kubernetes admission control. Finally, we added a search integration powered by Algolia.

Performance Optimizations

This release includes a number of optimizations to the AST and other packages. The optimizations focused on heap allocations during evaluation. With the new optimizations we see about ~25% faster evaluation across-the-board for end-to-end benchmarks in OPA:

Test Case Old New Delta
-----------------------------------------------------------
AuthzForbidAuthn-8 32.3µs±1% 30.5µs±1% −5.53%
AuthzForbidPath-8 109µs±1% 85µs±1% −22.14%
AuthzForbidMethod-8 115µs±2% 89µs±1% −22.44%
AuthzAllow10Paths-8 112µs±2% 87µs±0% −22.95%
AuthzAllow100Paths-8 725µs±3% 529µs±3% −27.09%
AuthzAllow1000Paths-8 6.27ms±1% 4.55ms±1% −27.40%

OPA benchmarks are run automatically on a regular basis and compared against the last stable release using the benchstat tool. The results are posted on the benchmark results page.

Improved File Loading in VS Code

The VS Code extension has been updated to use the new -b or --bundle flag on opa eval to avoid loading all JSON and YAML files inside the workspace. While the old file loading approach was acceptable for Rego-specific workspaces it fell over in larger or mixed workspaces (which most people have!)

With the new -b flag and the latest version of the Open Policy Agent extension for VS Code, file loading is much better.