The goal of CEL is fast, scalable, and portable expression evaluation.
Fast - CEL runs without the need for sandboxing, making it much faster than sandboxed solutions like WebAssembly, Lua, and embedded JavaScript.
Scalable - Features like variables and functions would make CEL more expressive, but also less scalable as it's easy to write a few lines of code with functions that consume exponential amounts of memory and compute. CEL is simply the expression and nothing more.
Portable - CEL is implemented in Go[0], C++[1], and Python[2] with Java open sourcing in development. There is a public codelab[3] available for Go if anyone is interested. There is also a conformance suite in CEL-Spec to ensure consistent behavior between runtimes and environments. Our objective is to make it possible to bring CEL to K8s, J2EE apps, and C++ proxies. Evaluate at line-rate everywhere. Personally, I hope someone tries to make CEL work on IoT devices some day too.
Where? - CEL is usually embedded into larger projects rather than being the one stop shop for solving a particular kind of problem. For example, CEL Policy Templates[4] has an opinionated way of using CEL to validate/evaluate YAML configs. Most of the time CEL is part of a service API.
In addition to being used in Firebase's Cloud Firestore / Cloud Storage security rules, it is also used in several other Google Cloud services:
- Cloud Armor[5]
- IAM Conditions[6]
- Cloud Healthcare Consents[7]
- Cloud Build Notifiers[8]
- Security Token Service[9]
- Access Levels[10], and more.
CEL is also used in some prominent open source projects like Envoy RBAC[11], Caddyserver[12], Krakend.io[13], and Cloud Custodian[14].
Unless the open source is part of a paid offering (like Firebase CLI), it's required to be listed as not being an Official Google Product. That said, CEL is used in a number of publicly supported Google Cloud services which means that it's well supported with dedicated maintenance. Case in point, I'm the CEL lead at Google.
OPA Rego and CEL are distinct, but you can see similar thinking in OPA Gatekeeper and CEL Policy Templates (https://github.com/google/cel-policy-templates-go) which are aimed at separating config from policy in order to create a better user experience. Note, the CEL Policy Templates are early in development, but build upon the abstractions provided by CEL.
Macros are considered an optional feature of the language because they can:
a) easily be disabled,
b) have no dedicated syntax beyond that defined for core CEL.
CEL supports subsetting and extension which means you can actually turn off built-in features in order to guarantee a sort of maximal compute / memory impact that an expression might have while still augmenting the core feature set in order to tailor it to your use case.
Bounded iteration is possible via macros, and such iterations can be nested; thus, you can have high polynomial time expressions, but only if you choose to permit them and many use cases (like IAM Conditions) don't. This is different from OPA Rego or HashiCorp Sentinel in that these features are baked into the syntax and impossible to turn off with 100% certainty.
Since you can't declare functions or variables within CEL, the environment of an expression (the variables and functions it can use) is completely controlled by the host process. The environment acts like a sandbox of sorts, but one specifically chosen by the application and not a general purpose mechanism like a hypervisor or sandbox like WebAssembly.
Fast - CEL runs without the need for sandboxing, making it much faster than sandboxed solutions like WebAssembly, Lua, and embedded JavaScript.
Scalable - Features like variables and functions would make CEL more expressive, but also less scalable as it's easy to write a few lines of code with functions that consume exponential amounts of memory and compute. CEL is simply the expression and nothing more.
Portable - CEL is implemented in Go[0], C++[1], and Python[2] with Java open sourcing in development. There is a public codelab[3] available for Go if anyone is interested. There is also a conformance suite in CEL-Spec to ensure consistent behavior between runtimes and environments. Our objective is to make it possible to bring CEL to K8s, J2EE apps, and C++ proxies. Evaluate at line-rate everywhere. Personally, I hope someone tries to make CEL work on IoT devices some day too.
Where? - CEL is usually embedded into larger projects rather than being the one stop shop for solving a particular kind of problem. For example, CEL Policy Templates[4] has an opinionated way of using CEL to validate/evaluate YAML configs. Most of the time CEL is part of a service API.
In addition to being used in Firebase's Cloud Firestore / Cloud Storage security rules, it is also used in several other Google Cloud services: - Cloud Armor[5] - IAM Conditions[6] - Cloud Healthcare Consents[7] - Cloud Build Notifiers[8] - Security Token Service[9] - Access Levels[10], and more.
CEL is also used in some prominent open source projects like Envoy RBAC[11], Caddyserver[12], Krakend.io[13], and Cloud Custodian[14].
[0]: https://github.com/google/cel-go [1]: https://github.com/google/cel-cpp [2]: https://github.com/cloud-custodian/cel-python [3]: https://codelabs.developers.google.com/codelabs/cel-go [4]: https://github.com/google/cel-policy-templates-go [5]: https://cloud.google.com/armor/docs/rules-language-reference [6]: https://cloud.google.com/iam/docs/conditions-overview [7]: https://cloud.google.com/healthcare/docs/concepts/consent-mo... [8]: https://cloud.google.com/cloud-build/docs/filter-build-notif... [9]: https://cloud.google.com/iam/docs/workload-identity-federati... [10]: https://cloud.google.com/access-context-manager/docs/custom-... [11]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overv... [12]: https://caddyserver.com/docs/caddyfile/matchers#expression [13]: https://www.krakend.io/docs/endpoints/common-expression-lang... [14]: https://github.com/cloud-custodian/cel-python