diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..d6ab6c3
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @jenkinsci/reverse-proxy-auth-plugin-developers
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 94df459..bd90db4 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,15 +1,18 @@
+# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+---
version: 2
updates:
-- package-ecosystem: maven
- directory: "/"
- schedule:
- interval: weekly
- ignore:
- - dependency-name: "org.jenkins-ci.main:jenkins-core"
- open-pull-requests-limit: 10
- target-branch: master
- reviewers:
- - rda1ton
- - sboardwell
- labels:
- - skip-changelog
+ - package-ecosystem: "maven"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ ignore:
+ - dependency-name: "org.jenkins-ci.main:jenkins-core"
+ open-pull-requests-limit: 10
+ reviewers:
+ - rda1ton
+ - sboardwell
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
new file mode 100644
index 0000000..da8cb13
--- /dev/null
+++ b/.github/release-drafter.yml
@@ -0,0 +1,6 @@
+# https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc
+---
+_extends: .github
+tag-template: reverse-proxy-auth-plugin-$NEXT_PATCH_VERSION
+name-template: $NEXT_PATCH_VERSION
+version-template: $MAJOR.$MINOR.$PATCH
diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml
new file mode 100644
index 0000000..4fc3d2c
--- /dev/null
+++ b/.github/workflows/release-drafter.yml
@@ -0,0 +1,16 @@
+# Automates creation of Release Drafts using Release Drafter
+# More Info: https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc
+---
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ update_release_draft:
+ runs-on: ubuntu-latest
+ steps:
+ # Drafts your next Release notes as Pull Requests are merged into "master"
+ - uses: release-drafter/release-drafter@v6
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 70660d7..0834364 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,15 @@
+target
+
+# mvn hpi:run
+work
+
+# IntelliJ IDEA project files
*.iml
*.iws
*.ipr
-target
-work
-/.idea
-/.classpath
-/.project
-/.settings
-.vscode
+.idea
+
+# Eclipse project files
+.settings
+.classpath
+.project
diff --git a/Jenkinsfile b/Jenkinsfile
index ec8ac5f..09d365a 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,2 +1,5 @@
// Build the plugin using https://github.com/jenkins-infra/pipeline-library
-buildPlugin(jdkVersions: [11,17])
+buildPlugin(configurations: [
+ [platform: 'linux', jdk: 21],
+ [platform: 'windows', jdk: 17],
+])
diff --git a/pom.xml b/pom.xml
index 860520a..5878ecb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
org.jenkins-ci.plugins
plugin
- 4.79
+ 4.88
@@ -13,7 +13,7 @@
hpi
Jenkins Reverse Proxy Auth Plugin
- https://github.com/jenkinsci/reverse-proxy-auth-plugin
+ https://github.com/jenkinsci/${project.artifactId}
@@ -45,13 +45,25 @@
1.7.8
-SNAPSHOT
- jenkinsci/reverse-proxy-auth-plugin
- 2.387.3
+ jenkinsci/${project.artifactId}
+ 2.426
+ ${jenkins.baseline}.3
Max
- true
false
+
+
+
+ io.jenkins.tools.bom
+ bom-${jenkins.baseline}.x
+ 3208.vb_21177d4b_cd9
+ pom
+ import
+
+
+
+
@@ -121,7 +133,29 @@
org.jenkins-ci.plugins
mailer
- 463.vedf8358e006b_
+
+
+ org.jenkins-ci.plugins
+ jackson2-api
+ test
+
+
+ org.testcontainers
+ testcontainers
+ 1.20.3
+ test
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
+ org.apache.commons
+ commons-compress
+
+
diff --git a/src/main/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealm.java b/src/main/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealm.java
index 363d957..ed449f2 100644
--- a/src/main/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealm.java
+++ b/src/main/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealm.java
@@ -271,6 +271,7 @@ public class ReverseProxySecurityRealm extends SecurityRealm {
public final String customLogOutUrl;
@DataBoundConstructor
+ @SuppressFBWarnings(value = "PA_PUBLIC_PRIMITIVE_ATTRIBUTE", justification = "API compatibility")
public ReverseProxySecurityRealm(
String forwardedUser,
String forwardedEmail,
diff --git a/src/test/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealmTest.java b/src/test/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealmTest.java
index 73cc58f..b1dad82 100644
--- a/src/test/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealmTest.java
+++ b/src/test/java/org/jenkinsci/plugins/reverse_proxy_auth/ReverseProxySecurityRealmTest.java
@@ -68,9 +68,9 @@ public Authentication call() {
private ReverseProxySecurityRealm createBasicRealm() {
return new ReverseProxySecurityRealm(
"X-Forwarded-User", // forwardedUser
- "X-Forwarded-Groups", // headerGroups
"X-Forwarded-Email", // forwardedEmail
"X-Forwarded-DisplayName", // forwardedDisplayName
+ "X-Forwarded-Groups", // headerGroups
"|", // headerGroupsDelimiter
"", // customLogInUrl
"", // customLogOutUrl
diff --git a/src/test/java/org/jenkinsci/plugins/reverse_proxy_auth/docker/PlanetExpressTest.java b/src/test/java/org/jenkinsci/plugins/reverse_proxy_auth/docker/PlanetExpressTest.java
new file mode 100644
index 0000000..a28bcd7
--- /dev/null
+++ b/src/test/java/org/jenkinsci/plugins/reverse_proxy_auth/docker/PlanetExpressTest.java
@@ -0,0 +1,107 @@
+package org.jenkinsci.plugins.reverse_proxy_auth.docker;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import hudson.Functions;
+import hudson.tasks.MailAddressResolver;
+import hudson.util.Secret;
+import org.acegisecurity.userdetails.ldap.LdapUserDetails;
+import org.jenkinsci.plugins.reverse_proxy_auth.ReverseProxySecurityRealm;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.RealJenkinsRule;
+import org.testcontainers.DockerClientFactory;
+import org.testcontainers.containers.GenericContainer;
+
+/**
+ * Tests the plugin when logging in to rroemhild/test-openldap
+ */
+public class PlanetExpressTest {
+
+ static final String TEST_IMAGE =
+ "rroemhild/test-openldap@sha256:b4e433bbcba1f17899d6bcb0a8e854bbe52c754faa4e785d0c27a2b55eb12cd8";
+ static final String DN = "dc=planetexpress,dc=com";
+ static final String MANAGER_DN = "cn=admin,dc=planetexpress,dc=com";
+ static final String MANAGER_SECRET = "GoodNewsEveryone";
+
+ @BeforeClass
+ public static void requiresDocker() {
+ assumeTrue(DockerClientFactory.instance().isDockerAvailable());
+ }
+
+ @BeforeClass
+ public static void linuxOnly() {
+ assumeFalse(
+ "Windows CI builders now have Docker installed…but it does not support Linux images",
+ Functions.isWindows() && System.getenv("JENKINS_URL") != null);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Rule
+ public GenericContainer container = new GenericContainer(TEST_IMAGE).withExposedPorts(389);
+
+ @Rule
+ public RealJenkinsRule rr = new RealJenkinsRule();
+
+ @Test
+ public void login() throws Throwable {
+ String server = container.getHost() + ":" + container.getFirstMappedPort();
+ rr.then(new Login(server));
+ }
+
+ private static class Login implements RealJenkinsRule.Step {
+ private final String server;
+
+ Login(String server) {
+ this.server = server;
+ }
+
+ @Override
+ public void run(JenkinsRule j) throws Throwable {
+ ReverseProxySecurityRealm realm = new ReverseProxySecurityRealm(
+ "X-Forwarded-User", // forwardedUser
+ "X-Forwarded-Email", // forwardedEmail
+ "X-Forwarded-DisplayName", // forwardedDisplayName
+ "X-Forwarded-Groups", // headerGroups
+ "|", // headerGroupsDelimiter
+ "", // customLogInUrl
+ "", // customLogOutUrl
+ server, // server
+ DN, // rootDN
+ false, // inhibitInferRootDN
+ "", // userSearchBase
+ "", // userSearch
+ "", // groupSearchBase
+ "", // groupSearchFilter
+ "", // groupMembershipFilter
+ "", // groupNameAttribute
+ MANAGER_DN, // managerDN
+ Secret.fromString(MANAGER_SECRET), // managerPassword
+ 15, // updateInterval
+ false, // disableLdapEmailResolver
+ "cn", // displayNameLdapAttribute
+ "mail" // emailAddressLdapAttribute
+ );
+ j.jenkins.setSecurityRealm(realm);
+ j.configRoundtrip();
+ try (JenkinsRule.WebClient wc = j.createWebClient()) {
+ wc.addRequestHeader(realm.getForwardedUser(), "fry");
+ String content = wc.login("fry", "fry").goTo("whoAmI").getBody().getTextContent();
+ assertThat(content, containsString("Philip J. Fry"));
+ }
+
+ LdapUserDetails zoidberg =
+ (LdapUserDetails) j.jenkins.getSecurityRealm().loadUserByUsername("zoidberg");
+ assertEquals("cn=John A. Zoidberg,ou=people,dc=planetexpress,dc=com", zoidberg.getDn());
+
+ String leelaEmail = MailAddressResolver.resolve(j.jenkins.getUser("leela"));
+ assertEquals("leela@planetexpress.com", leelaEmail);
+ }
+ }
+}