Skip to content
Permalink
Browse files

Fix JENKINS-13119

  • Loading branch information
gboissinot committed Mar 18, 2012
1 parent efbc513 commit 257acc17f1ae1560f95270d1c24aebc6b60d0261
@@ -22,7 +22,7 @@

@Override
public EnvInjectBuildWrapper getEnvInjectBuildWrapper() {
EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(filePath, null, null, null, false);
EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(filePath, null, null, null, null, false);
EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper();
envInjectBuildWrapper.setInfo(jobPropertyInfo);
return envInjectBuildWrapper;
@@ -22,7 +22,7 @@

@Override
public EnvInjectBuildWrapper getEnvInjectBuildWrapper() {
EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, localVarText, null, null, false);
EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, localVarText, null, null, null, false);
EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper();
envInjectBuildWrapper.setInfo(jobPropertyInfo);
return envInjectBuildWrapper;
@@ -10,13 +10,15 @@

private String scriptFilePath;
private String scriptContent;
private String groovyScriptContent;
private boolean loadFilesFromMaster;

@DataBoundConstructor
public EnvInjectJobPropertyInfo(String propertiesFilePath, String propertiesContent, String scriptFilePath, String scriptContent, boolean loadFilesFromMaster) {
public EnvInjectJobPropertyInfo(String propertiesFilePath, String propertiesContent, String scriptFilePath, String scriptContent, String groovyScriptContent, boolean loadFilesFromMaster) {
super(propertiesFilePath, propertiesContent);
this.scriptFilePath = Util.fixEmpty(scriptFilePath);
this.scriptContent = Util.fixEmpty(scriptContent);
this.groovyScriptContent = Util.fixEmpty(groovyScriptContent);
this.loadFilesFromMaster = loadFilesFromMaster;
}

@@ -28,6 +30,10 @@ public String getScriptContent() {
return scriptContent;
}

public String getGroovyScriptContent() {
return groovyScriptContent;
}

public boolean isLoadFilesFromMaster() {
return loadFilesFromMaster;
}
@@ -34,6 +34,7 @@
public Environment setUpEnvironment(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
if (!(build instanceof MatrixBuild)) {
EnvInjectLogger logger = new EnvInjectLogger(listener);
logger.info("Preparing an environment for the build.");
try {

//Process environment variables at node level
@@ -44,7 +45,7 @@ public Environment setUpEnvironment(AbstractBuild build, Launcher launcher, Buil

//Load job envinject job property
if (isEnvInjectJobPropertyActive(build)) {
return setUpEnvironmentRun(build, launcher, listener);
return setUpEnvironmentJobPropertyObject(build, launcher, listener);
}
} catch (Run.RunnerAbortedException rre) {
logger.info("Fail the build.");
@@ -194,7 +195,7 @@ public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener l
}
}

private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, EnvInjectException {
private Environment setUpEnvironmentJobPropertyObject(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, EnvInjectException {

EnvInjectVariableGetter variableGetter = new EnvInjectVariableGetter();
EnvInjectJobProperty envInjectJobProperty = variableGetter.getEnvInjectJobProperty(build);
@@ -203,7 +204,6 @@ private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher,
assert envInjectJobProperty != null && envInjectJobProperty.isOn();

EnvInjectLogger logger = new EnvInjectLogger(listener);
logger.info("Preparing an environment for the job.");

//Init infra env vars
Map<String, String> previousEnvVars = variableGetter.getEnvVarsPreviousSteps(build, logger);
@@ -246,6 +246,9 @@ private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher,
throw new Run.RunnerAbortedException();
}

//Evaluate Groovy script
Map<String, String> groovyMapEnvVars = envInjectEnvVarsService.executeAndGetMapGroovyScript(info.getGroovyScriptContent(), infraEnvVarsNode);

final Map<String, String> propertiesVariables = envInjectEnvVarsService.getEnvVarsPropertiesJobProperty(rootPath,
logger, info.isLoadFilesFromMaster(),
info.getPropertiesFilePath(), info.getPropertiesContentMap(),
@@ -254,7 +257,11 @@ private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher,
//Get variables get by contribution
Map<String, String> contributionVariables = getEnvVarsByContribution(build, envInjectJobProperty, listener);

final Map<String, String> resultVariables = envInjectEnvVarsService.getMergedVariables(infraEnvVarsNode, contributionVariables, propertiesVariables);
final Map<String, String> resultVariables = envInjectEnvVarsService.getMergedVariables(
infraEnvVarsNode,
propertiesVariables,
groovyMapEnvVars,
contributionVariables);

//Add an action
new EnvInjectActionSetter(rootPath).addEnvVarsToEnvInjectBuildAction(build, resultVariables);
@@ -324,26 +331,6 @@ private void injectPasswords(AbstractBuild build, EnvInjectJobProperty envInject
result.put("JENKINS_HOME", Hudson.getInstance().getRootDir().getPath());
result.put("HUDSON_HOME", Hudson.getInstance().getRootDir().getPath()); // legacy compatibility

//Global properties
for (NodeProperty<?> nodeProperty : Hudson.getInstance().getGlobalNodeProperties()) {
if (nodeProperty instanceof EnvironmentVariablesNodeProperty) {
EnvironmentVariablesNodeProperty environmentVariablesNodeProperty = (EnvironmentVariablesNodeProperty) nodeProperty;
result.putAll(environmentVariablesNodeProperty.getEnvVars());
}
}

//Node properties
if (computer != null) {
Node node = computer.getNode();
if (node != null) {
for (NodeProperty<?> nodeProperty : node.getNodeProperties()) {
if (nodeProperty instanceof EnvironmentVariablesNodeProperty) {
EnvironmentVariablesNodeProperty environmentVariablesNodeProperty = (EnvironmentVariablesNodeProperty) nodeProperty;
result.putAll(environmentVariablesNodeProperty.getEnvVars());
}
}
}
}
return result;
}

@@ -1,5 +1,6 @@
package org.jenkinsci.plugins.envinject.service;

import groovy.lang.GroovyShell;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
@@ -87,6 +88,38 @@ public int executeScript(boolean loadFromMaster,
}
}

public Map<String, String> executeAndGetMapGroovyScript(String scriptContent, Map<String, String> envVars) throws EnvInjectException {

if (scriptContent == null) {
return new HashMap<String, String>();
}

if (scriptContent.trim().length() == 0) {
return new HashMap<String, String>();
}

logger.info(String.format("Evaluation the following Groovy script content: \n%s\n", scriptContent));
GroovyShell shell = new GroovyShell();
for (Map.Entry<String, String> entryVariable : envVars.entrySet()) {
shell.setVariable(entryVariable.getKey(), entryVariable.getValue());
}
Object groovyResult = shell.evaluate(scriptContent);
if (groovyResult != null && !(groovyResult instanceof Map)) {
throw new EnvInjectException("The evaluated Groovy script must return a Map object.");
}

Map<String, String> result = new HashMap<String, String>();
if (groovyResult == null) {
return result;
}

for (Map.Entry entry : (((Map<Object, Object>) groovyResult).entrySet())) {
result.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}
return result;

}

This comment has been minimized.

Copy link
@ndeloof

ndeloof Apr 24, 2013

Member

This method need to check for RUN_SCRIPT permission, as this code is ran on jenkins master: a malicious user with Job.CONFIGURE could set groovy script to access Jenkins.instance.XXX and bypass security

public int executeScript(
String scriptContent,
FilePath scriptExecutionRoot,
@@ -101,21 +134,26 @@ public int executeScript(
}

public Map<String, String> getMergedVariables(Map<String, String> infraEnvVars, Map<String, String> propertiesEnvVars) {
return getMergedVariables(infraEnvVars, new HashMap<String, String>(), propertiesEnvVars);
return getMergedVariables(infraEnvVars, propertiesEnvVars, new HashMap<String, String>(), new HashMap<String, String>());
}

public Map<String, String> getMergedVariables(Map<String, String> infraEnvVars,
Map<String, String> contribEnvVars,
Map<String, String> propertiesEnvVars) {
Map<String, String> propertiesEnvVars,
Map<String, String> groovyMapEnvVars,
Map<String, String> contribEnvVars) {

//1--Resolve properties against infraEnvVars
resolveVars(propertiesEnvVars, infraEnvVars);

//2--Resolve properties against contribEnvVars
//2--Resolve properties against groovyEnvVars
resolveVars(propertiesEnvVars, groovyMapEnvVars);

//3--Resolve properties against contribEnvVars
resolveVars(propertiesEnvVars, contribEnvVars);

//3-- Get All variables in order (infraEnvVars, contribEnvVars, properties)
//4-- Get All variables in order (infraEnvVars, groovyEnvVars, contribEnvVars, properties)
Map<String, String> variables = new LinkedHashMap<String, String>(infraEnvVars);
variables.putAll(groovyMapEnvVars);
variables.putAll(contribEnvVars);
variables.putAll(propertiesEnvVars);

@@ -53,6 +53,7 @@ public int executeScriptSection(FilePath scriptExecutionRoot,

}


return 0;
}

@@ -67,6 +67,13 @@
value="${instance.info.scriptContent}"/>
</f:entry>

<f:entry title="${%Evaluated Groovy script}"
help="/descriptor/org.jenkinsci.plugins.envinject.EnvInjectJobProperty/help/groovyScriptContent">
<f:textarea
name="envInjectInfoJobProperty.groovyScriptContent"
value="${instance.info.groovyScriptContent}"/>
</f:entry>

<f:entry
title="${%Properties File Path}"
help="/descriptor/org.jenkinsci.plugins.envinject.EnvInjectJobProperty/help/propertiesFilePath">
@@ -0,0 +1,27 @@
<div>
<p>
Evaluate a Groovy script and inject a map result.<br/>
The groovy script must return a map Java object.<br/>
You can access parameters and other environment variables through variables in the Groovy script.<br/>
For example, the Groovy can compute environment variables from user input parameters, such as:<br/>
<i>
if (CASE==null){<br/>
return null; <br/>
} <br/>

def stringValue="StRinG"; <br/>

if ("upper".equals(CASE)){ <br/>
def map = [COMPUTE_VAR: stringValue.toUpperCase()]<br/>
return map <br/>
} <br/>
<br/>
if ("lower".equals(CASE)){ <br/>
def map = [COMPUTE_VAR: stringValue.toLowerCase()] <br/>
return map <br/>
} <br/>
</i>
<br/>
This script injects the COMPUTE_VAR environment variable according the CASE parameter value.
</p>
</div>
@@ -1,6 +1,6 @@
<div>
<p>
Inject Jenkins build variables such as EXECUTOR_NUMBER, BUILD_ID, BUILD_TAG, JOB_NAME and so on.
Inject Jenkins build variables such as EXECUTOR_NUMBER, BUILD_ID, BUILD_TAG, JOB_NAME and so on.<br/>
Inject also environment contributors and build variable contributors provided by other plugins.
</p>
</div>
@@ -1,7 +1,8 @@
<div>
<p>
If this option is checked, Jenkins makes it possible to set an environment
for the build job (or for each run on a matrix project) by defining environment variables and execute a script (a setup script).<br/>
for the build job (or for each run on a matrix project) by defining environment variables and execute a script
(a setup script).<br/>
All these actions will be executed before a SCM checkout.<br/>
By default, after the set up, only injected variables (with Jenkins variables) will be available in the build
scripts, in the Jenkins post-actions, and so on. <br/>
@@ -28,7 +28,7 @@ public void testPropertiesContentCustomWorkspace() throws Exception {

String propertiesContent = customEnvVarName + "=" + customEnvVarValue;

EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, propertiesContent, null, null, false);
EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, propertiesContent, null, null, null, false);
EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper();
envInjectBuildWrapper.setInfo(jobPropertyInfo);
project.getBuildWrappersList().add(envInjectBuildWrapper);

0 comments on commit 257acc1

Please sign in to comment.
You can’t perform that action at this time.