Skip to content
Original file line number Diff line number Diff line change
@@ -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'
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package hudson.security.csrf;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

import jakarta.servlet.ServletRequest;
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.TestExtension;
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;

@WithJenkins
class GlobalCrumbIssuerConfigurationTest {

private JenkinsRule j;

@BeforeEach
void setUp(JenkinsRule rule) {
j = rule;
}

@Test
void csrfSectionShownWhenOnlyDefaultIssuerAvailable() throws Exception {
// No @TestExtension here, so only DefaultCrumbIssuer is registered
j.jenkins.setCrumbIssuer(new DefaultCrumbIssuer(false));

JenkinsRule.WebClient wc = j.createWebClient();
HtmlPage page = wc.goTo("configureSecurity");
String pageContent = page.asNormalizedText();

// When only DefaultCrumbIssuer exists, the CSRF section should still be visible
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh?

Image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @daniel-beck for the confusion.. The comment was misleading ..
I'm fixing the test now to correctly assert that the CSRF section
is hidden when only DefaultCrumbIssuer is available.

assertThat(pageContent, containsString("Default Crumb Issuer"));
}

@Test
void csrfSectionShownWhenNonDefaultIssuerConfigured() throws Exception {
// DefaultCrumbIssuer is default, but other CrumbIssuer descriptors exist in test environment
// so the CSRF section should be visible
j.jenkins.setCrumbIssuer(new DefaultCrumbIssuer(false));

JenkinsRule.WebClient wc = j.createWebClient();
HtmlPage page = wc.goTo("configureSecurity");
String pageContent = page.asNormalizedText();

// With multiple CrumbIssuer descriptors available (from test extensions),
// the CSRF Protection section should always be shown
assertThat(pageContent, containsString("Default Crumb Issuer"));
}

@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 the System property"));
} finally {
GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION = original;
}
}

@TestExtension("csrfSectionShownWhenNonDefaultIssuerConfigured")
public static class DummyCrumbIssuer extends CrumbIssuer {

@Override
public String getCrumbRequestField() {
return "dummy";
}

@Override
public String issueCrumb(ServletRequest request, String salt) {
return "dummy-crumb";
}

public static class DescriptorImpl extends CrumbIssuerDescriptor<DummyCrumbIssuer> {

DescriptorImpl() {
super(
DummyCrumbIssuer.class.getName(),
"Dummy Crumb Issuer"
);
}

@Override
public String getDisplayName() {
return "Dummy Crumb Issuer";
}
}
}
}