org.italiangrid.voms.clients.impl.DefaultVOMSProxyInitBehaviour Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of voms-clients Show documentation
Show all versions of voms-clients Show documentation
VOMS service command-line clients
/**
* Copyright (c) Istituto Nazionale di Fisica Nucleare, 2006-2014.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.italiangrid.voms.clients.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.bouncycastle.asn1.x509.AttributeCertificate;
import org.bouncycastle.openssl.PasswordFinder;
import org.italiangrid.voms.VOMSError;
import org.italiangrid.voms.VOMSValidators;
import org.italiangrid.voms.ac.VOMSACValidator;
import org.italiangrid.voms.ac.ValidationResultListener;
import org.italiangrid.voms.ac.impl.DefaultVOMSValidator;
import org.italiangrid.voms.clients.ProxyInitParams;
import org.italiangrid.voms.clients.strategies.ProxyInitStrategy;
import org.italiangrid.voms.clients.strategies.VOMSCommandsParsingStrategy;
import org.italiangrid.voms.clients.util.PasswordFinders;
import org.italiangrid.voms.clients.util.VOMSProxyPathBuilder;
import org.italiangrid.voms.credential.LoadCredentialsEventListener;
import org.italiangrid.voms.credential.LoadCredentialsStrategy;
import org.italiangrid.voms.credential.VOMSEnvironmentVariables;
import org.italiangrid.voms.credential.impl.DefaultLoadCredentialsStrategy;
import org.italiangrid.voms.request.VOMSACRequest;
import org.italiangrid.voms.request.VOMSACService;
import org.italiangrid.voms.request.VOMSESLookupStrategy;
import org.italiangrid.voms.request.VOMSProtocolListener;
import org.italiangrid.voms.request.VOMSRequestListener;
import org.italiangrid.voms.request.VOMSServerInfoStore;
import org.italiangrid.voms.request.VOMSServerInfoStoreListener;
import org.italiangrid.voms.request.impl.BaseVOMSESLookupStrategy;
import org.italiangrid.voms.request.impl.DefaultVOMSACRequest;
import org.italiangrid.voms.request.impl.DefaultVOMSACService;
import org.italiangrid.voms.request.impl.DefaultVOMSESLookupStrategy;
import org.italiangrid.voms.request.impl.DefaultVOMSServerInfoStore;
import org.italiangrid.voms.store.VOMSTrustStore;
import org.italiangrid.voms.store.VOMSTrustStoreStatusListener;
import org.italiangrid.voms.store.impl.DefaultVOMSTrustStore;
import org.italiangrid.voms.util.CertificateValidatorBuilder;
import org.italiangrid.voms.util.CredentialsUtils;
import org.italiangrid.voms.util.VOMSFQANNamingScheme;
import eu.emi.security.authn.x509.StoreUpdateListener;
import eu.emi.security.authn.x509.ValidationErrorListener;
import eu.emi.security.authn.x509.ValidationResult;
import eu.emi.security.authn.x509.X509CertChainValidatorExt;
import eu.emi.security.authn.x509.X509Credential;
import eu.emi.security.authn.x509.helpers.proxy.ExtendedProxyType;
import eu.emi.security.authn.x509.helpers.proxy.ProxyHelper;
import eu.emi.security.authn.x509.proxy.ProxyCertificate;
import eu.emi.security.authn.x509.proxy.ProxyCertificateOptions;
import eu.emi.security.authn.x509.proxy.ProxyChainInfo;
import eu.emi.security.authn.x509.proxy.ProxyChainType;
import eu.emi.security.authn.x509.proxy.ProxyGenerator;
import eu.emi.security.authn.x509.proxy.ProxyPolicy;
import eu.emi.security.authn.x509.proxy.ProxyType;
import eu.emi.security.authn.x509.proxy.ProxyUtils;
/**
* The default VOMS proxy init behaviour.
*
* @author andreaceccanti
*
*/
public class DefaultVOMSProxyInitBehaviour implements ProxyInitStrategy {
private VOMSCommandsParsingStrategy commandsParser;
private X509CertChainValidatorExt certChainValidator;
private VOMSACValidator vomsValidator;
private ValidationResultListener validationResultListener;
private VOMSRequestListener requestListener;
private ProxyCreationListener proxyCreationListener;
private VOMSServerInfoStoreListener serverInfoStoreListener;
private LoadCredentialsEventListener loadCredentialsEventListener;
private ValidationErrorListener certChainValidationErrorListener;
private VOMSTrustStoreStatusListener vomsTrustStoreListener;
private StoreUpdateListener storeUpdateListener;
private VOMSProtocolListener protocolListener;
public DefaultVOMSProxyInitBehaviour(
VOMSCommandsParsingStrategy commandsParser,
ValidationResultListener validationListener,
VOMSRequestListener requestListener,
ProxyCreationListener pxCreationListener,
VOMSServerInfoStoreListener serverInfoStoreListener,
LoadCredentialsEventListener loadCredEventListener,
ValidationErrorListener certChainListener,
VOMSTrustStoreStatusListener vomsTSListener,
StoreUpdateListener trustStoreUpdateListener,
VOMSProtocolListener protocolListener) {
this.commandsParser = commandsParser;
this.validationResultListener = validationListener;
this.requestListener = requestListener;
this.proxyCreationListener = pxCreationListener;
this.serverInfoStoreListener = serverInfoStoreListener;
this.loadCredentialsEventListener = loadCredEventListener;
this.certChainValidationErrorListener = certChainListener;
this.vomsTrustStoreListener = vomsTSListener;
this.storeUpdateListener = trustStoreUpdateListener;
this.protocolListener = protocolListener;
}
public DefaultVOMSProxyInitBehaviour(
VOMSCommandsParsingStrategy commandsParser,
InitListenerAdapter listenerAdapter) {
this.commandsParser = commandsParser;
this.validationResultListener = listenerAdapter;
this.requestListener = listenerAdapter;
this.proxyCreationListener = listenerAdapter;
this.serverInfoStoreListener = listenerAdapter;
this.loadCredentialsEventListener = listenerAdapter;
this.certChainValidationErrorListener = listenerAdapter;
this.vomsTrustStoreListener = listenerAdapter;
this.storeUpdateListener = listenerAdapter;
this.protocolListener = listenerAdapter;
}
protected void validateUserCredential(ProxyInitParams params,
X509Credential cred) {
ValidationResult result = certChainValidator.validate(cred
.getCertificateChain());
if (!result.isValid())
throw new VOMSError("User credential is not valid!");
}
private void init(ProxyInitParams params) {
boolean hasVOMSCommands = params.getVomsCommands() != null
&& !params.getVomsCommands().isEmpty();
if (hasVOMSCommands || params.validateUserCredential()) {
params.setValidateUserCredential(true);
initCertChainValidator(params);
if (params.verifyAC() && hasVOMSCommands) {
initVOMSValidator(params);
}
}
}
public void initProxy(ProxyInitParams params) {
init(params);
VOMSServerInfoStore serverInfoStore = null;
// Fail fast if VO is not configured correctly
if (params.getVomsCommands() != null && !params.getVomsCommands().isEmpty()) {
serverInfoStore = initServerInfoStore(params);
checkCommands(params, serverInfoStore);
}
X509Credential cred = lookupCredential(params);
if (cred == null)
throw new VOMSError("No credentials found!");
if (params.validateUserCredential())
validateUserCredential(params, cred);
List acs = Collections.emptyList();
if (params.getVomsCommands() != null && !params.getVomsCommands().isEmpty()) {
initCertChainValidator(params);
acs = getAttributeCertificates(params, cred, serverInfoStore);
}
if (params.verifyAC() && !acs.isEmpty())
verifyACs(params, acs);
createProxy(params, cred, acs);
}
private void checkCommands(ProxyInitParams params, VOMSServerInfoStore sis) {
Map> vomsCommandsMap = commandsParser
.parseCommands(params.getVomsCommands());
for (String voOrAlias : vomsCommandsMap.keySet()) {
if (sis.getVOMSServerInfo(voOrAlias).isEmpty()) {
String msg = String.format("VOMS server for VO %s is not known! "
+ "Check your vomses configuration.", voOrAlias);
throw new VOMSError(msg);
}
}
}
private VOMSServerInfoStore initServerInfoStore(ProxyInitParams params) {
VOMSServerInfoStore sis = null;
if (params.getVomsCommands() != null && !params.getVomsCommands().isEmpty()) {
sis = new DefaultVOMSServerInfoStore.Builder()
.lookupStrategy(getVOMSESLookupStrategyFromParams(params))
.storeListener(serverInfoStoreListener).build();
}
return sis;
}
private void directorySanityChecks(String dirPath, String preambleMessage) {
File f = new File(dirPath);
String errorTemplate = String.format("%s: '%s'", preambleMessage, dirPath);
errorTemplate = errorTemplate + " (%s)";
if (!f.exists()) {
Throwable t = new FileNotFoundException(String.format(errorTemplate,
"file not found"));
throw new VOMSError(t.getMessage(), t);
}
if (!f.isDirectory()) {
throw new VOMSError(String.format(errorTemplate, "not a directory"));
}
if (!f.canRead())
throw new VOMSError(String.format(errorTemplate, "not readable"));
}
private void initCertChainValidator(ProxyInitParams params) {
if (certChainValidator == null) {
String trustAnchorsDir = DefaultVOMSValidator.DEFAULT_TRUST_ANCHORS_DIR;
if (System.getenv(VOMSEnvironmentVariables.X509_CERT_DIR) != null)
trustAnchorsDir = System.getenv(VOMSEnvironmentVariables.X509_CERT_DIR);
if (params.getTrustAnchorsDir() != null)
trustAnchorsDir = params.getTrustAnchorsDir();
directorySanityChecks(trustAnchorsDir, "Invalid trust anchors location");
CertificateValidatorBuilder builder = new CertificateValidatorBuilder();
certChainValidator = builder.trustAnchorsDir(trustAnchorsDir)
.storeUpdateListener(storeUpdateListener).lazyAnchorsLoading(true)
.validationErrorListener(certChainValidationErrorListener).build();
}
}
private VOMSACValidator initVOMSValidator(ProxyInitParams params) {
if (vomsValidator != null)
return vomsValidator;
String vomsdir = DefaultVOMSTrustStore.DEFAULT_VOMS_DIR;
if (System.getenv(VOMSEnvironmentVariables.X509_VOMS_DIR) != null)
vomsdir = System.getenv(VOMSEnvironmentVariables.X509_VOMS_DIR);
if (params.getVomsdir() != null)
vomsdir = params.getVomsdir();
directorySanityChecks(vomsdir, "Invalid vomsdir location");
VOMSTrustStore trustStore = new DefaultVOMSTrustStore(
Arrays.asList(vomsdir), vomsTrustStoreListener);
vomsValidator = VOMSValidators.newValidator(trustStore, certChainValidator,
validationResultListener);
return vomsValidator;
}
private void verifyACs(ProxyInitParams params, List acs) {
VOMSACValidator acValidator = initVOMSValidator(params);
acValidator.validateACs(acs);
}
// Why we have to do this nonsense?
private ProxyType extendedProxyTypeAsProxyType(ExtendedProxyType pt) {
switch (pt) {
case DRAFT_RFC:
return ProxyType.DRAFT_RFC;
case LEGACY:
return ProxyType.LEGACY;
case RFC3820:
return ProxyType.RFC3820;
default:
return null;
}
}
private void ensureProxyTypeIsCompatibleWithIssuingCredential(
ProxyCertificateOptions options, X509Credential issuingCredential,
List proxyCreationWarnings) {
if (ProxyUtils.isProxy(issuingCredential.getCertificateChain())) {
ProxyType issuingProxyType = extendedProxyTypeAsProxyType(ProxyHelper
.getProxyType(issuingCredential.getCertificateChain()[0]));
if (!issuingProxyType.equals(options.getType())) {
proxyCreationWarnings.add("forced " + issuingProxyType.name()
+ " proxy type to be compatible with the type of the issuing proxy.");
options.setType(issuingProxyType);
}
try {
boolean issuingProxyIsLimited = ProxyHelper.isLimited(issuingCredential
.getCertificateChain()[0]);
if (issuingProxyIsLimited && !options.isLimited()) {
proxyCreationWarnings
.add("forced the creation of a limited proxy to be compatible with the type of the issuing proxy.");
limitProxy(options);
}
} catch (IOException e) {
throw new VOMSError(e.getMessage(), e);
}
}
}
private void checkMixedProxyChain(X509Credential issuingCredential) {
if (ProxyUtils.isProxy(issuingCredential.getCertificateChain())) {
ProxyChainInfo ci;
try {
ci = new ProxyChainInfo(issuingCredential.getCertificateChain());
if (ci.getProxyType().equals(ProxyChainType.MIXED))
throw new VOMSError(
"Cannot generate a proxy certificate starting from a mixed type proxy chain.");
} catch (CertificateException e) {
throw new VOMSError(e.getMessage(), e);
}
}
}
private void ensureProxyLifetimeIsConsistentWithIssuingCredential(
ProxyCertificateOptions options, X509Credential issuingCredential,
List proxyCreationWarnings) {
Calendar cal = Calendar.getInstance();
Date proxyStartTime = cal.getTime();
cal.add(Calendar.SECOND, options.getLifetime());
Date proxyEndTime = cal.getTime();
Date issuingCredentialEndTime = issuingCredential.getCertificate()
.getNotAfter();
options.setValidityBounds(proxyStartTime, proxyEndTime);
if (proxyEndTime.after(issuingCredentialEndTime)) {
proxyCreationWarnings.add("proxy lifetime limited to issuing "
+ "credential lifetime.");
options.setValidityBounds(proxyStartTime, issuingCredentialEndTime);
}
}
private void limitProxy(ProxyCertificateOptions proxyOptions) {
proxyOptions.setLimited(true);
if (proxyOptions.getType().equals(ProxyType.RFC3820)
|| proxyOptions.getType().equals(ProxyType.DRAFT_RFC))
proxyOptions.setPolicy(new ProxyPolicy(ProxyPolicy.LIMITED_PROXY_OID));
}
private void createProxy(ProxyInitParams params, X509Credential credential,
List acs) {
List proxyCreationWarnings = new ArrayList();
String proxyFilePath = VOMSProxyPathBuilder.buildProxyPath();
String envProxyPath = System
.getenv(VOMSEnvironmentVariables.X509_USER_PROXY);
if (envProxyPath != null)
proxyFilePath = envProxyPath;
if (params.getGeneratedProxyFile() != null)
proxyFilePath = params.getGeneratedProxyFile();
ProxyCertificateOptions proxyOptions = new ProxyCertificateOptions(
credential.getCertificateChain());
proxyOptions.setProxyPathLimit(params.getPathLenConstraint());
proxyOptions.setLimited(params.isLimited());
proxyOptions.setLifetime(params.getProxyLifetimeInSeconds());
proxyOptions.setType(params.getProxyType());
proxyOptions.setKeyLength(params.getKeySize());
if (params.isEnforcingChainIntegrity()) {
checkMixedProxyChain(credential);
ensureProxyTypeIsCompatibleWithIssuingCredential(proxyOptions,
credential, proxyCreationWarnings);
ensureProxyLifetimeIsConsistentWithIssuingCredential(proxyOptions,
credential, proxyCreationWarnings);
}
if (params.isLimited())
limitProxy(proxyOptions);
if (acs != null && !acs.isEmpty())
proxyOptions.setAttributeCertificates(acs
.toArray(new AttributeCertificate[acs.size()]));
try {
ProxyCertificate proxy = ProxyGenerator.generate(proxyOptions,
credential.getKey());
CredentialsUtils.saveProxyCredentials(proxyFilePath,
proxy.getCredential());
proxyCreationListener.proxyCreated(proxyFilePath, proxy,
proxyCreationWarnings);
} catch (Throwable t) {
throw new VOMSError(
"Error creating proxy certificate: " + t.getMessage(), t);
}
}
protected List sortFQANsIfRequested(ProxyInitParams params,
List unsortedFQANs) {
if (params.getFqanOrder() != null && !params.getFqanOrder().isEmpty()) {
Set fqans = new LinkedHashSet();
for (String fqan : params.getFqanOrder()) {
if (VOMSFQANNamingScheme.isGroup(fqan))
fqans.add(fqan);
if (VOMSFQANNamingScheme.isQualifiedRole(fqan)
&& unsortedFQANs.contains(fqan))
fqans.add(fqan);
}
fqans.addAll(unsortedFQANs);
return new ArrayList(fqans);
}
return unsortedFQANs;
}
protected VOMSESLookupStrategy getVOMSESLookupStrategyFromParams(
ProxyInitParams params) {
if (params.getVomsesLocations() != null
&& !params.getVomsesLocations().isEmpty())
return new BaseVOMSESLookupStrategy(params.getVomsesLocations());
else
return new DefaultVOMSESLookupStrategy();
}
protected List getAttributeCertificates(
ProxyInitParams params, X509Credential cred,
VOMSServerInfoStore serverInfoStore) {
List vomsCommands = params.getVomsCommands();
if (vomsCommands == null || vomsCommands.isEmpty())
return Collections.emptyList();
Map> vomsCommandsMap = commandsParser
.parseCommands(params.getVomsCommands());
List acs = new ArrayList();
for (String vo : vomsCommandsMap.keySet()) {
List fqans = vomsCommandsMap.get(vo);
VOMSACRequest request = new DefaultVOMSACRequest.Builder(vo)
.fqans(sortFQANsIfRequested(params, fqans))
.targets(params.getTargets()).lifetime(params.getAcLifetimeInSeconds())
.build();
VOMSACService acService = new DefaultVOMSACService.Builder(
certChainValidator)
.requestListener(requestListener)
.serverInfoStore(serverInfoStore)
.vomsesLookupStrategy(getVOMSESLookupStrategyFromParams(params))
.protocolListener(protocolListener)
.connectTimeout(
(int) TimeUnit.SECONDS.toMillis(params.getTimeoutInSeconds()))
.readTimeout(
(int) TimeUnit.SECONDS.toMillis(params.getTimeoutInSeconds()))
.skipHostnameChecks(params.isSkipHostnameChecks())
.build();
AttributeCertificate ac = acService.getVOMSAttributeCertificate(cred,
request);
if (ac != null)
acs.add(ac);
}
if (!vomsCommandsMap.keySet().isEmpty() && acs.isEmpty())
throw new VOMSError(
"User's request for VOMS attributes could not be fulfilled.");
return acs;
}
private LoadCredentialsStrategy strategyFromParams(ProxyInitParams params) {
if (params.isNoRegen()) {
return new LoadProxyCredential(loadCredentialsEventListener,
params.getCertFile());
}
if (params.getCertFile() != null && params.getKeyFile() == null)
return new LoadUserCredential(loadCredentialsEventListener,
params.getCertFile());
if (params.getCertFile() != null && params.getKeyFile() != null)
return new LoadUserCredential(loadCredentialsEventListener,
params.getCertFile(), params.getKeyFile());
return new DefaultLoadCredentialsStrategy(
System.getProperty(DefaultLoadCredentialsStrategy.HOME_PROPERTY),
DefaultLoadCredentialsStrategy.TMPDIR_PROPERTY,
loadCredentialsEventListener);
}
private X509Credential lookupCredential(ProxyInitParams params) {
PasswordFinder pf = null;
if (params.isReadPasswordFromStdin())
pf = PasswordFinders.getNoPromptInputStreamPasswordFinder(System.in,
System.out);
else
pf = PasswordFinders.getDefault();
LoadCredentialsStrategy loadCredStrategy = strategyFromParams(params);
return loadCredStrategy.loadCredentials(pf);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy