Skip to content

Commit

Permalink
Fix JENKINS-15213
Browse files Browse the repository at this point in the history
Allow administrator to enable security for pre-send scripts. This is a
breaking change for current pre-send scripts.
  • Loading branch information
slide committed Dec 11, 2012
1 parent 58a8ce0 commit 062f768
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 10 deletions.
46 changes: 36 additions & 10 deletions src/main/java/hudson/plugins/emailext/ExtendedEmailPublisher.java
Expand Up @@ -348,23 +348,49 @@ private boolean sendMail(EmailType mailType, AbstractBuild<?, ?> build, BuildLis
debug(listener.getLogger(), "Some error occured trying to send the email...check the Jenkins log");
return false;
}

private class PresendScriptManager {
private AbstractBuild<?, ?> build;
private boolean enableSecurity;

public PresendScriptManager(AbstractBuild<?, ?> build, boolean enableSecurity) {
this.build = build;
this.enableSecurity = enableSecurity;
}

public Jenkins getJenkins() {
if (enableSecurity) {
throw new SecurityException("access to 'jenkins' is denied by global config");
}
return Jenkins.getInstance();
}

public Hudson getHudson() {
if (enableSecurity) {
throw new SecurityException("access to 'hudson' is denied by global config");
}
return Hudson.getInstance();
}

public AbstractBuild<?, ?> getBuild() {
if (enableSecurity) {
throw new SecurityException("access to 'build' is denied by global config");
}
return build;
}
}

private boolean executePresendScript(AbstractBuild<?, ?> build, BuildListener listener, MimeMessage msg)
throws RuntimeException {
boolean cancel = false;
if(StringUtils.isNotBlank(presendScript)) {
listener.getLogger().println("Executing pre-send script");
CompilerConfiguration cc = new CompilerConfiguration();
cc.addCompilationCustomizers(new ImportCustomizer().addStarImports(
"jenkins",
"jenkins.model",
"hudson",
"hudson.model"));
ClassLoader cl = Jenkins.getInstance().getPluginManager().uberClassLoader;
GroovyShell shell = new GroovyShell(cl,new Binding(),cc);
GroovyShell shell = new GroovyShell(cl);
StringWriter out = new StringWriter();
PrintWriter pw = new PrintWriter(out);
shell.setVariable("build", build);
PresendScriptManager manager = new PresendScriptManager(build, ExtendedEmailPublisher.DESCRIPTOR.isSecurityEnabled());
shell.setVariable("manager", manager);
shell.setVariable("msg", msg);
shell.setVariable("logger", listener.getLogger());
shell.setVariable("cancel", cancel);
Expand All @@ -375,6 +401,8 @@ private boolean executePresendScript(AbstractBuild<?, ?> build, BuildListener li
cancel = ((Boolean)shell.getVariable("cancel")).booleanValue();
debug(listener.getLogger(), "Pre-send script set cancel to %b", cancel);
}
} catch (SecurityException e) {
listener.getLogger().println("Pre-send script tried to access secured objects: " + e.getMessage());
} catch (Throwable t) {
t.printStackTrace(pw);
listener.getLogger().println(out.toString());
Expand Down Expand Up @@ -515,15 +543,13 @@ private MimeMessage createMail(EmailType type, AbstractBuild<?, ?> build, BuildL
Set<InternetAddress> replyToAddresses = new LinkedHashSet<InternetAddress>();
if (StringUtils.isNotBlank(replyTo)) {
addAddressesFromRecipientList(replyToAddresses, null, getRecipientList(type, build, replyTo, listener, charset), env, listener);

}

if (StringUtils.isNotBlank(type.getReplyTo())) {
addAddressesFromRecipientList(replyToAddresses, null, getRecipientList(type, build, type.getReplyTo(), listener, charset), env, listener);
}

if(replyToAddresses.size() > 0) {
debug(listener.getLogger(), "replyToAddresses.size() = " + replyToAddresses.size());
msg.setReplyTo(replyToAddresses.toArray(new InternetAddress[replyToAddresses.size()]));
}

Expand Down
Expand Up @@ -121,6 +121,8 @@ public class ExtendedEmailPublisherDescriptor extends BuildStepDescriptor<Publis

private boolean debugMode;

private boolean enableSecurity;

@Override
public String getDisplayName() {
return Messages.ExtendedEmailPublisherDescriptor_DisplayName();
Expand Down Expand Up @@ -258,6 +260,10 @@ public String getDefaultReplyTo() {
return defaultReplyTo;
}

public boolean isSecurityEnabled() {
return enableSecurity;
}

public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
Expand Down Expand Up @@ -384,6 +390,7 @@ public boolean configure(StaplerRequest req, JSONObject formData)
req.getParameter("ext_mailer_default_recipients") : "";

precedenceBulk = req.getParameter("extmailer.addPrecedenceBulk") != null;
enableSecurity = req.getParameter("extmailer.enableSecurity") != null;

// specify List-ID information
if (req.getParameter("extmailer.useListID") != null) {
Expand Down Expand Up @@ -446,6 +453,10 @@ public boolean isDebugMode() {
return debugMode;
}

public void setDebugMode(boolean debugMode) {
this.debugMode = debugMode;
}

public void debug(PrintStream logger, String format, Object... args) {
if(debugMode) {
logger.format(format, args);
Expand Down
Expand Up @@ -117,6 +117,9 @@
<f:optionalBlock name="ext_mailer_debug_mode" title="${%Enable Debug Mode}" checked="${descriptor.isDebugMode()}"
help="/plugin/email-ext/help/globalConfig/debugMode.html">
</f:optionalBlock >
<f:optionalBlock name="ext_mailer_security_enabled" title="${%Enable Security}" checked="${descriptor.isSecurityEnabled()}"
help="/plugin/email-ext/help/globalConfig/security.html">
</f:optionalBlock>
<!-- This is the help section. It displays a bunch of dynamic help for all content tokens. -->
<tr>
<td></td>
Expand Down
6 changes: 6 additions & 0 deletions src/main/webapp/help/globalConfig/security.html
@@ -0,0 +1,6 @@
<div>
<p>
When enabled, it removes the ability for pre-send scripts to directly access the Jenkins instance. A security exception will be thrown
if the user tries to access the Jenkins instance of the manager object.
</p>
</div>

0 comments on commit 062f768

Please sign in to comment.