Skip to content

Upgrade to Spring Security 6.x and EE 9 #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

- Upgrade to Spring Security 6.x and Jakarta EE 9 (thanks to [@basil](https://github.com/basil)).
- Compatibility with Jenkins 2.476 and higher (requires Java 17).
- Incompatibility with Jenkins 2.475 and lower, please make sure to upgrade CAS plugin and Jenkins together.

## [1.6.3] - 2023-05-14

- Fixed security issue (SECURITY-3000).
Expand Down
5 changes: 4 additions & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
buildPlugin()
buildPlugin(useContainerAgent: true, configurations: [
[platform: 'linux', jdk: 21],
[platform: 'windows', jdk: 17],
])
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ The latest version is available for download from the Update Center and from the

### Upgrade notice

- Jenkins **2.266 and higher** require CAS plugin version **1.5.0** or higher.
- Jenkins **2.265 and lower** require CAS plugin version **1.4.3** (1.5.0 is _NOT_ compatible).
- Jenkins **2.160 or 2.150.2 LTS** and higher require CAS plugin version **1.4.3**.
Some Jenkins versions require specific CAS plugin versions for compatibility reasons:

| Jenkins version | CAS plugin version |
|--------------------|--------------------|
| 2.476 and higher | 1.7.0 and higher |
| 2.475 | not compatible |
| 2.266 to 2.474 | 1.5.0 to 1.6.3 |
| 2.160 to 2.265 | 1.4.3 |
| 2.150.2 to 2.150.3 | 1.4.3 |
| Older releases | 1.4.2 and lower |

In these cases, you will need to upgrade Jenkins and CAS plugin together to avoid issues. This means manually downloading and updating the `cas-plugin.hpi` file in your Jenkins `plugins` directory (rename to `cas-plugin.jpi` as needed).

Expand Down
93 changes: 64 additions & 29 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License

Expand Down Expand Up @@ -28,19 +29,19 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.12</version>
<version>4.87</version>
<relativePath />
</parent>

<artifactId>cas-plugin</artifactId>
<version>${revision}${changelist}</version>
<packaging>hpi</packaging>
<name>CAS Plugin</name>
<url>https://github.com/jenkinsci/cas-plugin</url>
<url>https://github.com/jenkinsci/${project.artifactId}</url>

<scm>
<connection>scm:git:ssh://github.com/${gitHubRepo}.git</connection>
<developerConnection>scm:git:ssh://[email protected]/${gitHubRepo}.git</developerConnection>
<connection>scm:git:https://github.com/${gitHubRepo}.git</connection>
<developerConnection>scm:git:[email protected]:${gitHubRepo}.git</developerConnection>
<url>https://github.com/${gitHubRepo}</url>
<tag>${scmTag}</tag>
</scm>
Expand All @@ -67,8 +68,8 @@ THE SOFTWARE.

<licenses>
<license>
<name>The MIT License</name>
<url>http://www.opensource.org/licenses/MIT</url>
<name>MIT License</name>
<url>https://opensource.org/license/mit/</url>
</license>
</licenses>

Expand All @@ -88,43 +89,39 @@ THE SOFTWARE.
<properties>
<revision>1.6.4</revision>
<changelist>-SNAPSHOT</changelist>
<gitHubRepo>jenkinsci/cas-plugin</gitHubRepo>
<java.level>8</java.level>
<jenkins.version>2.266</jenkins.version>
<cas-client.version>3.6.1</cas-client.version>
<bouncycastle-api.version>2.18</bouncycastle-api.version>
<jaxb.version>2.3.6-1</jaxb.version>
<gitHubRepo>jenkinsci/${project.artifactId}</gitHubRepo>
<jenkins.version>2.476</jenkins.version>
<!-- TODO JENKINS-73339 until in parent POM -->
<jenkins-test-harness.version>2265.v3da_49c8134d6</jenkins-test-harness.version>
<maven.compiler.release>17</maven.compiler.release>
<cas-client.version>4.0.4</cas-client.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-2.263.x</artifactId>
<version>18</version>
<artifactId>bom-2.462.x</artifactId>
<version>3334.v18e2a_2f48356</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>bouncycastle-api</artifactId>
<version>${bouncycastle-api.version}</version>
</dependency>
<dependency>
<groupId>io.jenkins.plugins</groupId>
<artifactId>jaxb</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<groupId>org.apereo.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>${cas-client.version}</version>
</dependency>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<groupId>org.apereo.cas.client</groupId>
<artifactId>cas-client-support-saml</artifactId>
<version>${cas-client.version}</version>
</dependency>
<!-- TODO JENKINS-73339 until in parent POM, work around https://github.com/jenkinsci/plugin-pom/issues/936 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
Expand All @@ -133,8 +130,8 @@ THE SOFTWARE.
<artifactId>bouncycastle-api</artifactId>
</dependency>
<dependency>
<groupId>io.jenkins.plugins</groupId>
<artifactId>jaxb</artifactId>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>jackson2-api</artifactId>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand All @@ -145,8 +142,46 @@ THE SOFTWARE.
<artifactId>script-security</artifactId>
</dependency>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<groupId>org.apereo.cas.client</groupId>
<artifactId>cas-client-support-saml</artifactId>
<exclusions>
<!-- Provided by jackson2-api plugin -->
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<!-- Provided by Jenkins core -->
<exclusion>
<groupId>com.github.stephenc.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
<!-- Provided by bouncycastle-api plugin -->
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<!-- Provided by Jenkins core -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jenkinsci/plugins/cas/CasProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.jasig.cas.client.validation.TicketValidator;
import org.apereo.cas.client.validation.TicketValidator;
import org.springframework.security.cas.ServiceProperties;

import hudson.DescriptorExtensionList;
Expand Down
35 changes: 18 additions & 17 deletions src/main/java/org/jenkinsci/plugins/cas/CasSecurityRealm.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
import java.net.URL;
import java.net.URLEncoder;

import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.jasig.cas.client.session.SessionMappingStorage;
import org.jasig.cas.client.util.CommonUtils;
import org.apereo.cas.client.session.SessionMappingStorage;
import org.apereo.cas.client.util.CommonUtils;
import org.jenkinsci.plugins.cas.spring.CasConfigurationContext;
import org.jenkinsci.plugins.cas.spring.security.CasRestAuthenticator;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.StaplerRequest2;
import org.kohsuke.stapler.StaplerResponse2;
import org.kohsuke.stapler.interceptor.RequirePOST;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -41,7 +41,7 @@
import hudson.Extension;
import hudson.Util;
import hudson.model.Descriptor;
import hudson.security.ChainedServletFilter;
import hudson.security.ChainedServletFilter2;
import hudson.security.SecurityRealm;
import hudson.util.FormValidation;
import jenkins.model.Jenkins;
Expand Down Expand Up @@ -168,7 +168,7 @@
// ~ SecurityRealm implementation ===================================================================================

/**
* Login begins with our {@link #doCommenceLogin(StaplerRequest, StaplerResponse)} method.
* Login begins with our {@link #doCommenceLogin(StaplerRequest2, StaplerResponse2)} method.
* @return Jenkins commenceLogin URL
*/
@Override
Expand All @@ -181,7 +181,7 @@
* @return CAS logout URL
*/
@Override
protected String getPostLogOutUrl2(StaplerRequest req, Authentication auth) {
protected String getPostLogOutUrl2(StaplerRequest2 req, Authentication auth) {
if (Boolean.TRUE.equals(this.enableLogoutRedirect)) {
StringBuilder logoutUrlBuilder = new StringBuilder(casServerUrl);
logoutUrlBuilder.append("logout?service=");
Expand Down Expand Up @@ -209,26 +209,27 @@
if (authentication instanceof AnonymousAuthenticationToken) {
return authentication;
} else if ((authentication instanceof UsernamePasswordAuthenticationToken) && Boolean.TRUE.equals(enableRestApi)) {
LOG.debug("Authenticating UsernamePasswordAuthenticationToken with CAS REST API");
return getApplicationContext().getBean(CasRestAuthenticator.class).authenticate(authentication);
} else {
throw new BadCredentialsException("Unexpected authentication type: " + authentication);
}
}
});
}

/**
* Build the filter that will validate the service ticket returned by CAS.
* This filter will also wrap the original filter chain from Jenkins to
* preserve support for API token authentication (among other features).
* @return CAS filter
*/
@Override
public Filter createFilter(FilterConfig filterConfig) {
LOG.debug("Creating CAS authentication filter");
Filter defaultFilter = super.createFilter(filterConfig);
Filter casFilter = getApplicationContext().getBean("casFilter", ChainedServletFilter.class);
return new ChainedServletFilter(casFilter, defaultFilter);
Filter casFilter = getApplicationContext().getBean("casFilter", ChainedServletFilter2.class);
return new ChainedServletFilter2(casFilter, defaultFilter);

Check warning on line 232 in src/main/java/org/jenkinsci/plugins/cas/CasSecurityRealm.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 212-232 are not covered by tests
}

// ~ Stapler controller actions =====================================================================================
Expand All @@ -241,7 +242,7 @@
* @throws ServletException Servlet error
*/
@Override
public void doLogout(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
public void doLogout(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException {
// Remove session from CAS single sign-out storage
HttpSession session = req.getSession(false);
if (session != null) {
Expand All @@ -257,7 +258,7 @@
* @throws IOException I/O error
* @throws ServletException Servlet error
*/
public void doCommenceLogin(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
public void doCommenceLogin(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException {
LOG.debug("Redirecting to CAS for authentication");
getApplicationContext().getBean(CasAuthenticationEntryPoint.class).commence(req, rsp, null);
}
Expand All @@ -267,7 +268,7 @@
* @param req request
* @param rsp response
*/
public void doFinishLogin(StaplerRequest req, StaplerResponse rsp) {
public void doFinishLogin(StaplerRequest2 req, StaplerResponse2 rsp) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
LOG.debug("Finishing CAS login with authentication={}", authentication);
req.getSession(); // Force session creation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.Collection;

import org.codehaus.groovy.control.CompilationFailedException;
import org.jasig.cas.client.validation.TicketValidator;
import org.apereo.cas.client.validation.TicketValidator;
import org.jenkinsci.plugins.cas.CasProtocol;
import org.jenkinsci.plugins.cas.Messages;
import org.jenkinsci.plugins.cas.validation.Cas10RoleParsingTicketValidator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.jasig.cas.client.validation.ProxyList;
import org.jasig.cas.client.validation.TicketValidator;
import org.apereo.cas.client.validation.Cas20ProxyTicketValidator;
import org.apereo.cas.client.validation.Cas20ServiceTicketValidator;
import org.apereo.cas.client.validation.ProxyList;
import org.apereo.cas.client.validation.TicketValidator;
import org.jenkinsci.plugins.cas.CasProtocol;
import org.kohsuke.stapler.DataBoundConstructor;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.jasig.cas.client.validation.Cas30ProxyTicketValidator;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.jasig.cas.client.validation.ProxyList;
import org.jasig.cas.client.validation.TicketValidator;
import org.jasig.cas.client.validation.json.Cas30JsonProxyTicketValidator;
import org.jasig.cas.client.validation.json.Cas30JsonServiceTicketValidator;
import org.apereo.cas.client.validation.Cas30ProxyTicketValidator;
import org.apereo.cas.client.validation.Cas30ServiceTicketValidator;
import org.apereo.cas.client.validation.ProxyList;
import org.apereo.cas.client.validation.TicketValidator;
import org.apereo.cas.client.validation.json.Cas30JsonProxyTicketValidator;
import org.apereo.cas.client.validation.json.Cas30JsonServiceTicketValidator;
import org.jenkinsci.plugins.cas.CasProtocol;
import org.kohsuke.stapler.DataBoundConstructor;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.jenkinsci.plugins.cas.protocols;

import org.jasig.cas.client.validation.Saml11TicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
import org.apereo.cas.client.validation.Saml11TicketValidator;
import org.apereo.cas.client.validation.TicketValidator;
import org.jenkinsci.plugins.cas.CasProtocol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.springframework.security.cas.SamlServiceProperties;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import java.util.Collections;

import org.jasig.cas.client.session.HashMapBackedSessionMappingStorage;
import org.jasig.cas.client.session.SessionMappingStorage;
import org.jasig.cas.client.session.SingleSignOutHandler;
import org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
import org.apereo.cas.client.session.HashMapBackedSessionMappingStorage;
import org.apereo.cas.client.session.SessionMappingStorage;
import org.apereo.cas.client.session.SingleSignOutHandler;
import org.apereo.cas.client.validation.AbstractUrlBasedTicketValidator;
import org.apereo.cas.client.validation.TicketValidator;
import org.jenkinsci.plugins.cas.CasProtocol;
import org.jenkinsci.plugins.cas.CasSecurityRealm;
import org.jenkinsci.plugins.cas.spring.security.CasRestAuthenticator;
Expand All @@ -29,7 +29,7 @@
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;

import hudson.security.ChainedServletFilter;
import hudson.security.ChainedServletFilter2;
import hudson.security.HttpSessionContextIntegrationFilter2;
import hudson.security.SecurityRealm;

Expand Down Expand Up @@ -158,8 +158,8 @@
}

@Bean
public ChainedServletFilter casFilter(HttpSessionContextIntegrationFilter2 httpSessionContextIntegrationFilter, CasSingleSignOutFilter casSingleSignOutFilter, CasAuthenticationFilter casAuthenticationFilter) {
return new ChainedServletFilter(httpSessionContextIntegrationFilter, casSingleSignOutFilter, casAuthenticationFilter);
public ChainedServletFilter2 casFilter(HttpSessionContextIntegrationFilter2 httpSessionContextIntegrationFilter, CasSingleSignOutFilter casSingleSignOutFilter, CasAuthenticationFilter casAuthenticationFilter) {
return new ChainedServletFilter2(httpSessionContextIntegrationFilter, casSingleSignOutFilter, casAuthenticationFilter);

Check warning on line 162 in src/main/java/org/jenkinsci/plugins/cas/spring/CasConfigurationContext.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 162 is not covered by tests
}

@Bean
Expand Down
Loading