From b5c3764681f3b4ce83d0e78f6a9327925640d57e Mon Sep 17 00:00:00 2001 From: Kevin-CB Date: Tue, 21 Dec 2021 13:22:35 +0000 Subject: [PATCH 01/12] [SECURITY-2558] --- .../hudson/model/BuildAuthorizationToken.java | 4 -- .../hudson/model/AbstractProjectTest.java | 12 +++- .../BuildAuthorizationTokenSEC2558Test.java | 70 +++++++++++++++++++ .../model/ParameterizedJobMixInTest.java | 19 ++++- 4 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 test/src/test/java/hudson/model/BuildAuthorizationTokenSEC2558Test.java diff --git a/core/src/main/java/hudson/model/BuildAuthorizationToken.java b/core/src/main/java/hudson/model/BuildAuthorizationToken.java index 43563b6f4611..5ab6283cfbb4 100644 --- a/core/src/main/java/hudson/model/BuildAuthorizationToken.java +++ b/core/src/main/java/hudson/model/BuildAuthorizationToken.java @@ -28,7 +28,6 @@ import hudson.security.ACL; import java.io.IOException; import javax.servlet.http.HttpServletResponse; -import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.StaplerRequest; @@ -67,9 +66,6 @@ public static BuildAuthorizationToken create(StaplerRequest req) { } public static void checkPermission(Job project, BuildAuthorizationToken token, StaplerRequest req, StaplerResponse rsp) throws IOException { - if (!Jenkins.get().isUseSecurity()) - return; // everyone is authorized - if(token!=null && token.token != null) { //check the provided token String providedToken = req.getParameter("token"); diff --git a/test/src/test/java/hudson/model/AbstractProjectTest.java b/test/src/test/java/hudson/model/AbstractProjectTest.java index 5457cdfc1307..5d5858cf1ae2 100644 --- a/test/src/test/java/hudson/model/AbstractProjectTest.java +++ b/test/src/test/java/hudson/model/AbstractProjectTest.java @@ -355,17 +355,23 @@ public void queueSuccessBehaviorOverHTTP() throws Exception { JenkinsRule.WebClient wc = j.createWebClient() .withThrowExceptionOnFailingStatusCode(false); - WebResponse rsp = wc.goTo(p.getUrl() + "build", null).getWebResponse(); + WebResponse rsp = wc.getPage(wc.addCrumb(new WebRequest(new URL(j.getURL(),p.getUrl() + + "build?delay=0") + ,HttpMethod.POST))).getWebResponse(); assertEquals(HttpURLConnection.HTTP_CREATED, rsp.getStatusCode()); assertNotNull(rsp.getResponseHeaderValue("Location")); - WebResponse rsp2 = wc.goTo(p.getUrl() + "build", null).getWebResponse(); + WebResponse rsp2 = wc.getPage(wc.addCrumb(new WebRequest(new URL(j.getURL(),p.getUrl() + + "build?delay=0") + ,HttpMethod.POST))).getWebResponse(); assertEquals(HttpURLConnection.HTTP_CREATED, rsp2.getStatusCode()); assertEquals(rsp.getResponseHeaderValue("Location"), rsp2.getResponseHeaderValue("Location")); p.makeDisabled(true); - WebResponse rsp3 = wc.goTo(p.getUrl() + "build", null).getWebResponse(); + WebResponse rsp3 = wc.getPage(wc.addCrumb(new WebRequest(new URL(j.getURL(),p.getUrl() + + "build?delay=0") + ,HttpMethod.POST))).getWebResponse(); assertEquals(HttpURLConnection.HTTP_CONFLICT, rsp3.getStatusCode()); } diff --git a/test/src/test/java/hudson/model/BuildAuthorizationTokenSEC2558Test.java b/test/src/test/java/hudson/model/BuildAuthorizationTokenSEC2558Test.java new file mode 100644 index 000000000000..6b4e2fe66d4d --- /dev/null +++ b/test/src/test/java/hudson/model/BuildAuthorizationTokenSEC2558Test.java @@ -0,0 +1,70 @@ +package hudson.model; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.junit.Assert.assertThrows; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.HttpMethod; +import com.gargoylesoftware.htmlunit.WebRequest; +import java.lang.reflect.Field; +import java.net.URL; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.Issue; +import org.jvnet.hudson.test.JenkinsRule; + +// The existing @Before is annoying so this class is independent +// TODO : Using @Nested class could be more clean than using separate class +// TODO : Merge back into BuildAuthorizationTokenTest +public class BuildAuthorizationTokenSEC2558Test { + + @Rule + public JenkinsRule jr = new JenkinsRule(); + + private static final String token = "whatever"; + + @Test + @Issue("SECURITY-2558") + public void triggerJobWithoutSecurityRealm_ShouldSucceed_WithPost() throws Exception { + FreeStyleProject project = createFreestyleProjectWithToken(); + JenkinsRule.WebClient wc = jr.createWebClient(); + wc.getPage(wc.addCrumb(new WebRequest(new URL(jr.getURL(), project.getUrl() + + "build?delay=0") + ,HttpMethod.POST))); + jr.waitUntilNoActivity(); + assertThat("the project should have been built", project.getBuilds(), hasSize(1)); + } + + @Test + @Issue("SECURITY-2558") + public void triggerJobWithoutSecurityRealm_ShouldFail_WithGet() throws Exception { + FreeStyleProject project = jr.createFreeStyleProject(); + JenkinsRule.WebClient wc = jr.createWebClient(); + FailingHttpStatusCodeException fex = assertThrows( + "should not reach here since only POST request can", + FailingHttpStatusCodeException.class, + () -> wc.getPage(new WebRequest(new URL(jr.getURL(), project.getUrl() + "build?delay=0"), HttpMethod.GET))); + assertThat("Should fail with method not allowed", fex.getStatusCode(), is(405)); + } + + @Test + @Issue("SECURITY-2558") + public void triggerJobWithoutSecurityRealm_ButWithToken_ShouldSucceed_WithGet() throws Exception { + FreeStyleProject project = createFreestyleProjectWithToken(); + JenkinsRule.WebClient wc = jr.createWebClient(); + wc.getPage(new WebRequest(new URL(jr.getURL(), project.getUrl() + "build?delay=0&token=" + token) + ,HttpMethod.GET)); + jr.waitUntilNoActivity(); + assertThat("the project should have been built", project.getBuilds(), hasSize(1)); + } + + private FreeStyleProject createFreestyleProjectWithToken() throws Exception { + FreeStyleProject fsp = jr.createFreeStyleProject(); + Field f = AbstractProject.class.getDeclaredField("authToken"); + f.setAccessible(true); + f.set(fsp, new BuildAuthorizationToken(token)); + return fsp; + } +} diff --git a/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java b/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java index a5dccb9c8b9c..4f94a0b31a0d 100644 --- a/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java +++ b/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java @@ -23,10 +23,18 @@ */ package jenkins.model; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertThrows; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.HttpMethod; +import com.gargoylesoftware.htmlunit.WebRequest; import hudson.model.FreeStyleProject; import hudson.model.ParametersDefinitionProperty; import hudson.model.Queue; import hudson.model.StringParameterDefinition; +import java.net.URL; import javax.servlet.http.HttpServletResponse; import org.junit.Assert; import org.junit.Rule; @@ -58,9 +66,14 @@ public void doBuildWithParameters_shouldFailWhenInvokingDisabledProject() throws final FreeStyleProject project = j.createFreeStyleProject(); project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", "BAR"))); project.doDisable(); - + final JenkinsRule.WebClient webClient = j.createWebClient(); - webClient.assertFails(project.getUrl() + "buildWithParameters", HttpServletResponse.SC_CONFLICT); + + FailingHttpStatusCodeException fex = assertThrows( + "should fail when invoking disabled project", + FailingHttpStatusCodeException.class, + () -> webClient.getPage(webClient.addCrumb(new WebRequest(new URL(j.getURL(), project.getUrl() + "build?delay=0"), HttpMethod.POST)))); + assertThat("Should fail with conflict", fex.getStatusCode(), is(409)); } @Test @@ -72,7 +85,7 @@ public void doBuildQuietPeriodInSeconds() throws Exception { project.setQuietPeriod(projectQuietPeriodInSeconds); final JenkinsRule.WebClient webClient = j.createWebClient(); - webClient.goTo(project.getUrl() + "build", ""); + webClient.getPage(webClient.addCrumb(new WebRequest(new URL(j.getURL(), project.getUrl() + "build"), HttpMethod.POST))); long triggerTime = System.currentTimeMillis(); Queue.Item item = Jenkins.get().getQueue().getItem(1); From f3cbfa898de04c1c520a1cb5d15b5834785465c4 Mon Sep 17 00:00:00 2001 From: Jenkins Release Bot <66998184+jenkins-release-bot@users.noreply.github.com> Date: Tue, 11 Jan 2022 12:37:23 +0000 Subject: [PATCH 02/12] [maven-release-plugin] prepare release jenkins-2.329 --- bom/pom.xml | 2 +- cli/pom.xml | 2 +- core/pom.xml | 2 +- pom.xml | 4 ++-- test/pom.xml | 2 +- war/pom.xml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bom/pom.xml b/bom/pom.xml index 44220df8b8af..7115a020375f 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.329 jenkins-bom diff --git a/cli/pom.xml b/cli/pom.xml index 8772f2658fc2..9140abe3d14e 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.329 cli diff --git a/core/pom.xml b/core/pom.xml index 0b10a40a0d22..63126f36daaf 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,7 +29,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.329 jenkins-core diff --git a/pom.xml b/pom.xml index a48447ab85cb..b297a1e8fe59 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.329 pom Jenkins main module @@ -60,7 +60,7 @@ THE SOFTWARE. scm:git:git://github.com/jenkinsci/jenkins.git scm:git:ssh://git@github.com/jenkinsci/jenkins.git - ${scmTag} + jenkins-2.329 https://github.com/jenkinsci/jenkins diff --git a/test/pom.xml b/test/pom.xml index ad5cb291d233..b2280e0a81e7 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.329 jenkins-test diff --git a/war/pom.xml b/war/pom.xml index e71473d30ca0..891f9bd06396 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.329 jenkins-war From 1656ee796cad7662d8f0dda0650d047e8878b514 Mon Sep 17 00:00:00 2001 From: Jenkins Release Bot <66998184+jenkins-release-bot@users.noreply.github.com> Date: Tue, 11 Jan 2022 12:38:19 +0000 Subject: [PATCH 03/12] [maven-release-plugin] prepare for next development iteration --- bom/pom.xml | 2 +- cli/pom.xml | 2 +- core/pom.xml | 2 +- pom.xml | 6 +++--- test/pom.xml | 2 +- war/pom.xml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bom/pom.xml b/bom/pom.xml index 7115a020375f..44220df8b8af 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - 2.329 + ${revision}${changelist} jenkins-bom diff --git a/cli/pom.xml b/cli/pom.xml index 9140abe3d14e..8772f2658fc2 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.main jenkins-parent - 2.329 + ${revision}${changelist} cli diff --git a/core/pom.xml b/core/pom.xml index 63126f36daaf..0b10a40a0d22 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,7 +29,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - 2.329 + ${revision}${changelist} jenkins-core diff --git a/pom.xml b/pom.xml index b297a1e8fe59..633d20d71df7 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - 2.329 + ${revision}${changelist} pom Jenkins main module @@ -60,7 +60,7 @@ THE SOFTWARE. scm:git:git://github.com/jenkinsci/jenkins.git scm:git:ssh://git@github.com/jenkinsci/jenkins.git - jenkins-2.329 + ${scmTag} https://github.com/jenkinsci/jenkins @@ -70,7 +70,7 @@ THE SOFTWARE. - 2.329 + 2.330 -SNAPSHOT