Common Expression Language (CEL) — это язык выражений общего назначения, предназначенный для быстрого, переносимого и безопасного выполнения. Вы можете использовать CEL отдельно или встроить его в более крупный продукт. CEL отлично подходит для самых разных приложений: от маршрутизации удаленных вызовов процедур (RPC) до определения политик безопасности. CEL является расширяемым, независимым от платформы и оптимизированным для рабочих процессов с однократной компиляцией и множественной оценкой.
CEL был разработан специально для обеспечения безопасности выполнения пользовательского кода. Хотя слепо вызывать eval()
для пользовательского кода Python опасно, вы можете безопасно выполнить пользовательский CEL-код. А поскольку CEL предотвращает поведение, которое могло бы снизить его производительность, он безопасно оценивается за наносекунды или микросекунды. Скорость и безопасность CEL делают его идеальным для приложений, где производительность критически важна.
CEL оценивает выражения, похожие на однострочные функции или лямбда-выражения. Хотя CEL обычно используется для логических решений, вы также можете использовать его для создания более сложных объектов, таких как JSON или сообщения буфера протокола.
Почему CEL?
Многие службы и приложения оценивают декларативные конфигурации. Например, управление доступом на основе ролей (RBAC) — это декларативная конфигурация, которая принимает решение о доступе с учетом роли пользователя и набора пользователей. Хотя в большинстве случаев декларативных конфигураций достаточно, иногда вам требуется больше выразительных возможностей. Вот здесь и появляется CEL.
В качестве примера расширения декларативной конфигурации с помощью CEL рассмотрим возможности Google Cloud Identity and Access Management (IAM) . Хотя RBAC является распространенным случаем, IAM предлагает выражения CEL, позволяющие пользователям дополнительно ограничивать объем ролевого гранта в соответствии со свойствами прото-сообщения запроса или ресурсами, к которым осуществляется доступ. Описание таких условий через модель данных приведет к усложнению поверхности API, с которой будет сложно работать. Вместо этого использование CEL с контролем доступа на основе атрибутов (ABAC) является выразительным и мощным расширением RBAC.
Основные концепции CEL
В CEL выражение компилируется с учетом среды. На этапе компиляции создается абстрактное синтаксическое дерево (AST) в формате буфера протокола . Скомпилированные выражения сохраняются для использования в будущем, чтобы обеспечить максимально быструю оценку. Одно скомпилированное выражение может быть оценено с использованием множества различных входных данных.
Вот более детальный взгляд на некоторые из этих концепций.
Выражения
Выражения пишут пользователи. Выражения аналогичны телам однострочных функций или лямбда-выражениям. Сигнатура функции, объявляющая входные данные, записывается вне выражения CEL, а библиотека функций, доступных для CEL, импортируется автоматически.
Например, следующее выражение CEL принимает объект запроса, а запрос включает токен claims
. Выражение возвращает логическое значение, указывающее, действителен ли токен claims
.
Пример выражения CEL для аутентификации токена утверждений
// Check whether a JSON Web Token has expired by inspecting the 'exp' claim.
//
// Args:
// claims - authentication claims.
// now - timestamp indicating the current system time.
// Returns: true if the token has expired.
//
timestamp(claims["exp"]) < now
В то время как пользователи определяют выражение CEL, службы и приложения определяют среду, в которой оно работает.
Окружающая среда
Среды определяются службами . Службы и приложения, встраивающие CEL, объявляют среду выражения. Среда — это набор переменных и функций, которые можно использовать в выражениях CEL.
Например, следующий код textproto
объявляет среду, содержащую request
, а now
и переменные, используя сообщение CompileRequest
от службы CEL.
Пример объявления среды CEL
# Format: $SOURCE_PATH/service.proto#CompileRequest
declarations {
name: "request"
ident {
type { message_type: "google.rpc.context.AttributeContext.Request" }
}
}
declarations {
name: "now"
ident {
type { well_known: "TIMESTAMP" }
}
}
Объявления на основе прототипов используются средством проверки типов CEL, чтобы гарантировать, что все ссылки на идентификаторы и функции внутри выражения объявлены и используются правильно.
Фазы обработки выражения
Выражения CEL обрабатываются в три этапа:
- Разобрать
- Проверять
- Оценивать
Наиболее распространенный шаблон использования CEL — анализ и проверка выражений во время настройки, сохранение AST, а затем повторное получение и оценка AST во время выполнения.
Иллюстрация этапов обработки CEL
CEL анализируется из удобочитаемого выражения в AST с использованием лексера ANTLR и грамматики синтаксического анализатора. На этапе анализа создается AST на основе прототипа, где каждый узел Expr
в AST содержит целочисленный идентификатор, который используется для индексации метаданных, сгенерированных во время анализа и проверки. Файл syntax.proto
, созданный во время синтаксического анализа, представляет собой абстрактное представление того, что было введено в строковую форму выражения.
После анализа выражения его тип проверяется на соответствие среде, чтобы убедиться, что все идентификаторы переменных и функций в выражении объявлены и используются правильно. Средство проверки типов создает файл checked.proto
, содержащий метаданные типа, переменной и разрешения функций, которые могут значительно повысить эффективность оценки.
Наконец, после анализа и проверки выражения оценивается сохраненный AST.
Оценщику CEL нужны три вещи:
- Привязки функций для любых пользовательских расширений
- Привязки переменных
- AST для оценки
Привязки функций и переменных должны соответствовать тому, что использовалось для компиляции AST. Любой из этих входных данных можно повторно использовать в нескольких оценках, например, AST оценивается по множеству наборов привязок переменных, одни и те же переменные используются для многих AST, или привязки функций используются на протяжении всего жизненного цикла процесса (частый случай).