package org.dcache.gplazma.plugins; import com.google.common.collect.Collections2; import org.glite.authz.common.model.Request; import org.glite.authz.common.model.Response; import org.glite.authz.common.model.Result; import org.glite.authz.pep.client.PEPClient; import org.glite.authz.pep.client.PEPClientException; import org.glite.authz.pep.client.config.PEPClientConfiguration; import org.glite.authz.pep.client.config.PEPClientConfigurationException; import org.glite.authz.pep.profile.GridWNAuthorizationProfile; import org.globus.gsi.gssapi.jaas.GlobusPrincipal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.Principal; import java.util.Collection; import java.util.Collections; import java.util.Properties; import java.util.Set; import org.dcache.gplazma.AuthenticationException; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.instanceOf; /** * Implementation of an Argus Authorisation plugin for gPlazma2 * * The plugin supports blacklisting of subjects identified by X509 Certificates * and/or their DN. * * @author karsten * */ public class GPlazmaArgusPlugin implements GPlazmaAccountPlugin { private static final Logger _log = LoggerFactory.getLogger(GPlazmaArgusPlugin.class); private static final String CREATING_ARGUS_PLUGIN_WITH_PARAMETERS_params = "Creating Argus Plugin with parameters: {}"; private static final String COULD_NOT_CREATE_PEP_CLIENT_exception = "Could not create PEP Client"; private static final String INVALID_CONFIGURATION_FOR_ARGUS_PLUGIN = "Invalid configuration for ARGUS plugin."; private static final String G_PLAZMA_ARGUS_PLUGIN_ARGS_MUST_NOT_BE_NULL = "GPlazmaArgusPlugin: args must not be null."; private static final String INITIALISING_PEP_CLIENT_CONFIGURATION = "Initialising PEPClientConfiguration"; private static final String CONFIGURATION_resourceid_actionid = "Configuration: [{}]; [{}]"; private static final String AUTHORISING_SUBJECT_dn = "Authorising subject {}."; private static final String CREATED_REQUEST_request = "Created request: {}"; private static final String RECEIVED_RESPONSE_response = "Received response: {}"; private static final String BLACKLIST_CHECK_FOR_USER_dn_FAILED_DUE_TO_EXCEPTION_IN_PLUGIN = "Blacklist check for user '{}' failed due to exception in plugin."; private static final String DECISION_CODE_code = "Decision code: "; private static final String KEY_PASS = "gplazma.argus.hostkey.password"; private static final String HOST_KEY = "gplazma.argus.hostkey"; private static final String HOST_CERT = "gplazma.argus.hostcert"; private static final String TRUST_MATERIAL = "gplazma.argus.ca"; private static final String ACTION_ID = "gplazma.argus.action"; private static final String RESOURCE_ID = "gplazma.argus.resource"; private static final String PEP_ENDPOINT = "gplazma.argus.endpoint"; private final PEPClient _pepClient; private String _resourceId; private String _actionId; /** * Constructor * @param properties a set of key value pairs containing the plugins configuration. */ public GPlazmaArgusPlugin(Properties properties) { _log.debug(CREATING_ARGUS_PLUGIN_WITH_PARAMETERS_params, properties); try { PEPClientConfiguration pepConfiguration = initPepConfiguration(properties); _pepClient = new PEPClient(pepConfiguration); } catch (PEPClientException e) { _log.error(COULD_NOT_CREATE_PEP_CLIENT_exception, e); throw new IllegalArgumentException(INVALID_CONFIGURATION_FOR_ARGUS_PLUGIN, e); } } /** * Constructor * @param pepClient client to be used by plugin */ public GPlazmaArgusPlugin(PEPClient pepClient) { _pepClient = pepClient; } /** * This method initialises the instance's configuration, by parsing * the parameters given in args. Required key/value is PEPEndpoint. * @param properties array of key value pairs containing the plugins configuration ( key1, value1, key2, value2, ...) * @throws PEPClientConfigurationException */ private PEPClientConfiguration initPepConfiguration(Properties properties) throws PEPClientConfigurationException { checkNotNull(properties, G_PLAZMA_ARGUS_PLUGIN_ARGS_MUST_NOT_BE_NULL); PEPClientConfiguration pepConfig = new PEPClientConfiguration(); _log.debug(INITIALISING_PEP_CLIENT_CONFIGURATION); pepConfig.addPEPDaemonEndpoint(getProperty(properties, PEP_ENDPOINT)); _resourceId = getProperty(properties, RESOURCE_ID); _actionId = getProperty(properties, ACTION_ID); String trustMaterial = getProperty(properties, TRUST_MATERIAL); String hostCert = getProperty(properties, HOST_CERT); String hostKey = getProperty(properties, HOST_KEY); String keyPass = getProperty(properties, KEY_PASS); pepConfig.setTrustMaterial(trustMaterial); pepConfig.setKeyMaterial(hostCert, hostKey, keyPass); _log.debug(CONFIGURATION_resourceid_actionid, _resourceId, _actionId); return pepConfig; } private String getProperty(Properties properties, String key) { String value = properties.getProperty(key); checkArgument(value != null, "Undefined property: " + key); return value; } @Override public void account(Set<Principal> authorizedPrincipals) throws AuthenticationException { int decision = Result.DECISION_NOT_APPLICABLE; String dn = null; try { Collection<Principal> globusPrincipals = Collections.emptySet(); if (authorizedPrincipals != null) { globusPrincipals = Collections2 .filter(authorizedPrincipals, instanceOf(GlobusPrincipal.class)); } for (Principal principal : globusPrincipals) { dn = principal.getName(); _log.info(AUTHORISING_SUBJECT_dn, dn); Request request = ArgusPepRequestFactory.create(dn, _resourceId, _actionId, GridWNAuthorizationProfile.getInstance()); _log.debug(CREATED_REQUEST_request, request); Response response = _pepClient.authorize(request); _log.debug(RECEIVED_RESPONSE_response, response); for (Result result : response.getResults()) { decision = result.getDecision(); switch (decision) { case Result.DECISION_DENY: throw new AuthenticationException("user banned"); case Result.DECISION_INDETERMINATE: throw new AuthenticationException("indeterminate result"); } } } } catch (PEPClientException e) { decision = Result.DECISION_DENY; _log.warn(BLACKLIST_CHECK_FOR_USER_dn_FAILED_DUE_TO_EXCEPTION_IN_PLUGIN, dn ,e); throw new AuthenticationException("check failed", e); } finally { _log.info(DECISION_CODE_code, decision); } } }