提交 757bc8a5 编写于 作者: J Jesse Glick 提交者: Kohsuke Kawaguchi

[SECURITY-55]

This patch makes standard post-build action refuse to let you configure a downstream project you cannot currently build.
The one from parameterized-trigger will show an error in the configure screen but still lets you save the configuration; needs an analogous patch to that plugin.
Does not yet protect against POSTing config.xml with the trigger.
上级 aaf79ed3
...@@ -1794,6 +1794,13 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A ...@@ -1794,6 +1794,13 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
triggers = buildDescribable(req, Trigger.for_(this)); triggers = buildDescribable(req, Trigger.for_(this));
for (Trigger t : triggers) for (Trigger t : triggers)
t.start(this,true); t.start(this,true);
for (Publisher _t : Descriptor.newInstancesFromHeteroList(req, json, "publisher", Jenkins.getInstance().getExtensionList(BuildTrigger.DescriptorImpl.class))) {
BuildTrigger t = (BuildTrigger) _t;
for (AbstractProject downstream : t.getChildProjects(this)) {
downstream.checkPermission(BUILD);
}
}
} }
/** /**
......
...@@ -72,6 +72,7 @@ import java.lang.reflect.Type; ...@@ -72,6 +72,7 @@ import java.lang.reflect.Type;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.beans.Introspector; import java.beans.Introspector;
import javax.annotation.CheckForNull;
/** /**
* Metadata about a configurable instance. * Metadata about a configurable instance.
...@@ -909,7 +910,10 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable { ...@@ -909,7 +910,10 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable {
for (Object o : JSONArray.fromObject(formData)) { for (Object o : JSONArray.fromObject(formData)) {
JSONObject jo = (JSONObject)o; JSONObject jo = (JSONObject)o;
String kind = jo.getString("kind"); String kind = jo.getString("kind");
items.add(find(descriptors,kind).newInstance(req,jo)); Descriptor<T> d = find(descriptors, kind);
if (d != null) {
items.add(d.newInstance(req, jo));
}
} }
} }
...@@ -919,7 +923,7 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable { ...@@ -919,7 +923,7 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable {
/** /**
* Finds a descriptor from a collection by its class name. * Finds a descriptor from a collection by its class name.
*/ */
public static <T extends Descriptor> T find(Collection<? extends T> list, String className) { public static @CheckForNull <T extends Descriptor> T find(Collection<? extends T> list, String className) {
for (T d : list) { for (T d : list) {
if(d.getClass().getName().equals(className)) if(d.getClass().getName().equals(className))
return d; return d;
...@@ -933,7 +937,7 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable { ...@@ -933,7 +937,7 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable {
return null; return null;
} }
public static Descriptor find(String className) { public static @CheckForNull Descriptor find(String className) {
return find(Jenkins.getInstance().getExtensionList(Descriptor.class),className); return find(Jenkins.getInstance().getExtensionList(Descriptor.class),className);
} }
......
...@@ -318,7 +318,7 @@ public class BuildTrigger extends Recorder implements DependecyDeclarer { ...@@ -318,7 +318,7 @@ public class BuildTrigger extends Recorder implements DependecyDeclarer {
/** /**
* Form validation method. * Form validation method.
*/ */
public FormValidation doCheck(@AncestorInPath Item project, @QueryParameter String value ) { public FormValidation doCheck(@AncestorInPath Item project, @QueryParameter String value, @QueryParameter boolean upstream) {
// Require CONFIGURE permission on this project // Require CONFIGURE permission on this project
if(!project.hasPermission(Item.CONFIGURE)) return FormValidation.ok(); if(!project.hasPermission(Item.CONFIGURE)) return FormValidation.ok();
...@@ -333,6 +333,9 @@ public class BuildTrigger extends Recorder implements DependecyDeclarer { ...@@ -333,6 +333,9 @@ public class BuildTrigger extends Recorder implements DependecyDeclarer {
AbstractProject.findNearest(projectName,project.getParent()).getRelativeNameFrom(project))); AbstractProject.findNearest(projectName,project.getParent()).getRelativeNameFrom(project)));
if(!(item instanceof AbstractProject)) if(!(item instanceof AbstractProject))
return FormValidation.error(Messages.BuildTrigger_NotBuildable(projectName)); return FormValidation.error(Messages.BuildTrigger_NotBuildable(projectName));
if (!upstream && !item.hasPermission(Item.BUILD)) {
return FormValidation.error(Messages.BuildTrigger_you_have_no_permission_to_build_(projectName));
}
hasProjects = true; hasProjects = true;
} }
} }
......
...@@ -47,6 +47,7 @@ BuildTrigger.NoSuchProject=No such project ''{0}''. Did you mean ''{1}''? ...@@ -47,6 +47,7 @@ BuildTrigger.NoSuchProject=No such project ''{0}''. Did you mean ''{1}''?
BuildTrigger.NoProjectSpecified=No project specified BuildTrigger.NoProjectSpecified=No project specified
BuildTrigger.NotBuildable={0} is not buildable BuildTrigger.NotBuildable={0} is not buildable
BuildTrigger.Triggering=Triggering a new build of {0} BuildTrigger.Triggering=Triggering a new build of {0}
BuildTrigger.you_have_no_permission_to_build_=You have no permission to build {0}
CommandInterpreter.CommandFailed=command execution failed CommandInterpreter.CommandFailed=command execution failed
CommandInterpreter.UnableToDelete=Unable to delete script file {0} CommandInterpreter.UnableToDelete=Unable to delete script file {0}
......
...@@ -38,7 +38,7 @@ THE SOFTWARE. ...@@ -38,7 +38,7 @@ THE SOFTWARE.
<f:entry title="${%Projects names}" <f:entry title="${%Projects names}"
description="${%Multiple projects can be specified like 'abc, def'}"> description="${%Multiple projects can be specified like 'abc, def'}">
<f:textbox name="upstreamProjects" value="${h.getProjectListString(up)}" <f:textbox name="upstreamProjects" value="${h.getProjectListString(up)}"
checkUrl="'descriptorByName/hudson.tasks.BuildTrigger/check?value='+encodeURIComponent(this.value)" checkUrl="'descriptorByName/hudson.tasks.BuildTrigger/check?upstream=true&amp;value='+encodeURIComponent(this.value)"
autoCompleteField="upstreamProjects"/> autoCompleteField="upstreamProjects"/>
</f:entry> </f:entry>
</f:optionalBlock> </f:optionalBlock>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册