diff --git a/core/src/main/resources/hudson/security/csrf/GlobalCrumbIssuerConfiguration/config.groovy b/core/src/main/resources/hudson/security/csrf/GlobalCrumbIssuerConfiguration/config.groovy index b999cf5229..17869f6c47 100644 --- a/core/src/main/resources/hudson/security/csrf/GlobalCrumbIssuerConfiguration/config.groovy +++ b/core/src/main/resources/hudson/security/csrf/GlobalCrumbIssuerConfiguration/config.groovy @@ -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' + ) } } } diff --git a/test/src/test/java/hudson/security/csrf/GlobalCrumbIssuerConfigurationTest.java b/test/src/test/java/hudson/security/csrf/GlobalCrumbIssuerConfigurationTest.java new file mode 100644 index 0000000000..cc8c7e05cc --- /dev/null +++ b/test/src/test/java/hudson/security/csrf/GlobalCrumbIssuerConfigurationTest.java @@ -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> descriptors = j.jenkins.getDescriptorList(CrumbIssuer.class); + List> toRemove = new ArrayList<>(); + for (Descriptor 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; + } + } +}