From 63c7a278b789565b4730422a49c89a17af8e5d06 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Thu, 21 Apr 2022 22:20:59 +0000 Subject: [PATCH 01/11] Breaking change - getAuthorities Due to nessisity of removing deprecations, this breaking change got introduced. There is no possible way to add this two implementations, during this change. --- src/main/java/de/theit/jenkins/crowd/CrowdUser.java | 12 ++++++------ .../java/de/theit/jenkins/crowd/CrowdUserTest.java | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdUser.java b/src/main/java/de/theit/jenkins/crowd/CrowdUser.java index 45dd2cac..5a91188f 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdUser.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdUser.java @@ -25,10 +25,11 @@ */ package de.theit.jenkins.crowd; +import java.util.Collection; import java.util.List; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.userdetails.UserDetails; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; import com.atlassian.crowd.model.user.User; @@ -41,7 +42,7 @@ * @version $Id$ */ public class CrowdUser implements UserDetails { - /** Necessary for serialisation. */ + /** Necessary for serialization. */ private static final long serialVersionUID = -907996070755427899L; /** Stores the granted authorities. */ @@ -68,9 +69,8 @@ public CrowdUser(User pUser, List authorities) { * @see org.acegisecurity.userdetails.UserDetails#getAuthorities() */ @Override - public GrantedAuthority[] getAuthorities() { - return this.grantedAuthorities - .toArray(new GrantedAuthority[this.grantedAuthorities.size()]); + public Collection getAuthorities() { + return this.grantedAuthorities; } /** diff --git a/src/test/java/de/theit/jenkins/crowd/CrowdUserTest.java b/src/test/java/de/theit/jenkins/crowd/CrowdUserTest.java index 5f0a5168..f346ef77 100644 --- a/src/test/java/de/theit/jenkins/crowd/CrowdUserTest.java +++ b/src/test/java/de/theit/jenkins/crowd/CrowdUserTest.java @@ -4,8 +4,8 @@ import java.util.Collections; import java.util.List; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.GrantedAuthorityImpl; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import com.atlassian.crowd.model.user.ImmutableUser; import org.assertj.core.api.Assertions; @@ -20,7 +20,7 @@ public class CrowdUserTest { public void setUp() { ImmutableUser u = new ImmutableUser(0, "user1", "foo user 1", "foo@bar.baz", false, null, null, null); List authorities = new ArrayList<>(); - authorities.add(new GrantedAuthorityImpl("fooGroup")); + authorities.add(new SimpleGrantedAuthority("fooGroup")); dummy = new CrowdUser(u, authorities); } @@ -28,12 +28,12 @@ public void setUp() { public void testCrowdUser() { Assertions.assertThat(dummy.getUsername()).isEqualTo("user1"); - Assertions.assertThat(dummy.getAuthorities()[0].getAuthority()).isEqualTo("fooGroup"); + Assertions.assertThat(dummy.getAuthorities().iterator().next().getAuthority()).isEqualTo("fooGroup"); } @Test public void testGetAuthorities() { - Assertions.assertThat(dummy.getAuthorities()[0].getAuthority()).isEqualTo("fooGroup"); + Assertions.assertThat(dummy.getAuthorities().iterator().next().getAuthority()).isEqualTo("fooGroup"); } @Test From 496aa4fbc0d8aae401094226bc9184829d903d8d Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Thu, 21 Apr 2022 22:27:42 +0000 Subject: [PATCH 02/11] Breaking change - authenticate is now returning differnt object type --- .../crowd/CrowdAuthenticationManager.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationManager.java b/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationManager.java index fb6c89cf..83db6e29 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationManager.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationManager.java @@ -33,15 +33,15 @@ import com.atlassian.crowd.exception.UserNotFoundException; import com.atlassian.crowd.model.user.User; import hudson.security.SecurityRealm; -import org.acegisecurity.AccountExpiredException; -import org.acegisecurity.Authentication; -import org.acegisecurity.AuthenticationException; -import org.acegisecurity.AuthenticationManager; -import org.acegisecurity.AuthenticationServiceException; -import org.acegisecurity.BadCredentialsException; -import org.acegisecurity.CredentialsExpiredException; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.InsufficientAuthenticationException; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.CredentialsExpiredException; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; import java.util.ArrayList; import java.util.List; @@ -87,7 +87,7 @@ public CrowdAuthenticationManager(CrowdConfigurationService pConfiguration) { /** * {@inheritDoc} * - * @see org.acegisecurity.AuthenticationManager#authenticate(org.acegisecurity.Authentication) + * @see org.springframework.security.authentication.AuthenticationManager#authenticate(org.springframework.security.core.Authentication) */ @Override public Authentication authenticate(Authentication authentication) @@ -156,7 +156,7 @@ public Authentication authenticate(Authentication authentication) // add the "authenticated" authority to the list of granted // authorities... - authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY); + authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY2); // ..and finally all authorities retrieved from the Crowd server authorities.addAll(this.configuration.getAuthoritiesForUser(username)); From 6b1db03d7b1016c79931757a87d8d4eafd620699 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Thu, 21 Apr 2022 22:32:05 +0000 Subject: [PATCH 03/11] Remove next deprecation - breaking change --- .../crowd/CrowdUserDetailsService.java | 27 +++++++++---------- .../crowd/CrowdUserDetailsServiceTest.java | 13 ++++----- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java b/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java index d9371f74..f97cdd56 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java @@ -30,15 +30,15 @@ import com.atlassian.crowd.exception.OperationFailedException; import com.atlassian.crowd.exception.UserNotFoundException; import com.atlassian.crowd.model.user.User; + import hudson.security.SecurityRealm; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.userdetails.UserDetails; -import org.acegisecurity.userdetails.UserDetailsService; -import org.acegisecurity.userdetails.UsernameNotFoundException; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -81,17 +81,16 @@ public CrowdUserDetailsService(CrowdConfigurationService pConfiguration) { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) */ @Override public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException, DataAccessException { + throws UsernameNotFoundException { // check whether there's at least one active group the user is a member // of if (!this.configuration.isGroupMember(username)) { - throw new DataRetrievalFailureException(userNotValid(username, - this.configuration.getAllowedGroupNames())); + throw new UsernameNotFoundException(userNotValid(username, this.configuration.getAllowedGroupNames())); } User user; try { @@ -107,20 +106,20 @@ public UserDetails loadUserByUsername(String username) throw new UsernameNotFoundException(userNotFound(username), ex); } catch (ApplicationPermissionException ex) { LOG.warning(applicationPermission()); - throw new DataRetrievalFailureException(applicationPermission(), ex); + throw new UsernameNotFoundException(applicationPermission(), ex); } catch (InvalidAuthenticationException ex) { LOG.warning(invalidAuthentication()); - throw new DataRetrievalFailureException(invalidAuthentication(), ex); + throw new UsernameNotFoundException(invalidAuthentication(), ex); } catch (OperationFailedException ex) { LOG.log(Level.SEVERE, operationFailed(), ex); - throw new DataRetrievalFailureException(operationFailed(), ex); + throw new UsernameNotFoundException(operationFailed(), ex); } // create the list of granted authorities List authorities = new ArrayList(); // add the "authenticated" authority to the list of granted // authorities... - authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY); + authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY2); // ..and all authorities retrieved from the Crowd server authorities.addAll(this.configuration.getAuthoritiesForUser(username)); diff --git a/src/test/java/de/theit/jenkins/crowd/CrowdUserDetailsServiceTest.java b/src/test/java/de/theit/jenkins/crowd/CrowdUserDetailsServiceTest.java index c9012f60..5e46d503 100644 --- a/src/test/java/de/theit/jenkins/crowd/CrowdUserDetailsServiceTest.java +++ b/src/test/java/de/theit/jenkins/crowd/CrowdUserDetailsServiceTest.java @@ -1,10 +1,9 @@ package de.theit.jenkins.crowd; -import org.acegisecurity.userdetails.UsernameNotFoundException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.assertj.core.api.Assertions; import org.junit.Test; import org.mockito.Mockito; -import org.springframework.dao.DataRetrievalFailureException; import com.atlassian.crowd.exception.ApplicationPermissionException; import com.atlassian.crowd.exception.InvalidAuthenticationException; @@ -17,8 +16,7 @@ public class CrowdUserDetailsServiceTest { public void testCrowdUserDetailsService() { CrowdConfigurationService config = Mockito.mock(CrowdConfigurationService.class); CrowdUserDetailsService s = new CrowdUserDetailsService(config); - Assertions.assertThatThrownBy(() -> s.loadUserByUsername("foo")) - .isInstanceOf(DataRetrievalFailureException.class); + Assertions.assertThatThrownBy(() -> s.loadUserByUsername("foo")).isInstanceOf(UsernameNotFoundException.class); } @@ -49,7 +47,7 @@ public void testLoadUserByUsernameEx2() throws UserNotFoundException, OperationF Mockito.when(config.isGroupMember("foo")).thenReturn(Boolean.TRUE); Mockito.when(config.getUser("foo")).thenThrow(ApplicationPermissionException.class); Assertions.assertThatThrownBy(() -> s.loadUserByUsername("foo")) - .isInstanceOf(DataRetrievalFailureException.class); + .isInstanceOf(UsernameNotFoundException.class); } @Test @@ -60,7 +58,7 @@ public void testLoadUserByUsernameEx3() throws UserNotFoundException, OperationF Mockito.when(config.isGroupMember("foo")).thenReturn(Boolean.TRUE); Mockito.when(config.getUser("foo")).thenThrow(InvalidAuthenticationException.class); Assertions.assertThatThrownBy(() -> s.loadUserByUsername("foo")) - .isInstanceOf(DataRetrievalFailureException.class); + .isInstanceOf(UsernameNotFoundException.class); } @Test @@ -70,7 +68,6 @@ public void testLoadUserByUsernameEx4() throws UserNotFoundException, OperationF CrowdUserDetailsService s = new CrowdUserDetailsService(config); Mockito.when(config.isGroupMember("foo")).thenReturn(Boolean.TRUE); Mockito.when(config.getUser("foo")).thenThrow(OperationFailedException.class); - Assertions.assertThatThrownBy(() -> s.loadUserByUsername("foo")) - .isInstanceOf(DataRetrievalFailureException.class); + Assertions.assertThatThrownBy(() -> s.loadUserByUsername("foo")).isInstanceOf(UsernameNotFoundException.class); } } From 20153d484475c3f408e814438ece259d54c06e74 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Thu, 21 Apr 2022 23:01:43 +0000 Subject: [PATCH 04/11] Update email resolver with latest dependencies --- .../crowd/CrowdMailAddressResolverImpl.java | 21 ++++++++----------- .../CrowdMailAddressResolverImplTest.java | 12 ++++++----- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImpl.java b/src/main/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImpl.java index 29e13fc6..881b3e6c 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImpl.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImpl.java @@ -28,14 +28,15 @@ import hudson.Extension; import hudson.model.User; import hudson.security.SecurityRealm; +import hudson.security.UserMayOrMayNotExistException2; import hudson.tasks.MailAddressResolver; import jenkins.model.Jenkins; import java.util.logging.Level; import java.util.logging.Logger; -import org.acegisecurity.userdetails.UsernameNotFoundException; -import org.springframework.dao.DataAccessException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + /** * This class resolves email addresses via lookup in Crowd. @@ -61,21 +62,17 @@ public String findMailAddressFor(User u) { if (realm instanceof CrowdSecurityRealm) { try { - String userId = getUserIdFromDisplayName(u); + String userId = u.getId(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("Looking up mail address for user: " + userId); } - CrowdUser details = (CrowdUser) realm.loadUserByUsername(userId); + CrowdUser details = (CrowdUser) realm.loadUserByUsername2(userId); mail = details.getEmailAddress(); + } catch (UserMayOrMayNotExistException2 ex) { + LOG.log(Level.SEVERE, "User do not exist, unable to look up email address", ex); } catch (UsernameNotFoundException ex) { - if (LOG.isLoggable(Level.INFO)) { - LOG.info("Failed to look up email address in Crowd"); - } - } catch (DataAccessException ex) { - LOG.log(Level.SEVERE, - "Access exception trying to look up email address in Crowd", - ex); + LOG.info("Failed to look up email address in Crowd"); } } @@ -95,7 +92,7 @@ public String findMailAddressFor(User u) { * @return the user id from display name */ String getUserIdFromDisplayName(User user) { - String userId = user.getId(); + String userId = user.getDisplayName(); int pos = userId.lastIndexOf('('); if (pos > 0) { int pos2 = userId.indexOf(')', pos + 1); diff --git a/src/test/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImplTest.java b/src/test/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImplTest.java index 6d50e18d..72949ee1 100644 --- a/src/test/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImplTest.java +++ b/src/test/java/de/theit/jenkins/crowd/CrowdMailAddressResolverImplTest.java @@ -12,12 +12,14 @@ public class CrowdMailAddressResolverImplTest { public void testGetUserIdFromDisplayName() { CrowdMailAddressResolverImpl res = new CrowdMailAddressResolverImpl(); User user = Mockito.mock(User.class); - Mockito.when(user.getId()).thenReturn("Foo Bar (baz)"); + Mockito.when(user.getDisplayName()).thenReturn("Foo Bar (baz)"); + Mockito.when(user.getId()).thenReturn("baz"); String userIdFromDisplayName1 = res.getUserIdFromDisplayName(user); Assertions.assertThat(userIdFromDisplayName1).isEqualTo("baz"); // should also work with arbitrary brackets in the username - Mockito.when(user.getId()).thenReturn("Foo) (Bar) :) (zap)"); + Mockito.when(user.getDisplayName()).thenReturn("Foo) (Bar) :) (zap)"); + Mockito.when(user.getId()).thenReturn("zap"); String userIdFromDisplayName2 = res.getUserIdFromDisplayName(user); Assertions.assertThat(userIdFromDisplayName2).isEqualTo("zap"); } @@ -44,10 +46,10 @@ protected SecurityRealm getSecurityRealm() { CrowdUser crowdUser = Mockito.mock(CrowdUser.class); Mockito.when(crowdUser.getEmailAddress()).thenReturn("foo@bar.baz"); - Mockito.when(r.loadUserByUsername("foo")).thenReturn(crowdUser); + Mockito.when(r.loadUserByUsername2("foo")).thenReturn(crowdUser); User user = Mockito.mock(User.class); - Mockito.when(user.getId()).thenReturn("Firstname Lastname (foo)"); - + Mockito.when(user.getDisplayName()).thenReturn("Firstname Lastname (foo)"); + Mockito.when(user.getId()).thenReturn("foo"); Assertions.assertThat(res.findMailAddressFor(user)).isEqualTo("foo@bar.baz"); } From f4aa6abf7a99773d8e6062aae9e05ebf8d654ce6 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Thu, 21 Apr 2022 23:33:08 +0000 Subject: [PATCH 05/11] Remove deprecations from token lib --- .../crowd/CrowdAuthenticationToken.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationToken.java b/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationToken.java index 171cf10e..ca3565f7 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationToken.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdAuthenticationToken.java @@ -28,9 +28,9 @@ import java.util.List; import jenkins.model.Jenkins; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.providers.AbstractAuthenticationToken; -import org.acegisecurity.userdetails.UserDetails; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.userdetails.UserDetails; import org.apache.commons.lang.StringUtils; /** @@ -68,8 +68,8 @@ public class CrowdAuthenticationToken extends AbstractAuthenticationToken { */ public CrowdAuthenticationToken(String pPrincipal, String pCredentials, List authorities, String pSsoToken) { - super(authorities.toArray(new GrantedAuthority[authorities.size()])); - this.principal = Jenkins.get().getSecurityRealm().loadUserByUsername(pPrincipal); + super(authorities); + this.principal = Jenkins.get().getSecurityRealm().loadUserByUsername2(pPrincipal); this.credentials = pCredentials; this.ssoToken = pSsoToken; super.setAuthenticated(true); @@ -78,7 +78,7 @@ public CrowdAuthenticationToken(String pPrincipal, String pCredentials, /** * {@inheritDoc} * - * @see org.acegisecurity.Authentication#getCredentials() + * @see org.springframework.security.core.Authentication#getCredentials() */ @Override public String getCredentials() { @@ -88,7 +88,7 @@ public String getCredentials() { /** * {@inheritDoc} * - * @see org.acegisecurity.Authentication#getPrincipal() + * @see org.springframework.security.core.Authentication#getPrincipal() */ @Override public UserDetails getPrincipal() { @@ -108,7 +108,7 @@ public String getSSOToken() { /** * {@inheritDoc} * - * @see org.acegisecurity.providers.AbstractAuthenticationToken#getName() + * @see org.springframework.security.authentication.AbstractAuthenticationToken#getName() */ @Override public String getName() { @@ -127,6 +127,6 @@ public static void updateUserInfo(com.atlassian.crowd.model.user.User user) { * Gets the corresponding {@link hudson.model.User} object. */ private static hudson.model.User getJenkinsUser(String username) { - return hudson.model.User.get(username); + return hudson.model.User.getById(username, false); } } From 3b3aeac2343a8034937d916932f901e7c40db4ae Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Thu, 21 Apr 2022 23:37:41 +0000 Subject: [PATCH 06/11] Breaking chnage - spring for remember me service got updated --- .../jenkins/crowd/CrowdRememberMeServices.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java b/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java index 0bea860d..ef2f532d 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java @@ -35,9 +35,9 @@ import com.atlassian.crowd.model.authentication.ValidationFactor; import com.atlassian.crowd.model.user.User; import hudson.security.SecurityRealm; -import org.acegisecurity.Authentication; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.ui.rememberme.RememberMeServices; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.authentication.RememberMeServices; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -83,7 +83,7 @@ public CrowdRememberMeServices(CrowdConfigurationService pConfiguration) { /** * {@inheritDoc} * - * @see org.acegisecurity.ui.rememberme.RememberMeServices#autoLogin(javax.servlet.http.HttpServletRequest, + * @see org.springframework.security.web.authentication.RememberMeServices#autoLogin(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override @@ -126,7 +126,7 @@ public Authentication autoLogin(HttpServletRequest request, // => create the user object and finalize the auto-login // process List authorities = new ArrayList(); - authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY); + authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY2); authorities.addAll(this.configuration.getAuthoritiesForUser(user.getName())); result = new CrowdAuthenticationToken(user.getName(), null, authorities, ssoToken); } @@ -147,7 +147,7 @@ public Authentication autoLogin(HttpServletRequest request, /** * {@inheritDoc} * - * @see org.acegisecurity.ui.rememberme.RememberMeServices#loginFail(javax.servlet.http.HttpServletRequest, + * @see org.springframework.security.web.authentication.RememberMeServices#loginFail(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override @@ -170,7 +170,7 @@ public void loginFail(HttpServletRequest request, /** * {@inheritDoc} * - * @see org.acegisecurity.ui.rememberme.RememberMeServices#loginSuccess(javax.servlet.http.HttpServletRequest, + * @see org.springframework.security.web.authentication.RememberMeServices#loginSuccess(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse, * org.acegisecurity.Authentication) */ From d937a61bf03a0a70d9901b1dae73bef16ba2d7dd Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Fri, 22 Apr 2022 00:00:31 +0000 Subject: [PATCH 07/11] MIgrate main security real class to new spring implementation --- .../jenkins/crowd/CrowdSecurityRealm.java | 83 ++++++++++++------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java b/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java index cd9463b7..f46a1a2a 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java @@ -45,23 +45,21 @@ import hudson.util.Secret; import jenkins.model.Jenkins; -import org.acegisecurity.AccountExpiredException; -import org.acegisecurity.AuthenticationException; -import org.acegisecurity.AuthenticationManager; -import org.acegisecurity.AuthenticationServiceException; -import org.acegisecurity.BadCredentialsException; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.InsufficientAuthenticationException; -import org.acegisecurity.userdetails.UserDetails; -import org.acegisecurity.userdetails.UserDetailsService; -import org.acegisecurity.userdetails.UsernameNotFoundException; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.verb.POST; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataRetrievalFailureException; import javax.servlet.Filter; import javax.servlet.FilterConfig; @@ -361,8 +359,8 @@ public void doLogout(StaplerRequest req, StaplerResponse rsp) if (useSSO) { if (realm instanceof CrowdSecurityRealm - && realm.getSecurityComponents().rememberMe instanceof CrowdRememberMeServices) { - ((CrowdRememberMeServices) realm.getSecurityComponents().rememberMe).logout(req, rsp); + && realm.getSecurityComponents().rememberMe2 instanceof CrowdRememberMeServices) { + ((CrowdRememberMeServices) realm.getSecurityComponents().rememberMe2).logout(req, rsp); } } @@ -395,20 +393,46 @@ public Filter createFilter(FilterConfig filterConfig) { * @see hudson.security.AbstractPasswordBasedSecurityRealm#loadUserByUsername(java.lang.String) */ @Override - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException, DataAccessException { + @Deprecated + public org.acegisecurity.userdetails.UserDetails loadUserByUsername(String username) + throws org.acegisecurity.userdetails.UsernameNotFoundException, + org.springframework.dao.DataAccessException { return getSecurityComponents().userDetails.loadUserByUsername(username); } + /** + * @deprecated use {@link #loadGroupByGroupname2} + * @since 1.549 + */ + @Deprecated + public GroupDetails loadGroupByGroupname(String groupname, boolean fetchMembers) throws org.acegisecurity.userdetails.UsernameNotFoundException, org.springframework.dao.DataAccessException { + try { + return loadGroupByGroupname2(groupname, fetchMembers); + } catch (AuthenticationException x) { + throw org.acegisecurity.AuthenticationException.fromSpring(x); + } + } + + /** + * {@inheritDoc} + * + * @see hudson.security.AbstractPasswordBasedSecurityRealm#loadUserByUsername2(java.lang.String) + */ + @Override + public UserDetails loadUserByUsername2(String username) throws UsernameNotFoundException { + return getSecurityComponents().userDetails2.loadUserByUsername(username); + } + /** * {@inheritDoc} * * @see hudson.security.SecurityRealm#loadGroupByGroupname(java.lang.String) */ @Override + @Deprecated public GroupDetails loadGroupByGroupname(String groupname) - throws UsernameNotFoundException, DataAccessException { - + throws org.acegisecurity.userdetails.UsernameNotFoundException, + org.springframework.dao.DataAccessException { try { // load the user object from the remote Crowd server if (LOG.isLoggable(Level.FINER)) { @@ -426,28 +450,31 @@ public String getName() { if (LOG.isLoggable(Level.INFO)) { LOG.info(groupNotFound(groupname)); } - throw new DataRetrievalFailureException(groupNotFound(groupname), ex); + throw new org.springframework.dao.DataAccessException(groupNotFound(groupname), ex); } catch (ApplicationPermissionException ex) { LOG.warning(applicationPermission()); - throw new DataRetrievalFailureException(applicationPermission(), ex); + throw new org.springframework.dao.DataAccessException(applicationPermission(), ex); } catch (InvalidAuthenticationException ex) { LOG.warning(invalidAuthentication()); - throw new DataRetrievalFailureException(invalidAuthentication(), ex); + throw new org.springframework.dao.DataAccessException(invalidAuthentication(), ex); } catch (OperationFailedException ex) { LOG.log(Level.SEVERE, operationFailed(), ex); - throw new DataRetrievalFailureException(operationFailed(), ex); + throw new org.springframework.dao.DataAccessException(operationFailed(), ex); } } + /** * {@inheritDoc} * * @see hudson.security.AbstractPasswordBasedSecurityRealm#authenticate(java.lang.String, * java.lang.String) + * This function maybe broken due to need of introducing breaking changes for its dependencies */ @Override - protected UserDetails authenticate(String pUsername, String pPassword) - throws AuthenticationException { + @Deprecated + protected org.acegisecurity.userdetails.UserDetails authenticate(String pUsername, String pPassword) + throws org.acegisecurity.AuthenticationException { // ensure that the group is available, active and that the user // is a member of it if (!this.configuration.isGroupMember(pUsername)) { @@ -494,11 +521,11 @@ protected UserDetails authenticate(String pUsername, String pPassword) List authorities = new ArrayList(); // add the "authenticated" authority to the list of granted // authorities... - authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY); + authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY2); // ..and all authorities retrieved from the Crowd server authorities.addAll(this.configuration.getAuthoritiesForUser(pUsername)); - return new CrowdUser(user, authorities); + return (org.acegisecurity.userdetails.UserDetails)(new CrowdUser(user, authorities)); } /** @@ -622,7 +649,7 @@ public FormValidation doCheckSessionValidationInterval( * @param password The application's password. * @param group The Crowd groups users have to belong to if * specified. - * @param useSSO Spcifies if SSO should be used + * @param useSSO Specifies if SSO should be used * @param cookieDomain The cookie domain * @param sessionValidationInterval The session validation interval * @param cookieTokenkey The cookie token key @@ -732,7 +759,7 @@ public ListBoxModel doFillSizeItems() { public ListBoxModel doFillTtlItems() { ListBoxModel m = new ListBoxModel(); - // TODO use Messages (not that there were any translations before) + // TODO: use Messages (not that there were any translations before) m.add("30 sec", "30"); m.add("1 min", "60"); m.add("2 min", "120"); From 9e9a1c76a3294667cd193d190aaf57eedf1a8dd9 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Fri, 22 Apr 2022 00:02:18 +0000 Subject: [PATCH 08/11] Add remaining fixes --- .gitpod.yml | 3 +-- .../crowd/CrowdConfigurationService.java | 8 +++---- .../jenkins/crowd/CrowdServletFilter.java | 24 +++++++++---------- .../crowd/CrowdUserDetailsService.java | 1 - 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index d0d58a04..e97fbfd3 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -9,11 +9,10 @@ tasks: sdk install java 8.0.322-tem sdk install java 11.0.14-tem sdk use maven 3.8.3 - brew install gh xmlstarlet + brew install gh vscode: extensions: - bierner.markdown-preview-github-styles - - github.vscode-pull-request-github - redhat.fabric8-analytics - redhat.java - redhat.vscode-commons diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java b/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java index 475a0683..0c8431de 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java @@ -47,8 +47,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.GrantedAuthorityImpl; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.apache.commons.lang.SystemUtils; import com.atlassian.crowd.exception.ApplicationAccessDeniedException; @@ -396,7 +396,7 @@ public int compare(GrantedAuthority ga1, // now create the list of authorities for (String str : groupNames) { - authorities.add(new GrantedAuthorityImpl(str)); + authorities.add(new SimpleGrantedAuthority(str)); } // If correct object was returned save it to cache @@ -748,7 +748,7 @@ public boolean isAuthenticated(HttpServletRequest httpServletRequest, HttpServle currentThread.setContextClassLoader(CrowdConfigurationService.class.getClassLoader()); } try { - return crowdHttpAuthenticator.isAuthenticated(httpServletRequest, httpServletResponse); + return crowdHttpAuthenticator.checkAuthenticated(httpServletRequest, httpServletResponse).isAuthenticated(); } finally { if (currentThread != null) { currentThread.setContextClassLoader(orgContextClassLoader); diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdServletFilter.java b/src/main/java/de/theit/jenkins/crowd/CrowdServletFilter.java index d91f4fdb..c30ef54d 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdServletFilter.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdServletFilter.java @@ -26,10 +26,11 @@ package de.theit.jenkins.crowd; import com.atlassian.crowd.exception.OperationFailedException; -import org.acegisecurity.Authentication; -import org.acegisecurity.context.SecurityContext; -import org.acegisecurity.context.SecurityContextHolder; -import org.acegisecurity.ui.rememberme.RememberMeServices; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.RememberMeServices; + import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -46,7 +47,7 @@ import java.util.logging.Logger; import static de.theit.jenkins.crowd.ErrorMessages.operationFailed; -import static org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY; +import static org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY; /** * This class realizes a servlet filter that checks on each request the status @@ -99,8 +100,8 @@ public CrowdServletFilter(CrowdSecurityRealm pSecurityRealm, this.configuration = pConfiguration; this.defaultFilter = pDefaultFilter; - if (this.securityRealm.getSecurityComponents().rememberMe instanceof CrowdRememberMeServices) { - this.rememberMe = (CrowdRememberMeServices) this.securityRealm.getSecurityComponents().rememberMe; + if (this.securityRealm.getSecurityComponents().rememberMe2 instanceof CrowdRememberMeServices) { + this.rememberMe = (CrowdRememberMeServices) this.securityRealm.getSecurityComponents().rememberMe2; } } @@ -141,6 +142,7 @@ public void doFilter(ServletRequest request, ServletResponse response, if (LOG.isLoggable(Level.FINE)) { LOG.fine("User is not logged in (anymore) via Crowd => logout user"); } + SecurityContext sc = SecurityContextHolder.getContext(); sc.setAuthentication(null); // close the SSO session @@ -157,8 +159,7 @@ public void doFilter(ServletRequest request, ServletResponse response, SecurityContextHolder.clearContext(); // reset remember-me cookie - Cookie cookie = new Cookie( - ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, ""); + Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, ""); cookie.setHttpOnly(true); cookie.setSecure(true); cookie.setPath(req.getContextPath().length() > 0 ? req @@ -175,11 +176,10 @@ public void doFilter(ServletRequest request, ServletResponse response, if (LOG.isLoggable(Level.FINE)) { LOG.fine("User is logged in via Crowd, but no authentication token available; trying auto-login..."); } - Authentication auth = this.rememberMe.autoLogin(req, - res); + Authentication auth = this.rememberMe.autoLogin(req, res); if (null != auth) { if (LOG.isLoggable(Level.FINE)) { - LOG.fine("User sucessfully logged in"); + LOG.fine("User successfully logged in"); } sc.setAuthentication(auth); } diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java b/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java index f97cdd56..fa3e82a4 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdUserDetailsService.java @@ -38,7 +38,6 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; From 1ae075cf0825794e4d069ac699fe3ea3464a3fbc Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Fri, 22 Apr 2022 00:08:43 +0000 Subject: [PATCH 09/11] Bump plugin version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71e894bf..e51f6f1a 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ - 2.2.1 + 3.0.0 -SNAPSHOT jenkinsci/crowd2-plugin 2.303.1 From 3b281498e82d369b599567c896ad6f8c394de97e Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Fri, 22 Apr 2022 00:18:45 +0000 Subject: [PATCH 10/11] Fix small bug used for casting --- README.md | 2 +- .../de/theit/jenkins/crowd/CrowdSecurityRealm.java | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9b409e51..0c590ad6 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ The following changes and improvements are planned for the following releases ### 2.3.0 -* [ ] Update to latest libs +* [x] Update to latest libs ### 3.x.x diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java b/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java index f46a1a2a..ba61559e 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java @@ -463,18 +463,16 @@ public String getName() { } } - /** * {@inheritDoc} * - * @see hudson.security.AbstractPasswordBasedSecurityRealm#authenticate(java.lang.String, + * @see hudson.security.AbstractPasswordBasedSecurityRealm#authenticate2(java.lang.String, * java.lang.String) - * This function maybe broken due to need of introducing breaking changes for its dependencies + * */ @Override - @Deprecated - protected org.acegisecurity.userdetails.UserDetails authenticate(String pUsername, String pPassword) - throws org.acegisecurity.AuthenticationException { + protected UserDetails authenticate2(String pUsername, String pPassword) + throws AuthenticationException { // ensure that the group is available, active and that the user // is a member of it if (!this.configuration.isGroupMember(pUsername)) { @@ -525,7 +523,7 @@ protected org.acegisecurity.userdetails.UserDetails authenticate(String pUsernam // ..and all authorities retrieved from the Crowd server authorities.addAll(this.configuration.getAuthoritiesForUser(pUsername)); - return (org.acegisecurity.userdetails.UserDetails)(new CrowdUser(user, authorities)); + return new CrowdUser(user, authorities); } /** From 642f6e60bdba86a1e1bb0845b235f31cef361438 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak <9051964+DuMaM@users.noreply.github> Date: Fri, 22 Apr 2022 00:25:16 +0000 Subject: [PATCH 11/11] Update remaining docs --- .../jenkins/crowd/CrowdRememberMeServices.java | 2 +- .../java/de/theit/jenkins/crowd/CrowdUser.java | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java b/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java index ef2f532d..c5f1f8cb 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdRememberMeServices.java @@ -172,7 +172,7 @@ public void loginFail(HttpServletRequest request, * * @see org.springframework.security.web.authentication.RememberMeServices#loginSuccess(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse, - * org.acegisecurity.Authentication) + * org.springframework.security.core.Authentication) */ @Override public void loginSuccess(HttpServletRequest request, diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdUser.java b/src/main/java/de/theit/jenkins/crowd/CrowdUser.java index 5a91188f..5d0d414e 100644 --- a/src/main/java/de/theit/jenkins/crowd/CrowdUser.java +++ b/src/main/java/de/theit/jenkins/crowd/CrowdUser.java @@ -66,7 +66,7 @@ public CrowdUser(User pUser, List authorities) { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetails#getAuthorities() + * @see org.springframework.security.core.userdetails.UserDetails#getAuthorities() */ @Override public Collection getAuthorities() { @@ -76,7 +76,7 @@ public Collection getAuthorities() { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetails#getPassword() + * @see org.springframework.security.core.userdetails.UserDetails#getPassword() */ @Override public String getPassword() { @@ -86,7 +86,7 @@ public String getPassword() { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetails#getUsername() + * @see org.springframework.security.core.userdetails.UserDetails#getUsername() */ @Override public String getUsername() { @@ -96,7 +96,7 @@ public String getUsername() { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetails#isAccountNonExpired() + * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonExpired() */ @Override public boolean isAccountNonExpired() { @@ -106,7 +106,7 @@ public boolean isAccountNonExpired() { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetails#isAccountNonLocked() + * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonLocked() */ @Override public boolean isAccountNonLocked() { @@ -116,7 +116,7 @@ public boolean isAccountNonLocked() { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetails#isCredentialsNonExpired() + * @see org.springframework.security.core.userdetails.UserDetails#isCredentialsNonExpired() */ @Override public boolean isCredentialsNonExpired() { @@ -126,7 +126,7 @@ public boolean isCredentialsNonExpired() { /** * {@inheritDoc} * - * @see org.acegisecurity.userdetails.UserDetails#isEnabled() + * @see org.springframework.security.core.userdetails.UserDetails#isEnabled() */ @Override public boolean isEnabled() {