package hudson.plugins.collabnet.auth; import com.collabnet.ce.webservices.CollabNetApp; import groovy.lang.Binding; import hudson.Extension; import hudson.model.Descriptor; import hudson.model.Hudson; import hudson.plugins.collabnet.util.CNHudsonUtil; import hudson.security.SecurityRealm; import hudson.util.FormValidation; import hudson.util.VersionNumber; import hudson.util.spring.BeanBuilder; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.springframework.web.context.WebApplicationContext; import javax.servlet.Filter; import javax.servlet.FilterConfig; import java.io.IOException; import java.rmi.RemoteException; import java.util.logging.Level; import java.util.logging.Logger; public class CollabNetSecurityRealm extends SecurityRealm { private String collabNetUrl; /* viewing hudson page from CTF linked app should login to hudson */ private boolean mEnableSSOAuthFromCTF; /* logging in to hudson should login to CTF */ private boolean mEnableSSOAuthToCTF; private boolean mEnableSSORedirect = true; @DataBoundConstructor public CollabNetSecurityRealm(String collabNetUrl, boolean enableSSOAuthFromCTF, boolean enableSSOAuthToCTF) { this.collabNetUrl = CNHudsonUtil.sanitizeCollabNetUrl(collabNetUrl); this.mEnableSSOAuthFromCTF = enableSSOAuthFromCTF; this.mEnableSSOAuthToCTF = enableSSOAuthToCTF; CollabNetApp cn = new CollabNetApp(this.collabNetUrl); try { VersionNumber apiVersion = new VersionNumber(cn.getApiVersion()); if (apiVersion.compareTo(new VersionNumber("5.3.0.0")) >= 0) { // starting with CTF 5.3, redirect no longer works after login mEnableSSORedirect = false; } } catch (RemoteException re) { // ignore LOGGER.log(Level.WARNING, "Failed to retrieve the CTF version from "+this.collabNetUrl,re); } } public String getCollabNetUrl() { return this.collabNetUrl; } /** * Single sign on preference governing making hudson read CTF's SSO token * @return true to enable */ public boolean getEnableSSOAuthFromCTF() { return mEnableSSOAuthFromCTF; } /** * Single sign on preference governing making hudson login to CTF upon authenticating * @return true to enable */ public boolean getEnableSSOAuthToCTF() { return mEnableSSOAuthToCTF; } /** * Whether after singole singon into CTF, we should automatically redirect back to Hudson. * @return true to enable */ public boolean getEnableSSORedirect() { return mEnableSSORedirect; } @Override public SecurityRealm.SecurityComponents createSecurityComponents() { return new SecurityRealm.SecurityComponents(new CollabNetAuthManager (this.getCollabNetUrl())); } /** * Override the default createFilter. We want to use one that does not * return a 403 on login redirect because that may cause problems when * Hudson is run behind a proxy. */ @Override public Filter createFilter(FilterConfig filterConfig) { Binding binding = new Binding(); SecurityComponents sc = this.createSecurityComponents(); binding.setVariable("securityComponents", sc); BeanBuilder builder = new BeanBuilder(getClass().getClassLoader()); builder.parse(getClass(). getResourceAsStream("CNSecurityFilters.groovy"),binding); WebApplicationContext context = builder.createApplicationContext(); return (Filter) context.getBean("filter"); } /** * The CollabNetSecurityRealm Descriptor class. */ @Extension public static final class DescriptorImpl extends Descriptor<SecurityRealm> { /** * @return string to display for configuration screen. */ @Override public String getDisplayName() { return "CollabNet Security Realm"; } /** * Form validation for the CollabNet URL. * * @param value url */ public FormValidation doCheckCollabNetUrl(@QueryParameter String value) { if (!Hudson.getInstance().hasPermission(Hudson.ADMINISTER)) return FormValidation.ok(); String collabNetUrl = value; if (collabNetUrl == null || collabNetUrl.equals("")) { return FormValidation.error("The CollabNet URL is required."); } if (!checkSoapUrl(collabNetUrl)) { return FormValidation.error("Invalid CollabNet URL."); } return FormValidation.ok(); } /** * Check that a URL has the expected SOAP service. * * @param collabNetUrl for the CollabNet server * @return returns true if we can get a wsdl from the url, which * indicates that it's a working CollabNet server. */ private boolean checkSoapUrl(String collabNetUrl) { String soapURL = collabNetUrl + CollabNetApp.SOAP_SERVICE + "CollabNet?wsdl"; HttpClient client = new HttpClient(); try { GetMethod get = new GetMethod(soapURL); int status = client.executeMethod(get); return status == 200; } catch (IOException e) { return false; } catch (IllegalArgumentException iae) { return false; } } } private static final Logger LOGGER = Logger.getLogger(CollabNetSecurityRealm.class.getName()); }