What is Common Expression Language (CEL)?
Google developed the expression language known as Common Expression Language (CEL). This non-compete, open-source Turing language is used to define and apply restrictions as well as validate data. Kubernetes, Envoy, and the Google Cloud Certificate Authority Service all utilise CEL. CEL particularly generates CRDs (Custom Resource Definitions) in Kubernetes.
Common Expression Language is far more adaptable and simple to comprehend than C, C++, and Java, making it suitable for specifying rules and restrictions. Another language that is comparable to CEL is Rego. The two are different, though, in that the later makes use of optional Common Expression Language macros, while the former has a rigid syntax for the list of comprehensions. CEL uses the expressions as inline within a rule, whereas Rego uses local functions for comprehensions.
Syntax of CEL
Applications involving Certificate Authorities (CAs) are where Common Expression Language is most frequently utilised. Some security precautions are used when creating CEL code for a CA:
The certificate template and CA pool policy issuing are done in a flexible dialect.
IAM (Identity and Access Management) is done in a customer vernacular.
How Does Kubernetes Use CEL?
Validation rules, policies, and constraints may be created and managed using Common Expression Language in conjunction with Kubernetes using its API. Its versatility and ease of comprehension make it suitable for this use case. Typically brief, CEL expressions can be included as inline elements into the string fields of Kubernetes API services.
The primary function of Common Expression Language in Kubernetes is the creation and administration of Custom Resource Definitions (CRD). Because it is simple to include into CRD schemas and allows for the rich and comprehensible expression of constraints, CEL is the preferred option. Additionally, CEL makes it possible for CRDs to be self-maintained and guarantees that CRD schemas are safely performed and reviewed beforehand.
Common Expression Language Examples
Basic Expressions
10 + 5 // Addition: returns 15
10 - 3 // Subtraction: returns 7
10 * 2 // Multiplication: returns 20
10 / 2 // Division: returns 5
10 % 3 // Modulus: returns 1
Logical Operators
true && false // Logical AND: returns false
true || false // Logical OR: returns true
!true // Logical NOT: returns false
Comparison Operators
10 == 10 // Equality: returns true
10 != 5 // Inequality: returns true
10 > 5 // Greater than: returns true
5 < 10 // Less than: returns true
5 <= 5 // Less than or equal to: returns true
10 >= 5 // Greater than or equal to: returns true
String Operations
"hello" + " world" // Concatenation: returns "hello world"
"hello".size() // Returns 5
"hello".startsWith("he") // Returns true
"hello".endsWith("o") // Returns true
"hello".contains("ll") // Returns true
List Operations
[1, 2, 3].size() // Returns 3
[1, 2, 3][0] // Returns 1 (first element)
[1, 2, 3].contains(2) // Returns true
[1, 2, 3] + [4, 5] // Returns [1, 2, 3, 4, 5]
Map Operations (Dictionary)
{"name": "Alice", "age": 30}.name // Returns "Alice"
{"name": "Alice", "age": 30}.has("age") // Returns true
{"a": 1, "b": 2}.size() // Returns 2
Conditional (Ternary) Expression
x > 10 ? "large" : "small" // If x > 10, returns "large"; otherwise, "small"
Working with Null Values
null ?? "default" // If null, returns "default"
Filtering and Map Functions
[1, 2, 3, 4].filter(x, x > 2) // Returns [3, 4]
[1, 2, 3].map(x, x * 2) // Returns [2, 4, 6]
CEL Expression | Purpose |
names.isSorted() | Verify that a list of names is kept in alphabetical order |
items.map(x, x.weight).sum() == 1.0 | Verify that the “weights” of a list of objects sum to 1.0 |
lowPriorities.map(x, x.priority).max() < highPriorities.map(x, x.priority).min() | Verify that two sets of priorities do not overlap |
names.indexOf(‘should-be-first’) == 1 | Require that the first name in a list is a specific value |
Rules of Validation
It is significant to remember that the Validating Admission Policy rules were first implemented as an alpha version in Kubernetes 1.26 and have since been refined in later iterations. Admission requests are verified when a validation policy is established, and the policy is then linked to the relevant resources. CRD writers can specify the functionality of custom objects by using validation rules. Below are a few examples:
Validation Rule | Purpose |
self.minReplicas <= self.replicas | Validate an integer field is less than or equal to another integer field |
‘Available’ in self.stateCounts | Validate an entry with the ‘Available’ key exists in a map |
self.set1.all(e, !(e in self.set2)) | Validate that the elements of two sets are disjoint |
self == oldSelf | Validate that a required field is immutable once it is set |
self.created + self.ttl < self.expired | Validate that ‘expired’ date is after a ‘create’ date plus a ‘ttl’ duration |
Transition Rules
The old and new states of the resources listed in the validation criteria are compared using transition rules. They make sure the cluster’s API server doesn’t have any incorrect state transitions.
Transition Rule | Purpose |
self == oldSelf | For a required field, make that field immutable once it is set. For an optional field, only allow transitioning from unset to set, or from set to unset. |
(on parent of field) has(self.field) == has(oldSelf.field)on field: self == oldSelf | Make a field immutable: validate that a field, even if optional, never changes after the resource is created (for a required field, the previous rule is simpler). |
self.all(x, x in oldSelf) | Only allow adding items to a field that represents a set (prevent removals). |
self >= oldSelf | Validate that a number is monotonically increasing. |
Features
Quick
Evaluation of expression in performance-critical pathways from nanoseconds to microseconds is accelerated.
Transportable
It is lightweight, developer-friendly, and has a standard syntax for many Google and external systems.
Wide-ranging
Subsetting and extension are supported, and it’s simple to embed and modify to meet configuration and policy needs.
Secure
Only accesses data supplied by the host program and is not Turing complete.