Skip to content

Commit

Permalink
feat: update the plugin to use Spring framework classes
Browse files Browse the repository at this point in the history
  • Loading branch information
kuisathaverat committed Aug 29, 2022
1 parent 63dd103 commit 5149dd8
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@

package org.jenkinsci.plugins.saml;

import org.acegisecurity.providers.AbstractAuthenticationToken;

import javax.annotation.Nonnull;
import org.springframework.security.authentication.AbstractAuthenticationToken;

/**
* @see org.acegisecurity.Authentication
* @see AbstractAuthenticationToken
*/
public final class SamlAuthenticationToken extends AbstractAuthenticationToken {

Expand Down
43 changes: 0 additions & 43 deletions src/main/java/org/jenkinsci/plugins/saml/SamlGroupAuthority.java

This file was deleted.

16 changes: 5 additions & 11 deletions src/main/java/org/jenkinsci/plugins/saml/SamlGroupDetails.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@
under the License. */
package org.jenkinsci.plugins.saml;

import java.util.HashSet;
import java.util.Set;
import hudson.model.User;
import hudson.security.GroupDetails;
import jenkins.security.LastGrantedAuthoritiesProperty;
import org.acegisecurity.GrantedAuthority;

import java.util.HashSet;
import java.util.Set;


/**
Expand Down Expand Up @@ -52,23 +50,19 @@ public String getDisplayName() {
@Override
public Set<String> getMembers() {
if (members.isEmpty()) {
for (User u : User.getAll()) {
User.getAll().forEach(u -> {
LastGrantedAuthoritiesProperty prop = u.getProperty(LastGrantedAuthoritiesProperty.class);
if (hasGroupOnAuthorities(prop)) {
members.add(u.getId());
}
}
});
}
return members;
}

private boolean hasGroupOnAuthorities(LastGrantedAuthoritiesProperty prop) {
if (prop != null) {
for (GrantedAuthority a : prop.getAuthorities()) {
if (name.equals(a.getAuthority())) {
return true;
}
}
return prop.getAuthorities2().stream().anyMatch(a -> name.equals(a.getAuthority()));
}
return false;
}
Expand Down
97 changes: 56 additions & 41 deletions src/main/java/org/jenkinsci/plugins/saml/SamlSecurityRealm.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@

package org.jenkinsci.plugins.saml;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.servlet.http.HttpSession;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.Util;
import hudson.security.GroupDetails;
import hudson.security.UserMayOrMayNotExistException;
import hudson.util.FormValidation;
import hudson.model.Descriptor;
import hudson.model.User;
import hudson.security.SecurityRealm;
import hudson.tasks.Mailer.UserProperty;
import jenkins.model.Jenkins;
import jenkins.security.SecurityListener;
import org.acegisecurity.*;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.Authentication;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
Expand All @@ -39,23 +37,35 @@
import org.jenkinsci.plugins.saml.user.SamlCustomProperty;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.*;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.Header;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import org.pac4j.core.redirect.RedirectAction;
import org.pac4j.core.redirect.RedirectAction.RedirectType;
import org.springframework.dao.DataAccessException;
import org.pac4j.saml.profile.SAML2Profile;

import javax.annotation.Nonnull;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.apache.commons.codec.binary.Base64.*;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import hudson.Extension;
import hudson.Util;
import hudson.model.Descriptor;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.GroupDetails;
import hudson.security.SecurityRealm;
import hudson.security.UserMayOrMayNotExistException2;
import hudson.tasks.Mailer.UserProperty;
import hudson.util.FormValidation;
import jenkins.model.Jenkins;
import jenkins.security.SecurityListener;
import static org.apache.commons.codec.binary.Base64.decodeBase64;
import static org.apache.commons.codec.binary.Base64.isBase64;
import static org.opensaml.saml.common.xml.SAMLConstants.SAML2_REDIRECT_BINDING_URI;

/**
Expand Down Expand Up @@ -225,15 +235,11 @@ public boolean allowsSignup() {
@Override
public SecurityComponents createSecurityComponents() {
LOG.finer("createSecurityComponents");
return new SecurityComponents(new AuthenticationManager() {

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (authentication instanceof SamlAuthenticationToken) {
return authentication;
}
throw new BadCredentialsException("Unexpected authentication type: " + authentication);
return new SecurityComponents(authentication -> {
if (authentication instanceof SamlAuthenticationToken) {
return authentication;
}

throw new BadCredentialsException("Unexpected authentication type: " + authentication);
}, new SamlUserDetailsService());
}

Expand Down Expand Up @@ -326,13 +332,12 @@ public HttpResponse doFinishLogin(final StaplerRequest request, final StaplerRes
List<GrantedAuthority> authorities = loadGrantedAuthorities(saml2Profile);

// create user data
SamlUserDetails userDetails = new SamlUserDetails(username, authorities.toArray(new GrantedAuthority[authorities.size()]));
SamlUserDetails userDetails = new SamlUserDetails(username, authorities);

SamlAuthenticationToken samlAuthToken = new SamlAuthenticationToken(userDetails);

// initialize security context
SecurityContextHolder.getContext().setAuthentication(samlAuthToken);
SecurityListener.fireAuthenticated(userDetails);
ACL.as2(samlAuthToken);
SecurityListener.fireAuthenticated2(userDetails);
User user = User.current();

saveUser |= modifyUserFullName(user, saml2Profile);
Expand Down Expand Up @@ -499,11 +504,11 @@ List<GrantedAuthority> loadGrantedAuthorities(SAML2Profile saml2Profile) {

// build list of authorities
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(AUTHENTICATED_AUTHORITY);
authorities.add(AUTHENTICATED_AUTHORITY2);
int countEmptyGroups = 0;
for (String group : groups) {
if (StringUtils.isNotBlank(group)) {
authorities.add(new SamlGroupAuthority(group));
authorities.add(new SimpleGrantedAuthority(group));
} else {
countEmptyGroups++;
}
Expand Down Expand Up @@ -620,16 +625,26 @@ public void doLogout(StaplerRequest req, StaplerResponse rsp) throws IOException
LOG.log(Level.FINEST, "Here we could do the SAML Single Logout");
}

/**
* This method is overwritten due to SAML has no way to retrieve the members of a Group and this cause issues on
* some Authorization plugins. Because of that we have to implement SamlGroupDetails
*/
@SuppressWarnings("deprecation")
@Override
public GroupDetails loadGroupByGroupname(String groupname) throws UsernameNotFoundException, DataAccessException {
GroupDetails dg = new SamlGroupDetails(groupname);

if (dg.getMembers().isEmpty()) {
throw new UserMayOrMayNotExistException(groupname);
throw new UserMayOrMayNotExistException2(groupname);
}
return dg;
}

/**
* This method is overwritten due to SAML has no way to retrieve the members of a Group and this cause issues on
* some Authorization plugins. Because of that we have to implement SamlGroupDetails
*/
@SuppressWarnings("deprecation")
@Override
public GroupDetails loadGroupByGroupname(String groupname, boolean fetchMembers)
throws UsernameNotFoundException, DataAccessException {
Expand Down
18 changes: 9 additions & 9 deletions src/main/java/org/jenkinsci/plugins/saml/SamlUserDetails.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@

package org.jenkinsci.plugins.saml;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetails;

import java.util.Collection;
import java.util.Collections;
import javax.annotation.Nonnull;
import java.util.Arrays;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

/**
* @see UserDetails
Expand All @@ -31,15 +31,15 @@ public class SamlUserDetails implements UserDetails {
private static final long serialVersionUID = 2L;

private final String username;
private final GrantedAuthority[] authorities;
private final Collection<GrantedAuthority> authorities;

public SamlUserDetails(@Nonnull String username, GrantedAuthority[] authorities) {
public SamlUserDetails(@Nonnull String username, Collection<GrantedAuthority> authorities) {
this.username = username;
this.authorities = Arrays.copyOf(authorities, authorities.length);
this.authorities = Collections.unmodifiableCollection(authorities);
}

public GrantedAuthority[] getAuthorities() {
return Arrays.copyOf(authorities, authorities.length);
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}

public String getPassword() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@

package org.jenkinsci.plugins.saml;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import hudson.model.User;
import hudson.security.SecurityRealm;
import hudson.security.UserMayOrMayNotExistException2;
import jenkins.model.Jenkins;
import jenkins.security.LastGrantedAuthoritiesProperty;
import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetailsService;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* This service is responsible for restoring UserDetails object by userId
Expand All @@ -41,7 +41,7 @@ public class SamlUserDetailsService implements UserDetailsService {
public SamlUserDetails loadUserByUsername(@Nonnull String username) {

// try to obtain user details from current authentication details
Authentication auth = Jenkins.getAuthentication();
Authentication auth = Jenkins.getAuthentication2();
if (username.compareTo(auth.getName()) == 0 && auth instanceof SamlAuthenticationToken) {
return (SamlUserDetails) auth.getDetails();
}
Expand All @@ -53,20 +53,20 @@ public SamlUserDetails loadUserByUsername(@Nonnull String username) {
throw new UserMayOrMayNotExistException2(username);
}

List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY);
List<GrantedAuthority>authorities = new ArrayList<>();
authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY2);

if (username.compareTo(user.getId()) == 0) {
LastGrantedAuthoritiesProperty lastGranted = user.getProperty(LastGrantedAuthoritiesProperty.class);
if (lastGranted != null) {
for (GrantedAuthority a : lastGranted.getAuthorities()) {
if (a != SecurityRealm.AUTHENTICATED_AUTHORITY) {
SamlGroupAuthority ga = new SamlGroupAuthority(a.getAuthority());
for (GrantedAuthority a : lastGranted.getAuthorities2()) {
if (a != SecurityRealm.AUTHENTICATED_AUTHORITY2) {
SimpleGrantedAuthority ga = new SimpleGrantedAuthority(a.getAuthority());
authorities.add(ga);
}
}
}
}
return new SamlUserDetails(user.getId(), authorities.toArray(new GrantedAuthority[0]));
return new SamlUserDetails(user.getId(), authorities);
}
}
Loading

0 comments on commit 5149dd8

Please sign in to comment.