Questo è un problema difficile: come può essere eseguito in modo sicuro tale codice fornito dall'utente e come è possibile garantire una buona esperienza utente?
Se esegui il codice per conto di qualcun altro, non ti puoi fidare di quel codice . Il codice può tentare di manipolare le risorse di elaborazione (quindi incorrere in costi per te e negare risorse di calcolo ad altri offerenti), può tentare di hackerare il tuo sistema o il codice di altri offerenti o semplicemente utilizzare le risorse di calcolo fornite come parte di una botnet ... le possibilità di abuso sono infinite. Quindi è necessario sandbox questo codice molto strettamente. Il modello di sicurezza Java è un buon inizio e consente di negare la riflessione e altre API al codice non attendibile. Tuttavia, potresti comunque trovare difficoltà a limitare in modo affidabile le risorse di calcolo disponibili.
Il prossimo problema è l'esperienza dell'utente. Come possono gli utenti scrivere, eseguire il debug e testare il loro codice? Fornirai una sorta di IDE? Quali API offri a quel codice? Come è documentato? Esiste un ambiente di test in cui è possibile provare le strategie di offerta? Come raccoglierai e visualizzerai i messaggi di errore?
Se compili il codice Java , sei limitato dal modello di sicurezza Java. Questo può essere effettivamente sufficiente, supponendo che tu sia competente con quel modello di sicurezza (non lo sono) e puoi configurarlo in modo appropriato. Puoi facilmente memorizzare nella cache il codice compilato , in modo che non debba essere ricompilato per ogni esecuzione. Ci sono strumenti maturi su Java, quindi sarebbe semplice offrire un tipo di IDE.
Se utilizzi qualsiasi altra lingua basata su JVM come Groovy, valgono le stesse considerazioni. Alla fine, tutto andrà come bytecode JVM e sarà quindi ragionevolmente veloce.
Se integri un linguaggio di scripting non JVM (una lingua esistente come JavaScript o una DSL di tua progettazione), allora hai più controllo sul confine di sicurezza tra il tuo codice e il non sicuro codice utente Tuttavia, questo potrebbe essere un po 'più lento. In particolare, l'implementazione della propria DSL è solitamente piuttosto soggetta a errori e spesso lenta.
Se una sandbox in-process non è sufficiente per le proprie esigenze, considerare sandbox a livello di processo o di sistema operativo: containerizzazione e virtualizzazione. esegui il codice utente in un processo separato e comunichi tramite un socket. Questo non solo migliora la sicurezza, ma consente anche una maggiore scalabilità. Tuttavia, qualsiasi input / output deve essere serializzato, il che può limitare le prestazioni.
Invece di creare un DSL testuale, puoi anche progettare un motore di regole . Fondamentalmente, si forniscono blocchi configurabili che gli utenti possono combinare in una GUI. Questo è più accessibile ai non programmatori. Offrendo o non offrendo determinati blocchi (come loop, dichiarazioni di funzioni, ...) è possibile influenzare il costo dei programmi risultanti, pur offrendo una maggiore flessibilità rispetto a una serie di strategie preconfigurate. Mentre controlli tutti i blocchi disponibili, puoi anche creare un chiaro limite di sicurezza senza dover utilizzare complicate funzionalità di isolamento.
A meno che le tue offerte non siano state risolte in pochi secondi, esiste un'altra opzione: offrire un'API REST . In questo modo, non devi eseguire alcun codice non affidabile. Esistono strumenti molto maturi per la creazione di API. C'è un confine di sicurezza molto chiaro. Puoi facilmente limitare gli utenti in eccesso. Con un'API, gli utenti possono iscriversi a un feed di eventi e reagire inviando le loro azioni ai tuoi endpoint API. Sono quindi totalmente liberi nel modo in cui scrivono le loro strategie. Tuttavia, dovranno fornire le proprie risorse di calcolo. Se questa è un'alternativa valida dipende in gran parte dal tuo mercato: il tuo prodotto è destinato ai consumatori, oppure è B2B o per sviluppatori?
Tuttavia, qualunque sia la tua scelta, altre considerazioni come l'offerta di un ambiente di test utilizzabile possono essere molto più complicate rispetto alla semplice integrazione di un linguaggio di scripting o all'offerta di un'API.
Suggerirei di porsi e / o chiarire con le parti interessate:
- Che tipo di flessibilità è necessaria e quali sono le possibilità di abuso con quella flessibilità?
- È sufficiente un motore di regole per fornire la flessibilità necessaria?
- In caso contrario, un'API sarebbe appropriata?
- In caso contrario, quale linguaggio di programmazione / scripting sarebbe la migliore esperienza utente? Per esempio. Java, Groovy, JavaScript o un DSL personalizzato? Molti problemi di prestazioni possono essere risolti buttando soldi sul problema (usando più server), quindi le prestazioni non dovrebbero essere la tua prima considerazione qui.