Loading projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java +0 −16 Original line number Diff line number Diff line Loading @@ -174,20 +174,4 @@ public interface GroupPersistence<T extends Principal> throws UserNotFoundException, GroupNotFoundException, TransientException, AccessControlException; /** * Check whether the user is a member of the group. * * @param userID The userID. * @param groupID The groupID. * * @return true or false * * @throws UserNotFoundException If the user is not found. * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ boolean isMember(T userID, String groupID) throws UserNotFoundException, TransientException, AccessControlException; } projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java +4 −2 Original line number Diff line number Diff line Loading @@ -127,6 +127,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO private LdapUserDAO<T> userPersist; // this gets filled by the LdapgroupPersistence GroupDetailSelector searchDetailSelector; public LdapGroupDAO(LdapConfig config, LdapUserDAO<T> userPersist) { super(config); Loading Loading @@ -811,8 +814,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } throw new RuntimeException("BUG: failed to extract group name from " + groupDN.toString()); } // this gets filled by the LdapgroupPersistence GroupDetailSelector searchDetailSelector; private boolean isDetailedSearch(Group g, Role r) { Loading projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java +2 −11 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ public class LdapGroupPersistence<T extends Principal> config = LdapConfig.getLdapConfig(); } protected void setDetailSelector(GroupDetailSelector gds) public void setDetailSelector(GroupDetailSelector gds) { this.detailSelector = gds; } Loading Loading @@ -257,13 +257,4 @@ public class LdapGroupPersistence<T extends Principal> } } } public boolean isMember(T userID, String groupID) throws UserNotFoundException, TransientException, AccessControlException { return (new LdapUserPersistence<T>()).isMember(userID, groupID); } } projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/LoginServlet.java +159 −8 Original line number Diff line number Diff line Loading @@ -70,17 +70,30 @@ package ca.nrc.cadc.ac.server.web; import java.io.IOException; import java.security.AccessControlException; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import javax.security.auth.Subject; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.Role; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.server.GroupDetailSelector; import ca.nrc.cadc.ac.server.UserPersistence; import ca.nrc.cadc.ac.server.ldap.LdapGroupPersistence; import ca.nrc.cadc.ac.server.ldap.LdapUserPersistence; import ca.nrc.cadc.auth.AuthenticatorImpl; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.auth.SSOCookieManager; import ca.nrc.cadc.log.ServletLogInfo; import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.util.StringUtil; @SuppressWarnings("serial") Loading @@ -88,6 +101,33 @@ public class LoginServlet extends HttpServlet { private static final Logger log = Logger.getLogger(LoginServlet.class); private static final String CONTENT_TYPE = "text/plain"; // " as " - delimiter use for proxy user authentication public static final String PROXY_USER_DELIM = "\\s[aA][sS]\\s"; String proxyGroup; // only users in this group can impersonate other users String nonImpersonGroup; // users in this group cannot be impersonated private static final String PROXY_ACCESS = "Proxy user access: "; @Override public void init(final ServletConfig config) throws ServletException { super.init(config); try { this.proxyGroup = config.getInitParameter( LoginServlet.class.getName() + ".proxyGroup"); log.info("proxyGroup: " + proxyGroup); this.nonImpersonGroup = config.getInitParameter( LoginServlet.class.getName() + ".nonImpersonGroup"); log.info("nonImpersonGroup: " + nonImpersonGroup); } catch(Exception ex) { log.error("failed to init: " + ex); } } /** * Attempt to login for userid/password. */ Loading @@ -100,15 +140,29 @@ public class LoginServlet extends HttpServlet try { log.info(logInfo.start()); String userID = request.getParameter("username"); String userID = request.getParameter("username").trim(); String proxyUser = null; String[] fields = userID.split(PROXY_USER_DELIM); if (fields.length == 2 ) { proxyUser = fields[0].trim(); userID = fields[1].trim(); checkCanImpersonate(userID, proxyUser); } String password = request.getParameter("password"); UserPersistence up = new LdapUserPersistence(); if (StringUtil.hasText(userID)) { if (StringUtil.hasText(password)) { if (new LdapUserPersistence().doLogin(userID, password)) if ((StringUtil.hasText(proxyUser) && up.doLogin(proxyUser, password)) || (!StringUtil.hasText(proxyUser) && up.doLogin(userID, password))) { String token = new SSOCookieManager().generate(new HttpPrincipal(userID)); String token = new SSOCookieManager().generate( new HttpPrincipal(userID, proxyUser)); response.setContentType(CONTENT_TYPE); response.setContentLength(token.length()); response.getWriter().write(token); Loading @@ -126,16 +180,24 @@ public class LoginServlet extends HttpServlet } catch (IllegalArgumentException e) { log.debug(e.getMessage(), e); logInfo.setMessage(e.getMessage()); String msg = e.getMessage(); if (msg.startsWith(PROXY_ACCESS)) { log.warn(msg, e); } else { log.debug(msg, e); } logInfo.setMessage(msg); response.setContentType(CONTENT_TYPE); response.getWriter().write(e.getMessage()); response.getWriter().write(msg); response.setStatus(400); } catch (AccessControlException e) { log.debug(e.getMessage(), e); String message = "Invalid credentials"; String message = e.getMessage(); logInfo.setMessage(message); response.setContentType(CONTENT_TYPE); response.getWriter().write(message); Loading @@ -157,4 +219,93 @@ public class LoginServlet extends HttpServlet log.info(logInfo.end()); } } /** * Checks if user can impersonate another user */ protected void checkCanImpersonate(final String userID, final String proxyUser) throws AccessControlException, UserNotFoundException, TransientException, Throwable { final LdapGroupPersistence<HttpPrincipal> gp = getLdapGroupPersistence(); // Users (proxy and the user to be impersonated) are not authenticated // at this point so in order to make the calls to check their group // membership we need to create corresponding subjects and run the // get groups command in the corresponding subject context. AuthenticatorImpl ai = new AuthenticatorImpl(); Subject proxySubject = new Subject(); proxySubject.getPrincipals().add(new HttpPrincipal(proxyUser)); ai.augmentSubject(proxySubject); try { Subject.doAs(proxySubject, new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { if (gp.getGroups(new HttpPrincipal(proxyUser), Role.MEMBER, proxyGroup).size() == 0) { throw new AccessControlException(PROXY_ACCESS + proxyUser + " as " + userID + " failed - not allowed to impersonate (" + proxyUser + " not in " + proxyGroup + " group)"); } return null; } }); Subject userSubject = new Subject(); userSubject.getPrincipals().add(new HttpPrincipal(userID)); ai.augmentSubject(userSubject); Subject.doAs(userSubject, new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { if (gp.getGroups(new HttpPrincipal(userID), Role.MEMBER, nonImpersonGroup).size() != 0) { throw new AccessControlException(PROXY_ACCESS + proxyUser + " as " + userID + " failed - non impersonable (" + userID + " in " + nonImpersonGroup + " group)"); } return null; } }); } catch (PrivilegedActionException e) { Throwable cause = e.getCause(); if (cause != null) { throw cause; } Exception exception = e.getException(); if (exception != null) { throw exception; } throw e; } } protected LdapGroupPersistence<HttpPrincipal> getLdapGroupPersistence() { LdapGroupPersistence<HttpPrincipal> gp = new LdapGroupPersistence<HttpPrincipal>(); gp.setDetailSelector(new GroupDetailSelector() { @Override public boolean isDetailedSearch(Group g, Role r) { return false; } }); return gp; } } projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/WhoAmIServlet.java +5 −3 Original line number Diff line number Diff line Loading @@ -126,7 +126,7 @@ public class WhoAmIServlet extends HttpServlet else { redirect(response, currentWebPrincipals.toArray( new HttpPrincipal[1])[0]); new HttpPrincipal[1])[0], request.getScheme()); } } catch (IllegalArgumentException e) Loading Loading @@ -155,14 +155,16 @@ public class WhoAmIServlet extends HttpServlet * * @param response The HTTP response. * @param webPrincipal The HttpPrincipal instance. * @param scheme The scheme */ void redirect(final HttpServletResponse response, final HttpPrincipal webPrincipal) throws IOException final HttpPrincipal webPrincipal, final String scheme) throws IOException { final RegistryClient registryClient = getRegistryClient(); final URL redirectURL = registryClient.getServiceURL( URI.create(AC.GMS_SERVICE_URI), "https", USER_GET_PATH); URI.create(AC.GMS_SERVICE_URI), scheme, USER_GET_PATH); // Take the first one. final String redirectUrl = Loading Loading
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java +0 −16 Original line number Diff line number Diff line Loading @@ -174,20 +174,4 @@ public interface GroupPersistence<T extends Principal> throws UserNotFoundException, GroupNotFoundException, TransientException, AccessControlException; /** * Check whether the user is a member of the group. * * @param userID The userID. * @param groupID The groupID. * * @return true or false * * @throws UserNotFoundException If the user is not found. * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ boolean isMember(T userID, String groupID) throws UserNotFoundException, TransientException, AccessControlException; }
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java +4 −2 Original line number Diff line number Diff line Loading @@ -127,6 +127,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO private LdapUserDAO<T> userPersist; // this gets filled by the LdapgroupPersistence GroupDetailSelector searchDetailSelector; public LdapGroupDAO(LdapConfig config, LdapUserDAO<T> userPersist) { super(config); Loading Loading @@ -811,8 +814,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } throw new RuntimeException("BUG: failed to extract group name from " + groupDN.toString()); } // this gets filled by the LdapgroupPersistence GroupDetailSelector searchDetailSelector; private boolean isDetailedSearch(Group g, Role r) { Loading
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java +2 −11 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ public class LdapGroupPersistence<T extends Principal> config = LdapConfig.getLdapConfig(); } protected void setDetailSelector(GroupDetailSelector gds) public void setDetailSelector(GroupDetailSelector gds) { this.detailSelector = gds; } Loading Loading @@ -257,13 +257,4 @@ public class LdapGroupPersistence<T extends Principal> } } } public boolean isMember(T userID, String groupID) throws UserNotFoundException, TransientException, AccessControlException { return (new LdapUserPersistence<T>()).isMember(userID, groupID); } }
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/LoginServlet.java +159 −8 Original line number Diff line number Diff line Loading @@ -70,17 +70,30 @@ package ca.nrc.cadc.ac.server.web; import java.io.IOException; import java.security.AccessControlException; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import javax.security.auth.Subject; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.Role; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.server.GroupDetailSelector; import ca.nrc.cadc.ac.server.UserPersistence; import ca.nrc.cadc.ac.server.ldap.LdapGroupPersistence; import ca.nrc.cadc.ac.server.ldap.LdapUserPersistence; import ca.nrc.cadc.auth.AuthenticatorImpl; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.auth.SSOCookieManager; import ca.nrc.cadc.log.ServletLogInfo; import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.util.StringUtil; @SuppressWarnings("serial") Loading @@ -88,6 +101,33 @@ public class LoginServlet extends HttpServlet { private static final Logger log = Logger.getLogger(LoginServlet.class); private static final String CONTENT_TYPE = "text/plain"; // " as " - delimiter use for proxy user authentication public static final String PROXY_USER_DELIM = "\\s[aA][sS]\\s"; String proxyGroup; // only users in this group can impersonate other users String nonImpersonGroup; // users in this group cannot be impersonated private static final String PROXY_ACCESS = "Proxy user access: "; @Override public void init(final ServletConfig config) throws ServletException { super.init(config); try { this.proxyGroup = config.getInitParameter( LoginServlet.class.getName() + ".proxyGroup"); log.info("proxyGroup: " + proxyGroup); this.nonImpersonGroup = config.getInitParameter( LoginServlet.class.getName() + ".nonImpersonGroup"); log.info("nonImpersonGroup: " + nonImpersonGroup); } catch(Exception ex) { log.error("failed to init: " + ex); } } /** * Attempt to login for userid/password. */ Loading @@ -100,15 +140,29 @@ public class LoginServlet extends HttpServlet try { log.info(logInfo.start()); String userID = request.getParameter("username"); String userID = request.getParameter("username").trim(); String proxyUser = null; String[] fields = userID.split(PROXY_USER_DELIM); if (fields.length == 2 ) { proxyUser = fields[0].trim(); userID = fields[1].trim(); checkCanImpersonate(userID, proxyUser); } String password = request.getParameter("password"); UserPersistence up = new LdapUserPersistence(); if (StringUtil.hasText(userID)) { if (StringUtil.hasText(password)) { if (new LdapUserPersistence().doLogin(userID, password)) if ((StringUtil.hasText(proxyUser) && up.doLogin(proxyUser, password)) || (!StringUtil.hasText(proxyUser) && up.doLogin(userID, password))) { String token = new SSOCookieManager().generate(new HttpPrincipal(userID)); String token = new SSOCookieManager().generate( new HttpPrincipal(userID, proxyUser)); response.setContentType(CONTENT_TYPE); response.setContentLength(token.length()); response.getWriter().write(token); Loading @@ -126,16 +180,24 @@ public class LoginServlet extends HttpServlet } catch (IllegalArgumentException e) { log.debug(e.getMessage(), e); logInfo.setMessage(e.getMessage()); String msg = e.getMessage(); if (msg.startsWith(PROXY_ACCESS)) { log.warn(msg, e); } else { log.debug(msg, e); } logInfo.setMessage(msg); response.setContentType(CONTENT_TYPE); response.getWriter().write(e.getMessage()); response.getWriter().write(msg); response.setStatus(400); } catch (AccessControlException e) { log.debug(e.getMessage(), e); String message = "Invalid credentials"; String message = e.getMessage(); logInfo.setMessage(message); response.setContentType(CONTENT_TYPE); response.getWriter().write(message); Loading @@ -157,4 +219,93 @@ public class LoginServlet extends HttpServlet log.info(logInfo.end()); } } /** * Checks if user can impersonate another user */ protected void checkCanImpersonate(final String userID, final String proxyUser) throws AccessControlException, UserNotFoundException, TransientException, Throwable { final LdapGroupPersistence<HttpPrincipal> gp = getLdapGroupPersistence(); // Users (proxy and the user to be impersonated) are not authenticated // at this point so in order to make the calls to check their group // membership we need to create corresponding subjects and run the // get groups command in the corresponding subject context. AuthenticatorImpl ai = new AuthenticatorImpl(); Subject proxySubject = new Subject(); proxySubject.getPrincipals().add(new HttpPrincipal(proxyUser)); ai.augmentSubject(proxySubject); try { Subject.doAs(proxySubject, new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { if (gp.getGroups(new HttpPrincipal(proxyUser), Role.MEMBER, proxyGroup).size() == 0) { throw new AccessControlException(PROXY_ACCESS + proxyUser + " as " + userID + " failed - not allowed to impersonate (" + proxyUser + " not in " + proxyGroup + " group)"); } return null; } }); Subject userSubject = new Subject(); userSubject.getPrincipals().add(new HttpPrincipal(userID)); ai.augmentSubject(userSubject); Subject.doAs(userSubject, new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { if (gp.getGroups(new HttpPrincipal(userID), Role.MEMBER, nonImpersonGroup).size() != 0) { throw new AccessControlException(PROXY_ACCESS + proxyUser + " as " + userID + " failed - non impersonable (" + userID + " in " + nonImpersonGroup + " group)"); } return null; } }); } catch (PrivilegedActionException e) { Throwable cause = e.getCause(); if (cause != null) { throw cause; } Exception exception = e.getException(); if (exception != null) { throw exception; } throw e; } } protected LdapGroupPersistence<HttpPrincipal> getLdapGroupPersistence() { LdapGroupPersistence<HttpPrincipal> gp = new LdapGroupPersistence<HttpPrincipal>(); gp.setDetailSelector(new GroupDetailSelector() { @Override public boolean isDetailedSearch(Group g, Role r) { return false; } }); return gp; } }
projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/WhoAmIServlet.java +5 −3 Original line number Diff line number Diff line Loading @@ -126,7 +126,7 @@ public class WhoAmIServlet extends HttpServlet else { redirect(response, currentWebPrincipals.toArray( new HttpPrincipal[1])[0]); new HttpPrincipal[1])[0], request.getScheme()); } } catch (IllegalArgumentException e) Loading Loading @@ -155,14 +155,16 @@ public class WhoAmIServlet extends HttpServlet * * @param response The HTTP response. * @param webPrincipal The HttpPrincipal instance. * @param scheme The scheme */ void redirect(final HttpServletResponse response, final HttpPrincipal webPrincipal) throws IOException final HttpPrincipal webPrincipal, final String scheme) throws IOException { final RegistryClient registryClient = getRegistryClient(); final URL redirectURL = registryClient.getServiceURL( URI.create(AC.GMS_SERVICE_URI), "https", USER_GET_PATH); URI.create(AC.GMS_SERVICE_URI), scheme, USER_GET_PATH); // Take the first one. final String redirectUrl = Loading