Hide CSRF configuration UI when only DefaultCrumbIssuer is available (#26057)

* Hide CSRF configuration UI when only DefaultCrumbIssuer is available

* Add test for CSRF section visibility

* Remove unused import in GlobalCrumbIssuerConfigurationTest

* Add @TestExtension DummyCrumbIssuer to provide second CrumbIssuer descriptor in test environment

* Fix CSRF configuration test assertions per review feedback

* Fix unused import in CSRF configuration test

* Fix hidden test assertion to check DummyCrumbIssuer absence

* Fix CSRF test: use TestCrumbIssuer, assert CSRF section hidden correctly

* Merge CSRF tests into single class, remove separate WithDummy file

* Merge CSRF tests into single class, remove separate WithDummy file

* Use non-deprecated DefaultCrumbIssuer constructor in test

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Daniel Beck <1831569+daniel-beck@users.noreply.github.com>
Co-authored-by: Mark Waite <mark.earl.waite@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-06-13 22:30:11 -06:00
1 parent a015301bde
commit 85680f92ba
2 files changed
+90 -4

No files matched your search

@@ -1,19 +1,31 @@
package hudson.security.csrf.GlobalCrumbIssuerConfiguration
import hudson.security.csrf.CrumbIssuer
import hudson.security.csrf.DefaultCrumbIssuer
def f=namespace(lib.FormTagLib)
def f = namespace(lib.FormTagLib)
def all = CrumbIssuer.all()
def disableCsrf =
hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION
if (!all.isEmpty()) {
def onlyDefaultIssuer =
all.size() == 1 && all[0].clazz == DefaultCrumbIssuer
def showCsrfConfig = !onlyDefaultIssuer || disableCsrf
if (showCsrfConfig) {
f.section(title: _("CSRF Protection")) {
if (hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION) {
if (disableCsrf) {
f.entry {
p(raw(_('disabled')))
p(_('unsupported'))
}
} else {
f.dropdownDescriptorSelector(title: _("Crumb Issuer"), descriptors: all, field: 'crumbIssuer')
f.dropdownDescriptorSelector(
title: _("Crumb Issuer"),
descriptors: all,
field: 'crumbIssuer'
)
}
}
}
@@ -0,0 +1,74 @@
package hudson.security.csrf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import hudson.ExtensionList;
import hudson.model.Descriptor;
import java.util.ArrayList;
import java.util.List;
import org.htmlunit.html.HtmlPage;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
@WithJenkins
class GlobalCrumbIssuerConfigurationTest {
private JenkinsRule j;
@BeforeEach
void setUp(JenkinsRule rule) {
j = rule;
}
@Test
void csrfSectionHiddenWhenOnlyDefaultIssuerAvailable() throws Exception {
// Remove all non-default CrumbIssuer descriptors so only DefaultCrumbIssuer remains
ExtensionList<Descriptor<CrumbIssuer>> descriptors = j.jenkins.getDescriptorList(CrumbIssuer.class);
List<Descriptor<CrumbIssuer>> toRemove = new ArrayList<>();
for (Descriptor<CrumbIssuer> d : descriptors) {
if (!(d instanceof DefaultCrumbIssuer.DescriptorImpl)) {
toRemove.add(d);
}
}
descriptors.removeAll(toRemove);
j.jenkins.setCrumbIssuer(new DefaultCrumbIssuer());
JenkinsRule.WebClient wc = j.createWebClient();
HtmlPage page = wc.goTo("configureSecurity");
String pageContent = page.asNormalizedText();
assertThat(pageContent, not(containsString("CSRF Protection")));
}
@Test
void csrfSectionShownWhenNonDefaultIssuerConfigured() throws Exception {
// TestCrumbIssuer is registered by Jenkins test harness automatically,
// so CrumbIssuer.all() has more than just DefaultCrumbIssuer and CSRF section is shown.
JenkinsRule.WebClient wc = j.createWebClient();
HtmlPage page = wc.goTo("configureSecurity");
String pageContent = page.asNormalizedText();
assertThat(pageContent, containsString("CSRF Protection"));
}
@Test
void csrfSectionShownWhenCsrfProtectionDisabled() throws Exception {
boolean original = GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION;
try {
GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION = true;
JenkinsRule.WebClient wc = j.createWebClient();
HtmlPage page = wc.goTo("configureSecurity");
String pageContent = page.asNormalizedText();
assertThat(pageContent, containsString("This configuration is unavailable because"));
} finally {
GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION = original;
}
}
}