Common Expression Language (CEL), hızlı, taşınabilir ve güvenli bir şekilde yürütülecek şekilde tasarlanmış genel amaçlı bir ifade dilidir. CEL'i tek başına kullanabilir veya daha büyük bir ürüne yerleştirebilirsiniz. CEL, uzak prosedür çağrılarını (RPC'ler) yönlendirmekten güvenlik politikalarını tanımlamaya kadar çok çeşitli uygulamalar için uygundur. CEL, genişletilebilir, platformdan bağımsızdır ve bir kez derleme/çok kez değerlendirme iş akışları için optimize edilmiştir.
CEL, kullanıcı kodunu yürütmek için özel olarak güvenli olacak şekilde tasarlanmıştır. Kullanıcının Python kodunda eval()
işlevini körü körüne çağırmak tehlikeli olsa da kullanıcının CEL kodunu güvenli bir şekilde çalıştırabilirsiniz. CEL, daha düşük performanslı davranışları engellediği için değerlendirmeyi nanosaniyeler veya mikrosaniyeler içinde güvenli bir şekilde yapar. CEL'in hızı ve güvenliği, onu performans açısından kritik uygulamalar için ideal kılar.
CEL, tek satırlık işlevlere veya lambda ifadelerine benzer ifadeleri değerlendirir. CEL genellikle boolean kararlar için kullanılsa da JSON veya protokol arabellek mesajları gibi daha karmaşık nesneler oluşturmak için de kullanabilirsiniz.
Neden CEL?
Birçok hizmet ve uygulama, bildirim temelli yapılandırmaları değerlendirir. Örneğin, rol tabanlı erişim denetimi (RBAC), bir kullanıcı rolü ve bir kullanıcı grubu verildiğinde erişim kararı veren bildirim temelli bir yapılandırmadır. Bildirim temelli yapılandırmalar çoğu durumda yeterli olsa da bazen daha fazla ifade gücüne ihtiyacınız olur. CEL bu noktada devreye girer.
Bildirim temelli bir yapılandırmayı CEL ile genişletme örneği olarak Google Cloud Identity and Access Management'ın (IAM) özelliklerini ele alalım. RBAC yaygın bir durum olsa da IAM, kullanıcıların isteğin proto mesaj özelliklerine veya erişilen kaynaklara göre role dayalı iznin kapsamını daha da kısıtlamasına olanak tanıyan CEL ifadeleri sunar. Bu tür koşulların veri modeli aracılığıyla açıklanması, çalışılması zor olan karmaşık bir API yüzeyine yol açar. Bunun yerine, CEL'i özellik tabanlı erişim denetimi (ABAC) ile kullanmak, RBAC'nin etkileyici ve güçlü bir uzantısıdır.
CEL'in temel kavramları
CEL'de bir ifade, bir ortama göre derlenir. Derleme adımında, protocol buffer biçiminde bir soyut sözdizimi ağacı (AST) oluşturulur. Derlenmiş ifadeler, değerlendirmenin mümkün olduğunca hızlı olması için gelecekte kullanılmak üzere saklanır. Tek bir derlenmiş ifade, birçok farklı girişle değerlendirilebilir.
Bu kavramlardan bazılarını daha yakından inceleyelim.
İfadeler
İfadeler kullanıcılar tarafından yazılır. İfadeler, tek satırlık işlev gövdelerine veya lambda ifadelerine benzer. Girişi bildiren işlev imzası, CEL ifadesinin dışında yazılır ve CEL'de kullanılabilen işlev kitaplığı otomatik olarak içe aktarılır.
Örneğin, aşağıdaki CEL ifadesi bir istek nesnesi alır ve istek bir claims
jetonu içerir. İfade, claims
jetonunun hâlâ geçerli olup olmadığını belirten bir Boole değeri döndürür.
Hak talebi jetonunun kimliğini doğrulamak için örnek CEL ifadesi
// 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
Kullanıcılar CEL ifadesini tanımlarken hizmetler ve uygulamalar, ifadenin çalıştığı ortamı tanımlar.
Ortam
Ortamlar hizmetlere göre tanımlanır. CEL'yi yerleştiren hizmetler ve uygulamalar, ifade ortamını bildirir. Ortam, CEL ifadelerinde kullanılabilen değişkenler ve işlevler topluluğudur.
Örneğin, aşağıdaki textproto
kodu, bir CEL hizmetinden gelen CompileRequest
mesajını kullanarak request
ve now
değişkenlerini içeren bir ortamı bildirir.
Örnek CEL ortamı bildirimi
# Format: $SOURCE_PATH/service.proto#CompileRequest
declarations {
name: "request"
ident {
type { message_type: "google.rpc.context.AttributeContext.Request" }
}
}
declarations {
name: "now"
ident {
type { we
ll_known: "TIMESTAMP" }
}
}
Proto tabanlı bildirimler, bir ifadedeki tüm tanımlayıcı ve işlev referanslarının doğru şekilde bildirilip kullanıldığından emin olmak için CEL türü denetleyicisi tarafından kullanılır.
İfade işleme aşamaları
CEL ifadeleri üç aşamada işlenir:
- Ayrıştır
- Kontrol Et
- Değerlendir
CEL kullanımının en yaygın şekli, ifadeleri yapılandırma zamanında ayrıştırıp kontrol etmek, AST'yi depolamak ve ardından çalışma zamanında AST'yi tekrar tekrar alıp değerlendirmektir.
CEL işleme aşamalarının resmi
CEL, okunabilir bir ifadeden ANTLR sözcük ayrıştırıcı ve ayrıştırma dilbilgisi kullanılarak AST'ye ayrıştırılır. Ayrıştırma aşamasında, AST'deki her Expr
düğümünün ayrıştırma ve kontrol sırasında oluşturulan meta verilere dizin oluşturmak için kullanılan bir tam sayı kimliği içerdiği proto tabanlı bir AST yayınlanır. Ayrıştırma sırasında oluşturulan syntax.proto
dosyası, ifadenin dize biçiminde yazılanların soyut gösterimini ifade eder.
Bir ifade ayrıştırıldıktan sonra, ifadedeki tüm değişken ve işlev tanımlayıcılarının bildirilmiş ve doğru şekilde kullanıldığından emin olmak için ortamda tür kontrolü yapılır. Tür denetleyicisi, değerlendirme verimliliğini önemli ölçüde artırabilecek tür, değişken ve işlev çözümleme meta verilerini içeren bir checked.proto
dosyası oluşturur.
Son olarak, bir ifade ayrıştırılıp kontrol edildikten sonra depolanan AST değerlendirilir.
CEL değerlendiricinin üç şeye ihtiyacı vardır:
- Tüm özel uzantılar için işlev bağlamaları
- Değişken bağlamalar
- Değerlendirilecek bir AST
İşlev ve değişken bağlamaları, AST'yi derlemek için kullanılanlarla eşleşmelidir. Bu girişlerden herhangi biri birden fazla değerlendirmede yeniden kullanılabilir. Örneğin, bir AST birçok değişken bağlama kümesinde değerlendirilebilir, aynı değişkenler birçok AST'ye karşı kullanılabilir veya bir sürecin ömrü boyunca kullanılan işlev bağlamaları (yaygın bir durum) olabilir.