CEL (Common Expression Language)

Common Expression Language (CEL) è un linguaggio di espressione per uso generico progettato per essere veloce, portabile e sicuro da eseguire. Puoi utilizzare la tecnologia CEL da sola o incorporarla in un prodotto più grande. Il CEL è ideale per un'ampia gamma di applicazioni, dal routing delle chiamate di procedura remota (RPC) alla definizione dei criteri di sicurezza. Il CEL è estensibile, indipendente dalla piattaforma e ottimizzato per i flussi di lavoro che prevedono la compilazione una volta e la valutazione di più flussi di lavoro.

Il CEL è stato progettato specificamente per garantire la sicurezza durante l'esecuzione del codice utente. Anche se è pericoloso chiamare eval() con il codice Python di un utente, puoi eseguire in sicurezza il codice CEL di un utente. Inoltre, poiché il CEL impedisce comportamenti che le renderebbero meno performanti, la valutazione CEL avviene in modo sicuro in nanosecondi o microsecondi. La velocità e la sicurezza della tecnologia CEL la rendono ideale per le applicazioni critiche per le prestazioni.

La CEL valuta le espressioni simili a funzioni a riga singola o alle espressioni lambda. Sebbene il CEL sia comunemente usato per le decisioni booleane, puoi usarlo anche per creare oggetti più complessi come JSON o messaggi del buffer di protocollo.

Perché il CEL?

Molti servizi e applicazioni valutano le configurazioni dichiarative. Ad esempio, il controllo degli accessi basato sui ruoli (RBAC) è una configurazione dichiarativa che produce una decisione di accesso in base a un ruolo utente e a un insieme di utenti. Sebbene le configurazioni dichiarative siano sufficienti nella maggior parte dei casi, a volte è necessaria una potenza più espressiva. È qui che entra in gioco il CEL.

Come esempio di estensione di una configurazione dichiarativa con CEL, considera le funzionalità di Identity and Access Management (IAM) di Google Cloud. Sebbene il caso RBAC sia il caso comune, IAM offre espressioni CEL per consentire agli utenti di limitare ulteriormente l'ambito della concessione basata sui ruoli in base alle proprietà dei messaggi del protocollo della richiesta o alle risorse a cui si accede. La descrizione di tali condizioni tramite il modello dei dati comporterebbe una piattaforma API complessa con cui è difficile lavorare. L'utilizzo del CEL con il controllo dell'accesso basato su attributi (ABAC) è invece un'estensione espressiva ed efficace di RBAC.

Concetti fondamentali di CEL

In CEL, un'espressione viene compilata in un ambiente. Il passaggio della compilazione genera un albero di sintassi astratto (AST) in formato buffer di protocollo. Le espressioni compilate vengono archiviate per un uso futuro in modo che la valutazione sia il più veloce possibile. Una singola espressione compilata può essere valutata con molti input diversi.

Esaminiamo più da vicino alcuni di questi concetti.

Espressioni

Le espressioni sono scritte dagli utenti. Le espressioni sono simili ai corpi di funzioni a riga singola o alle espressioni lambda. La firma della funzione che dichiara l'input è scritta al di fuori dell'espressione CEL e la libreria di funzioni disponibili per CEL viene importata automaticamente.

Ad esempio, la seguente espressione CEL accetta un oggetto di richiesta e la richiesta include un token claims. L'espressione restituisce un valore booleano che indica se il token claims è ancora valido.

Espressione CEL di esempio per autenticare un token di attestazione

// 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

Mentre gli utenti definiscono l'espressione CEL, i servizi e le applicazioni definiscono l'ambiente in cui viene eseguita.

Ambienti

Gli ambienti sono definiti dai servizi. I servizi e le applicazioni che incorporano la tecnologia CEL dichiarano l'ambiente di espressione. L'ambiente è la raccolta di variabili e funzioni che possono essere utilizzate nelle espressioni CEL.

Ad esempio, il seguente codice textproto dichiara un ambiente contenente le variabili request e now utilizzando il messaggio CompileRequest da un servizio CEL.

Esempio di dichiarazione dell'ambiente 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" }
  }
}

Le dichiarazioni basate su proto vengono utilizzate dal controllo dei tipi CEL per garantire che tutti i riferimenti a identificatori e funzioni all'interno di un'espressione vengano dichiarati e utilizzati correttamente.

Fasi di elaborazione dell'espressione

Le espressioni CEL vengono elaborate in tre fasi:

  1. Analizza
  2. Controllo
  3. Valuta

Il pattern più comune di utilizzo della tecnologia CEL consiste nell'analizzare e verificare le espressioni in fase di configurazione, archiviare l'AST e quindi recuperarlo e valutarlo ripetutamente in fase di runtime.

Illustrazione delle fasi di elaborazione CEL

Le espressioni vengono analizzate e controllate nei percorsi di configurazione, archiviate e poi valutate in base a uno o più contesti sui percorsi di lettura.

Il CEL viene analizzato da un'espressione leggibile a un AST utilizzando una grammatica lexer e dell'analizzatore sintattico ANTLR. La fase di analisi emette un AST basato su proto in cui ogni nodo Expr nell'AST contiene un ID numero intero che viene utilizzato per l'indicizzazione nei metadati generati durante l'analisi e il controllo. Il file syntax.proto prodotto durante l'analisi rappresenta la rappresentazione astratta di ciò che è stato digitato nella stringa dell'espressione.

Una volta analizzata, l'espressione viene sottoposta a controllo del tipo rispetto all'ambiente per garantire che tutti gli identificatori di variabili e funzioni nell'espressione siano stati dichiarati e vengano utilizzati correttamente. Il controllo dei tipi produce un file checked.proto che include metadati di tipo, variabile e risoluzione delle funzioni che possono migliorare drasticamente l'efficienza della valutazione.

Infine, dopo l'analisi e il controllo di un'espressione, viene valutato l'AST archiviato.

Il responsabile della valutazione CEL ha bisogno di tre aspetti:

  • Associazioni di funzioni per qualsiasi estensione personalizzata
  • Associazioni di variabili
  • Un AST da valutare

Le associazioni di funzioni e variabili devono corrispondere a quelle utilizzate per compilare l'AST. Ognuno di questi input può essere riutilizzato in più valutazioni, ad esempio un AST valutato in molti insiemi di associazioni di variabili, le stesse variabili utilizzate per molte AST o le associazioni di funzioni utilizzate per tutta la durata di un processo (caso comune).