-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prototyping integration with Script Security plugin #28
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
#Friday July 28 02:39:00 EDT 2013 | ||
constructor=name,parentPropertyName,script,description,uuid,remote,readonlyInputField,classPath | ||
constructor=name,parentPropertyName,script,sandbox,description,uuid,remote,readonlyInputField,classPath | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,9 @@ | |
|
||
import org.apache.commons.lang.ObjectUtils; | ||
import org.apache.commons.lang.StringUtils; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; | ||
import org.jvnet.localizer.ResourceBundleHolder; | ||
import org.kohsuke.stapler.DataBoundConstructor; | ||
|
||
|
@@ -48,31 +51,46 @@ public class ChoiceParameterDefinition extends ScriptParameterDefinition | |
private final Boolean readonlyInputField; | ||
|
||
private String choiceType; | ||
|
||
@Deprecated | ||
public ChoiceParameterDefinition(String name, String script, String description, String uuid, | ||
Boolean remote, String classPath) | ||
{ | ||
this(name, script, description, uuid, remote, false, classPath, PARAMETER_TYPE_SINGLE_SELECT); | ||
} | ||
|
||
@Deprecated | ||
public ChoiceParameterDefinition(String name, String script, String description, String uuid, | ||
Boolean remote, Boolean readonlyInputField, String classPath, String choiceType) | ||
{ | ||
this(name, script, /* sandbox */ false, description, uuid, remote, readonlyInputField, classPath, choiceType); | ||
} | ||
|
||
/** | ||
* Constructor. | ||
* @param name parameter name | ||
* @param script script, which generates the parameter value | ||
* @param sandbox whether to execute the script in the security sandbox or not | ||
* @param description parameter description | ||
* @param uuid identifier (optional) | ||
* @param remote execute the script on a remote node | ||
* @param choiceType type of the choice (single, multi, etc.) to display | ||
*/ | ||
@DataBoundConstructor | ||
public ChoiceParameterDefinition(String name, String script, String description, String uuid, | ||
public ChoiceParameterDefinition(String name, String script, boolean sandbox, String description, String uuid, | ||
Boolean remote, Boolean readonlyInputField, String classPath, String choiceType) | ||
{ | ||
super(name, script, description, uuid, remote, classPath); | ||
super(name, script, sandbox, description, uuid, remote, classPath); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the super is calling configuring, but without checking for !sandbox |
||
this.readonlyInputField = readonlyInputField; | ||
this.choiceType = choiceType; | ||
} | ||
|
||
private Object readResolve() { | ||
if (!getSandbox()) { | ||
ScriptApproval.get().configuring(getScript(), GroovyLanguage.get(), ApprovalContext.create()); | ||
} | ||
return this; | ||
} | ||
|
||
/** | ||
* Return default parameter value - used by trigger mechanism. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
#Sun Sep 19 00:45:21 PDT 2010 | ||
constructor=name,script,description,uuid,remote,readonlyInputField,classPath | ||
constructor=name,script,sandbox,description,uuid,remote,readonlyInputField,classPath | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto here |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,14 +19,17 @@ | |
import hudson.model.AutoCompletionCandidates; | ||
import hudson.remoting.Callable; | ||
import hudson.remoting.VirtualChannel; | ||
import hudson.util.FormValidation; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
import org.apache.commons.lang.ArrayUtils; | ||
import org.apache.commons.lang.StringUtils; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; | ||
import org.kohsuke.stapler.QueryParameter; | ||
|
||
import com.seitenbau.jenkins.plugins.dynamicparameter.config.DynamicParameterConfiguration; | ||
|
@@ -50,6 +53,9 @@ public abstract class ScriptParameterDefinition extends BaseParameterDefinition | |
/** Script, which generates the parameter value. */ | ||
private final String _script; | ||
|
||
/** Security sandbox. */ | ||
private final boolean _sandbox; | ||
|
||
/** Local class path. */ | ||
private final FilePath _localBaseDirectory; | ||
|
||
|
@@ -58,24 +64,26 @@ public abstract class ScriptParameterDefinition extends BaseParameterDefinition | |
|
||
/** Class path. */ | ||
private final String _classPath; | ||
|
||
/** | ||
* Constructor. | ||
* @param name parameter name | ||
* @param script script, which generates the parameter value | ||
* @param whether to use the security sandbox or not | ||
* @param description parameter description | ||
* @param uuid identifier (optional) | ||
* @param remote execute the script on a remote node | ||
*/ | ||
protected ScriptParameterDefinition(String name, String script, String description, String uuid, | ||
protected ScriptParameterDefinition(String name, String script, boolean sandbox, String description, String uuid, | ||
Boolean remote, String classPath) | ||
{ | ||
super(name, description, uuid, remote); | ||
|
||
_localBaseDirectory = new FilePath(DynamicParameterConfiguration.INSTANCE.getBaseDirectoryFile()); | ||
_remoteBaseDirectory = DEFAULT_REMOTE_CLASSPATH; | ||
_classPath = classPath; | ||
_script = script; | ||
_script = ScriptApproval.get().configuring(script, GroovyLanguage.get(), ApprovalContext.create()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should pass in |
||
_sandbox = sandbox; | ||
} | ||
|
||
/** | ||
|
@@ -122,19 +130,24 @@ public final String[] getClassPathList() | |
{ | ||
return _classPath.split(CLASSPATH_SPLITTER); | ||
} | ||
|
||
public final boolean getSandbox() | ||
{ | ||
return _sandbox; | ||
} | ||
|
||
@Override | ||
protected ClasspathScriptCall prepareLocalCall(Map<String, String> parameters) | ||
{ | ||
ClasspathScriptCall call = new ClasspathScriptCall(getScript(), parameters, setupLocalClassPaths()); | ||
ClasspathScriptCall call = new ClasspathScriptCall(getScript(), parameters, setupLocalClassPaths(), getSandbox()); | ||
return call; | ||
} | ||
|
||
@Override | ||
protected ClasspathScriptCall prepareRemoteCall(VirtualChannel channel, Map<String, String> parameters) throws IOException, | ||
InterruptedException | ||
{ | ||
ClasspathScriptCall call = new ClasspathScriptCall(getScript(), parameters, setupRemoteClassPaths(channel)); | ||
ClasspathScriptCall call = new ClasspathScriptCall(getScript(), parameters, setupRemoteClassPaths(channel), getSandbox()); | ||
return call; | ||
} | ||
|
||
|
@@ -244,6 +257,10 @@ public static String[] splitClassPaths(String value) | |
return value.toLowerCase().split(CLASSPATH_SPLITTER); | ||
} | ||
} | ||
|
||
public FormValidation doCheckGroovyScript(@QueryParameter String value, @QueryParameter boolean sandbox) { | ||
return sandbox ? FormValidation.ok() : ScriptApproval.get().checking(value, GroovyLanguage.get()); | ||
} | ||
|
||
} | ||
|
||
|
@@ -259,23 +276,26 @@ public static final class ClasspathScriptCall implements Callable<Object, Throwa | |
private final Map<String, String> _parameters; | ||
|
||
private final FilePath[] _classPaths; | ||
|
||
private final boolean _sandbox; | ||
|
||
/** | ||
* Constructor. | ||
* @param script script to execute | ||
* @param classPaths class paths | ||
*/ | ||
public ClasspathScriptCall(String script, Map<String, String> parameters, FilePath[] classPaths) | ||
public ClasspathScriptCall(String script, Map<String, String> parameters, FilePath[] classPaths, boolean sandbox) | ||
{ | ||
_remoteScript = script; | ||
_parameters = parameters; | ||
_classPaths = classPaths; | ||
_sandbox = sandbox; | ||
} | ||
|
||
@Override | ||
public Object call() | ||
{ | ||
return JenkinsUtils.execute(_remoteScript, _parameters, _classPaths); | ||
return JenkinsUtils.execute(_remoteScript, _parameters, _classPaths, _sandbox); | ||
} | ||
|
||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
#Sun Sep 19 00:45:21 PDT 2010 | ||
constructor=name,script,description,remote,readonlyInputField,classPath | ||
constructor=name,script,sandbox,description,remote,readonlyInputField,classPath | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
*/ | ||
package com.seitenbau.jenkins.plugins.dynamicparameter.util; | ||
|
||
import groovy.lang.Binding; | ||
import groovy.lang.GroovyShell; | ||
import hudson.FilePath; | ||
import hudson.Plugin; | ||
|
@@ -41,6 +42,12 @@ | |
import org.codehaus.groovy.control.CompilerConfiguration; | ||
import org.jenkinsci.plugins.scriptler.config.Script; | ||
import org.jenkinsci.plugins.scriptler.config.ScriptlerConfiguration; | ||
import org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException; | ||
import org.jenkinsci.plugins.scriptsecurity.sandbox.Whitelist; | ||
import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; | ||
import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; | ||
|
||
import com.seitenbau.jenkins.plugins.dynamicparameter.BaseParameterDefinition; | ||
|
||
|
@@ -77,7 +84,7 @@ public static Object execute(String script) | |
public static Object execute(String script, Map<String, String> parameters) | ||
{ | ||
FilePath[] emptyClassPaths = new FilePath[]{}; | ||
return execute(script, parameters, emptyClassPaths); | ||
return execute(script, parameters, emptyClassPaths, /* sandbox */ false); | ||
} | ||
|
||
/** | ||
|
@@ -87,11 +94,18 @@ public static Object execute(String script, Map<String, String> parameters) | |
* @param classPaths class paths | ||
* @return result from the script | ||
*/ | ||
public static Object execute(String script, Map<String, String> parameters, FilePath[] classPaths) | ||
public static Object execute(final String script, Map<String, String> parameters, FilePath[] classPaths, boolean sandbox) | ||
{ | ||
try | ||
{ | ||
CompilerConfiguration config = new CompilerConfiguration(); | ||
CompilerConfiguration config; | ||
|
||
if (sandbox) { | ||
config = GroovySandbox.createSecureCompilerConfiguration(); | ||
} | ||
else { | ||
config = new CompilerConfiguration(); | ||
} | ||
|
||
// set class path | ||
ArrayList<String> classPathList = new ArrayList<String>(classPaths.length); | ||
|
@@ -113,25 +127,57 @@ public static Object execute(String script, Map<String, String> parameters, File | |
logger.log(Level.INFO, "Cannot access path", exp); | ||
} | ||
config.setClasspathList(classPathList); | ||
GroovyShell groovyShell = new GroovyShell(config); | ||
|
||
Binding binding = new Binding(); | ||
for (Entry<String, String> parameter : parameters.entrySet()) | ||
{ | ||
groovyShell.setVariable(parameter.getKey(), parameter.getValue()); | ||
binding.setVariable(parameter.getKey(), parameter.getValue()); | ||
} | ||
|
||
// execute script | ||
Object evaluate = groovyShell.evaluate(script); | ||
final Object evaluate; | ||
if (sandbox) { | ||
final GroovyShell groovyShell = new GroovyShell(binding, config); | ||
MyRunnable r = new MyRunnable(groovyShell, script); | ||
GroovySandbox.runInSandbox(r, Whitelist.all()); | ||
evaluate = r.getEvaluated(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding a
|
||
} else { | ||
evaluate = new GroovyShell(binding, config).evaluate(ScriptApproval.get().using(script, GroovyLanguage.get())); | ||
} | ||
|
||
return evaluate; | ||
} | ||
catch (Exception e) | ||
{ | ||
logger.log(Level.SEVERE, "Cannot access class path", e); | ||
if (e instanceof RejectedAccessException) { | ||
ScriptApproval.get().accessRejected((RejectedAccessException) e, ApprovalContext.create()); | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
private static final class MyRunnable implements Runnable { | ||
|
||
private Object evaluated; | ||
private GroovyShell groovyShell; | ||
private String script; | ||
|
||
public MyRunnable(GroovyShell groovyShell, String script) { | ||
this.groovyShell = groovyShell; | ||
this.script = script; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
evaluated = groovyShell.evaluate(script); | ||
} | ||
|
||
public Object getEvaluated() { | ||
return evaluated; | ||
} | ||
} | ||
|
||
/** | ||
* Check if a plugin is available. | ||
* @param shortName plugin short name | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should never have been placed into source control to begin with.
*.stapler
files are generated as a build product.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I had never seen *.stapler files in plug-ins before so I assumed I should try to modify it accordingly.