User story #8629
closedAllows generation-time javascript eval in directive parameters
Description
Some times, we want to make little transformation in user input before using it.
Typically, we want to use the node hostname, but actually just the hostname (not the full FQDN), and capitalize.
Or we want to take only the first char group of node UUID.
Or we want to hash some text in sha512 to sign something, and the text must containt the node ip.
Or whatever.
Today, these use case can only be done with a script on the node and a CFEngine variable definition. Not only these is cumbersome, sometimes it is NOT what we want. In particular in the case of the hash, we don't want to give admin of the node (or other people having read access to that information) hint about how the hash is built.
So, the goal is to provide a generic scripting langage (a subset of a well know one - js) to allows text manipulation, and have the eval done when we have node contextual information (id, properties, etc) available.
Of course, we must be careful about performance, error reporting, syntaxe.
Finally, we propose to put the feature available in 3.1 BEHIND a feature switch, so that people can try the feature in current long term supported version, but so that nothing change by default for other.
Updated by François ARMAND over 8 years ago
- Status changed from New to In progress
Updated by François ARMAND over 8 years ago
So, sandboxing JS SCripting engine is hard.
For reference, we want to prevents two majors kinds of issues:
- accessing JVM resources / java objects. Typically, we don't really want that the user is able to
rm -rf /from a directive parameter script. This one is trivial, but anything from net to changing classloader or permission / securityManager must be disallowed. See https://tersesystems.com/2015/12/29/sandbox-experiment/ for more insight on that point.
- avoiding that a "while(true){}" (or a less evident infinite loop) block Rudder forever, and free the corresponding Thread resources afterward.
Both are tricky, because you can't easily or without risk kill threads on java, and sandboxing them is non trivial at all. Here are some reference linkgs:
http://stackoverflow.com/questions/32520413/scriptengine-clear-and-dispose
http://stackoverflow.com/questions/20793089/secure-nashorn-js-execution
http://stackoverflow.com/questions/1347099/how-do-i-secure-scripts-run-using-javax-scripting
http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/
http://stackoverflow.com/questions/24466203/how-to-remove-java-apis-from-nashorn-engine
http://calumleslie.blogspot.fr/2008/06/simple-jvm-sandboxing.html
http://stackoverflow.com/questions/3947558/java-security-sandboxing-plugins-loaded-via-urlclassloader
http://stackoverflow.com/questions/24855182/interrupt-java-thread-running-nashorn-script
Updated by François ARMAND over 8 years ago
Oh, and to make everything nicer, there is two JsEngine in Java: Rhino for JVM 6 & 7, Nashorn for JVM 8. So we can't even say we are just going to use some dedicated feature of one or the other, because it would imply a different jar for Java 7 and Java 8, and we certainly DON'T want that.
And it is impossible to make Nashorn works on Java 7 or earlier (it uses JVM 8 dedicated features), nor it is affordable to use Rhino in Java 8 (it is possible, but complex, fragile, a maintenance nightmare).
So we are stuck with thread level sandboxing and time-outing.
Updated by Benoît PECCATTE over 8 years ago
I reiterate my suggestion to use lua instead.
LUA has been invented to be small, embeddable and easy to use. Which means:
- runs in the jvm directly (easy to integrate, and integrated sandboxing)
- can only cal functions exported to it (natural sandboxing)
- easy to learn since it looks like other languages
Updated by François ARMAND over 8 years ago
I think that js is just more widespread: there is more doc, there is a higher chance people using Rudder had already been exposed to it, and there is a higher chance that the syntaxe is already barelly knows. All of that doesn't hold for lua.
An idea: we could make the keyword for "this is a script" ($eval today) could be $evaljs. So that let open doors to other lang in the future (and that let the user little doubt about what he should use).
Updated by Benoît PECCATTE over 8 years ago
Most of the code users will write will be one liners, ie : function call, math expression, variable access. Those have the same syntax in js as in lua.
Updated by François ARMAND over 8 years ago
- Status changed from In progress to Pending technical review
- Assignee changed from François ARMAND to Vincent MEMBRÉ
- Pull Request set to https://github.com/Normation/rudder/pull/1141
Updated by Nicolas CHARLES over 8 years ago
- Pull Request changed from https://github.com/Normation/rudder/pull/1141 to https://github.com/Normation/rudder/pull/1144
Updated by Nicolas CHARLES over 8 years ago
Updated by Nicolas CHARLES over 8 years ago
- Assignee changed from Vincent MEMBRÉ to François ARMAND
Updated by François ARMAND over 8 years ago
- Status changed from Pending technical review to Pending release
- % Done changed from 0 to 100
Applied in changeset rudder|9586bcd0b219b93556424e6c5c956375729fbee4.
Updated by Alexis Mousset over 8 years ago
- Status changed from Pending release to Released
This bug has been fixed in Rudder 3.1.12 and 3.2.5 which were released today.
- 3.1: Announce Changelog
- 3.2: Announce Changelog
- Download: https://www.rudder-project.org/site/get-rudder/downloads/
Updated by Alexis Mousset over 8 years ago
- Related to Bug #8801: Inconsistent hashing algorithms used in passwords generated in the script engine added
Updated by François ARMAND about 8 years ago
- Related to Bug #8857: Some Javascript engine fails when accessing system values added
Updated by François ARMAND about 8 years ago
- Related to Bug #8936: JS scripting engine is broken with IBM JDK 7 (and 8) added
Updated by Benoît PECCATTE over 7 years ago
- Related to Bug #9190: Script evaluation is not limited to password fields anymore added
Updated by Benoît PECCATTE over 7 years ago
- Related to User story #6264: Get directive parameter value from external source (kv store, rest, etc) added
Updated by Benoît PECCATTE over 7 years ago
- Related to User story #3380: Add ace.js library added