/* * OSGAuthorization.java * * Created on October 18, 2005, 3:20 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. * * Weigand 6/16/06: * Modified the VOMSUserInfo class to identify the user of a cert # differently. The old method was was causing a problem with # delegated proxies and we now mirror what Globus does in the gridmap authz * service. The peerSubject was needed on instantiation of the VOMSUserIndo * class. */ package org.opensciencegrid.authz.gt4; import java.io.File; import java.security.Principal; import java.util.Arrays; import java.util.Iterator; import java.security.cert.X509Certificate; import java.util.Set; import javax.security.auth.Subject; import javax.xml.namespace.QName; import javax.xml.rpc.handler.MessageContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.globus.gsi.gssapi.GlobusGSSCredentialImpl; import org.globus.gsi.jaas.GlobusPrincipal; import org.globus.gsi.jaas.JaasGssUtil; import org.globus.gsi.jaas.UserNamePrincipal; import org.globus.wsrf.Resource; import org.globus.wsrf.ResourceContext; import org.globus.wsrf.ResourceException; import org.globus.wsrf.ResourceContextException; import org.globus.wsrf.config.ConfigException; import org.globus.wsrf.impl.security.descriptor.SecurityPropertiesHelper; import org.globus.security.gridmap.GridMap; import org.globus.wsrf.impl.security.util.AuthUtil; import org.globus.wsrf.impl.security.authorization.exceptions.AuthorizationException; import org.globus.wsrf.impl.security.authorization.exceptions.CloseException; import org.globus.wsrf.impl.security.authorization.exceptions.InitializeException; import org.globus.wsrf.impl.security.authorization.exceptions.InvalidPolicyException; import org.globus.wsrf.security.SecurityManager; import org.globus.wsrf.security.authorization.PDP; import org.globus.wsrf.security.authorization.PDPConfig; import org.opensciencegrid.authz.client.GRIDIdentityMappingServiceClient; import org.opensciencegrid.authz.common.GridId; import org.opensciencegrid.authz.common.LocalId; import org.w3c.dom.Node; /** This class implements the Globus Callout to call an Identity Mapping Service * such as GUMS. For more information about the Globus AuthZ callout mechanism * refer to Globus documentation. *

* The entry point for the class is the isPermitted method, that will be called * by the GT4 code. initialize will be called once when the Globus container * is started. * * @author Gabriele Carcassi */ public class OSGAuthorization implements PDP { public static final String FILE = "gridmap-file"; public static final String OBJECT = "gridmapObject"; String prefix = null; String servicePath = null; private static Log log = LogFactory.getLog(OSGAuthorization.class); // ---------------------------------------------------------------------- public Node getPolicy(Node policy) throws InvalidPolicyException { // Not clear what this function should implement: // other implementation just return null, so that's what we'll do return null; } // --------------------------------------------------------------------- public Node setPolicy(Node policy) throws InvalidPolicyException { // Not clear what this function should implement: // other implementation just return null, so that's what we'll do return null; } // --------------------------------------------------------------------- public String[] getPolicyNames() { // Not clear what this function should implement: // other implementation just return null, so that's what we'll do return null; } // --------------------------------------------------------------------- public boolean isPermitted(Subject peerSubject, MessageContext context, QName op) throws AuthorizationException { GridId userGridID = null; try { log.info("=========== PRIMA GT4 AUTHORIZATION ==============="); log.info("GT4 PRIMA OSGAuthorization started for "+AuthUtil.getIdentity(peerSubject)); String username = null; // -- Retrieve a configuration object -- PRIMAConfiguration conf = PRIMAConfiguration.getInstance(); // -- Retrieve the client certificate chain -- X509Certificate[] clientCertChain = retrieveClientCertChain(peerSubject); // -- Retrieve the server certificate chain -- log.trace("Retrieving server certificate chain..."); X509Certificate[] serviceCertChain = retrieveServiceCertChain(context); if (log.isTraceEnabled()) { if (serviceCertChain == null) { log.warn("No server certificate chain retrieved"); } else { log.trace("Server certificate chain retrieved: " + Arrays.asList(serviceCertChain)); } } // -- retrieve the VOMS information ---- VOMSUserInfo vomsInfo = VOMSUserInfo.retrieveVOMSUserInfo(peerSubject, clientCertChain); log.info("PRIMA: Client certificate information: " + vomsInfo); log.trace("PRIMA: Retrieving GRAM Service DN..."); String hostDN = retrieveDN(retrieveServiceCredential(context)); log.trace("PRIMA: GRAM Service DN (" + hostDN + ")"); log.trace("PRIMA: Preparing information for AuthZ server call..."); userGridID = new GridId(); userGridID.setHostDN(hostDN); userGridID.setUserDN(vomsInfo.getUserDN()); userGridID.setUserFQAN(vomsInfo.getFirstFQAN()); userGridID.setUserFQANIssuer(vomsInfo.getVOMSServerDN()); log.info("PRIMA: User "+userGridID); /* * * Check cache * */ // get resource Resource resource = null; try { ResourceContext ctx = ResourceContext .getResourceContext((org.apache.axis.MessageContext)context); resource = ctx.getResource(); } catch (ResourceContextException exp) { // FIXME: quiet catch. need to have more specific exceptions // from core. log.debug("Error retrieving resource", exp); resource = null; } catch (ResourceException exp) { // FIXME: quiet catch. need to have more specific exceptions // from core. log.debug("Error retrieving resource", exp); resource = null; } log.debug("Service " + this.servicePath); GridMap gridMap = null; try { gridMap = SecurityPropertiesHelper.getGridMap(this.servicePath, resource); } catch (ConfigException exp) { log.debug("Error getting gridmap", exp); throw new AuthorizationException("Error getting gridmap"); } if (gridMap == null) { log.info("No gridmap object, call GUMS"); } else { String[] usernames = gridMap.getUserIDs(AuthUtil.getIdentity(peerSubject)); if ((usernames == null) || (usernames.length <=0)) { log.info("PRIMA: No cached info found"); } else { log.info("PRIMA: Found cached user " + usernames[0]); log.trace("PRIMA: Cached nr: " + usernames.length); // --- set local account in gt4 context ---- setupReturnContext(peerSubject, usernames[0]); log.info("=========== PRIMA GT4 DONE - CACHED ==============="); return true; } } // -- set up a couple message strings to insure consistency -- String userMsg = new String(" for "+userGridID+" "); String serviceMsg = new String(" authz service (" +conf.getImsContact()+") "); log.info("PRIMA: Contacting "+serviceMsg+"for"+userMsg); log.trace("PRIMA: Setting up AuthZ server call stub"); GRIDIdentityMappingServiceClient authZClient = new GRIDIdentityMappingServiceClient(conf.getImsContact()); authZClient.setGlobusCredentials(retrieveServiceCredential(context)); // -- call the GUMS service --- log.trace("PRIMA: Calling AuthZ server ("+conf.getImsContact()+")"); LocalId userLocalID = authZClient.mapCredentials(userGridID); // -- user is denied if GUMS didn't return a local account if (userLocalID == null) { log.warn("PRIMA: DENY -"+userMsg+"from"+serviceMsg); return false; } // --- set local account in gt4 context ---- setupReturnContext(peerSubject, userLocalID.getUserName()); // -- user is authorized --- log.info("PRIMA: PERMIT -"+userMsg+"from"+serviceMsg+" is assigned local account (" +userLocalID.getUserName()+ ")"); log.info("=========== PRIMA GT4 AUTHORIZATION DONE - GUMS PERMIT ==============="); return true; } catch (Exception e) { log.warn("PRIMA: DENY - User (" + AuthUtil.getIdentity(peerSubject) + ") - prior to contacting service: " + e.getMessage()); log.info("=========== PRIMA GT4 AUTHORIZATION DONE - GUMS DENY ==============="); return false; } } // --------------------------------------------------------------------- // FIXME: Last parameter is servicePath (by convention) public void initialize(PDPConfig pDPConfig, String string, String servicePath_) throws InitializeException { log.trace("PRIMA: GT4 OSGAuthorization invoked"); initializeConfLocation(pDPConfig, string); this.servicePath = servicePath_; log.debug("service " + this.servicePath); } // --------------------------------------------------------------------- private static final String CONF_LOCATION_DEFAULT = "/etc/grid-security/prima-authz.conf"; // --------------------------------------------------------------------- private void initializeConfLocation(PDPConfig pDPConfig, String string) { String confLocation = null; try { confLocation = (String) pDPConfig.getProperty(string, "confLocation"); if (confLocation == null) { log.trace("PRIMA: Using default configuration file '" + CONF_LOCATION_DEFAULT + "'"); confLocation = CONF_LOCATION_DEFAULT; PRIMAConfiguration.setConfLocation(confLocation); } else { PRIMAConfiguration.setConfLocation(confLocation); } } catch (Exception e) { log.warn("PRIMA: Couldn't retrieve the configuration location from the properties file."); confLocation = CONF_LOCATION_DEFAULT; PRIMAConfiguration.setConfLocation(confLocation); } } // --------------------------------------------------------------------- public void close() throws CloseException { // Nothing to close for now } // --------------------------------------------------------------------- void setupReturnContext(Subject peerSubject, String username) { log.trace("PRIMA: Local account set to '" + username + "' in GT4 security context"); peerSubject.getPrincipals().add(new UserNamePrincipal(username)); } // --------------------------------------------------------------------- X509Certificate[] retrieveClientCertChain(Subject peerSubject) { log.trace("PRIMA: Retrieving user certificate chain for " + AuthUtil.getIdentity(peerSubject)); Set publicCreds = peerSubject.getPublicCredentials(); if (publicCreds == null) { log.warn("PRIMA: DENY - No certificate chain found."); throw new RuntimeException("PRIMA: Couldn't retrieve client certificate chain."); } Iterator iter = publicCreds.iterator(); while (iter.hasNext()) { Object obj = iter.next(); if (obj instanceof X509Certificate[]) { log.debug("PRIMA: Client certificate chain retrieved -" + Arrays.asList((X509Certificate[]) obj)); return (X509Certificate[]) obj; } log.warn("PRIMA: Object " + obj + " is not a certificate chain"); } log.warn("PRIMA: No certificate chain found: getPublicCredentials didn't contain any X509Certificate[] objects"); throw new RuntimeException("PRIMA: Couldn't retrieve client certificate chain."); } // --------------------------------------------------------------------- X509Certificate[] retrieveServiceCertChain(MessageContext context) throws AuthorizationException { org.apache.axis.MessageContext ctx = (org.apache.axis.MessageContext) context; SecurityManager manager = SecurityManager.getManager(ctx); Subject systemSubject = null; try { systemSubject = manager.getSystemSubject(); } catch (org.globus.wsrf.security.SecurityException e) { log.warn("No System credentials were found", e); throw new AuthorizationException("No System credentials were found: " + e.getMessage() , e); } GlobusGSSCredentialImpl credential = (GlobusGSSCredentialImpl)JaasGssUtil.getCredential(systemSubject); return credential.getCertificateChain(); } // --------------------------------------------------------------------- GlobusGSSCredentialImpl retrieveServiceCredential(MessageContext context) throws AuthorizationException { org.apache.axis.MessageContext ctx = (org.apache.axis.MessageContext) context; SecurityManager manager = SecurityManager.getManager(ctx); Subject systemSubject = null; try { systemSubject = manager.getSystemSubject(); } catch (org.globus.wsrf.security.SecurityException e) { log.warn("No System credentials were found", e); throw new AuthorizationException("No System credentials were found: " + e.getMessage() , e); } GlobusGSSCredentialImpl credential = (GlobusGSSCredentialImpl)JaasGssUtil.getCredential(systemSubject); return credential; } // --------------------------------------------------------------------- String retrieveDN(GlobusGSSCredentialImpl credential) { return credential.getGlobusCredential().getIdentity(); } }