You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ms...@apache.org on 2015/03/25 18:02:13 UTC
airavata git commit: - added support of self generating certs if a
proper ca cert and key is provided (would be good to shift to oauth2 in
future for individual gateway users),
the classic myproxy sequence also works - minor unicore security context api
Repository: airavata
Updated Branches:
refs/heads/master b27dc195a -> 80d9df511
- added support of self generating certs if a proper ca cert and key is
provided (would be good to shift to oauth2 in future for individual
gateway users), the classic myproxy sequence also works
- minor unicore security context api changes
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/80d9df51
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/80d9df51
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/80d9df51
Branch: refs/heads/master
Commit: 80d9df511f2656c2d53c251804c24c974781c0b2
Parents: b27dc19
Author: msmemon <sh...@gmail.com>
Authored: Wed Mar 25 18:01:23 2015 +0100
Committer: msmemon <sh...@gmail.com>
Committed: Wed Mar 25 18:01:23 2015 +0100
----------------------------------------------------------------------
.../client/samples/CreateLaunchExperiment.java | 12 ++-
.../gfac/bes/handlers/AbstractSMSHandler.java | 2 +-
.../gfac/bes/provider/impl/BESProvider.java | 18 ++--
.../bes/security/UNICORESecurityContext.java | 58 +++++++++++-
.../gfac/bes/security/X509SecurityContext.java | 93 +++++++++++++++++++-
.../airavata/gfac/bes/utils/BESConstants.java | 7 ++
6 files changed, 176 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/airavata/blob/80d9df51/airavata-api/airavata-client-sdks/java-client-samples/src/main/java/org/apache/airavata/client/samples/CreateLaunchExperiment.java
----------------------------------------------------------------------
diff --git a/airavata-api/airavata-client-sdks/java-client-samples/src/main/java/org/apache/airavata/client/samples/CreateLaunchExperiment.java b/airavata-api/airavata-client-sdks/java-client-samples/src/main/java/org/apache/airavata/client/samples/CreateLaunchExperiment.java
index e65acb4..925528c 100644
--- a/airavata-api/airavata-client-sdks/java-client-samples/src/main/java/org/apache/airavata/client/samples/CreateLaunchExperiment.java
+++ b/airavata-api/airavata-client-sdks/java-client-samples/src/main/java/org/apache/airavata/client/samples/CreateLaunchExperiment.java
@@ -59,7 +59,7 @@ public class CreateLaunchExperiment {
private static Airavata.Client airavataClient;
private static String echoAppId = "Echo_5dd52cd4-f9a0-459f-9baf-f8e715e44548";
- private static String mpiAppId = "HelloMPI_720e159f-198f-4daa-96ca-9f5eafee92c9";
+ private static String mpiAppId = "HelloMPI_bfd56d58-6085-4b7f-89fc-646576830518";
private static String wrfAppId = "WRF_7ad5da38-c08b-417c-a9ea-da9298839762";
private static String amberAppId = "Amber_aa083c86-4680-4002-b3ef-fad93c181926";
private static String gromacsAppId = "GROMACS_05622038-9edd-4cb1-824e-0b7cb993364b";
@@ -165,10 +165,10 @@ public class CreateLaunchExperiment {
for (int i = 0; i < 100; i++) {
// final String expId = createExperimentForSSHHost(airavata);
// final String expId = createEchoExperimentForFSD(airavataClient);
-// final String expId = createMPIExperimentForFSD(airavataClient);
+ final String expId = createMPIExperimentForFSD(airavataClient);
// final String expId = createEchoExperimentForStampede(airavataClient);
// final String expId = createEchoExperimentForTrestles(airavataClient);
- final String expId = createExperimentEchoForLocalHost(airavataClient);
+// final String expId = createExperimentEchoForLocalHost(airavataClient);
experimentIds.add(expId);
// final String expId = createExperimentWRFTrestles(airavataClient);
// final String expId = createExperimentForBR2(airavataClient);
@@ -327,6 +327,9 @@ public class CreateLaunchExperiment {
userConfigurationData.setAiravataAutoSchedule(false);
userConfigurationData.setOverrideManualScheduledParams(false);
userConfigurationData.setComputationalResourceScheduling(scheduling);
+
+ userConfigurationData.setGenerateCert(false);
+ userConfigurationData.setUserDN("");
// set output directory
AdvancedOutputDataHandling dataHandling = new AdvancedOutputDataHandling();
@@ -381,6 +384,9 @@ public class CreateLaunchExperiment {
userConfigurationData.setAiravataAutoSchedule(false);
userConfigurationData.setOverrideManualScheduledParams(false);
userConfigurationData.setComputationalResourceScheduling(scheduling);
+
+ userConfigurationData.setGenerateCert(false);
+ userConfigurationData.setUserDN("");
// set output directory
AdvancedOutputDataHandling dataHandling = new AdvancedOutputDataHandling();
http://git-wip-us.apache.org/repos/asf/airavata/blob/80d9df51/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/handlers/AbstractSMSHandler.java
----------------------------------------------------------------------
diff --git a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/handlers/AbstractSMSHandler.java b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/handlers/AbstractSMSHandler.java
index 903c3cc..c1c13be 100644
--- a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/handlers/AbstractSMSHandler.java
+++ b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/handlers/AbstractSMSHandler.java
@@ -134,7 +134,7 @@ public abstract class AbstractSMSHandler implements BESConstants, GFacHandler{
}
//TODO: check what kind of credential (server signed or myproxy) should be used
try {
- secProperties = unicoreContext.getDefaultConfiguration();
+ secProperties = unicoreContext.getDefaultConfiguration(false);
} catch (Exception e) {
throw new GFacHandlerException(e);
}
http://git-wip-us.apache.org/repos/asf/airavata/blob/80d9df51/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/provider/impl/BESProvider.java
----------------------------------------------------------------------
diff --git a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/provider/impl/BESProvider.java b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/provider/impl/BESProvider.java
index c75ea55..b301f2b 100644
--- a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/provider/impl/BESProvider.java
+++ b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/provider/impl/BESProvider.java
@@ -88,14 +88,18 @@ public class BESProvider extends AbstractProvider implements GFacProvider,
}
SecurityUtils.addSecurityContext(jobExecutionContext);
UNICORESecurityContext unicoreContext = (UNICORESecurityContext) jobExecutionContext.getSecurityContext(X509SecurityContext.X509_SECURITY_CONTEXT);
- if (log.isDebugEnabled()) {
- log.debug("Generating default configuration.");
- }
- // TODO: check what credential mode should be used
- try {
- secProperties = unicoreContext.getDefaultConfiguration();
+ try{
+ if (jobExecutionContext.getExperiment()
+ .getUserConfigurationData().isGenerateCert()) {
+ secProperties = unicoreContext
+ .getDefaultConfiguration(false, jobExecutionContext
+ .getExperiment().getUserConfigurationData());
+ }else {
+ secProperties = unicoreContext.getDefaultConfiguration(false);
+ }
+
} catch (ApplicationSettingsException e) {
- throw new GFacProviderException(e.getMessage(), e);
+ throw new GFacProviderException("Error initializing security of Unicore provider", e);
}
if (log.isDebugEnabled()) {
log.debug("Security properties initialized.");
http://git-wip-us.apache.org/repos/asf/airavata/blob/80d9df51/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/UNICORESecurityContext.java
----------------------------------------------------------------------
diff --git a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/UNICORESecurityContext.java b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/UNICORESecurityContext.java
index 15ea552..f2ec94e 100644
--- a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/UNICORESecurityContext.java
+++ b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/UNICORESecurityContext.java
@@ -26,12 +26,15 @@ import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
-
import org.apache.airavata.common.exception.ApplicationSettingsException;
+import org.apache.airavata.common.utils.ServerSettings;
import org.apache.airavata.credential.store.store.CredentialReader;
import org.apache.airavata.gfac.GFacException;
import org.apache.airavata.gfac.RequestData;
+import org.apache.airavata.gfac.bes.utils.BESConstants;
import org.apache.airavata.gfac.bes.utils.SecurityUtils;
+import org.apache.airavata.gfac.core.provider.GFacProviderException;
+import org.apache.airavata.model.workspace.experiment.UserConfigurationData;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,7 +64,7 @@ public class UNICORESecurityContext extends X509SecurityContext {
* @throws ApplicationSettingsException
* @throws GFacException, ApplicationSettingsException
*/
- public DefaultClientConfiguration getDefaultConfiguration() throws GFacException, ApplicationSettingsException {
+ public DefaultClientConfiguration getDefaultConfiguration(Boolean enableMessageLogging) throws GFacException, ApplicationSettingsException {
try{
X509Credential cred = getX509Credentials();
secProperties = new DefaultClientConfiguration(dcValidator, cred);
@@ -71,14 +74,65 @@ public class UNICORESecurityContext extends X509SecurityContext {
throw new GFacException(e.getMessage(), e);
}
secProperties.getETDSettings().setExtendTrustDelegation(true);
+ if(enableMessageLogging) secProperties.setMessageLogging(true);
// secProperties.setMessageLogging(true);
// secProperties.setDoSignMessage(true);
secProperties.getETDSettings().setIssuerCertificateChain(secProperties.getCredential().getCertificateChain());
+ return secProperties;
+ }
+
+ public DefaultClientConfiguration getDefaultConfiguration(Boolean enableMessageLogging, UserConfigurationData userData) throws GFacException, ApplicationSettingsException {
+ X509Credential cred = null;
+ try{
+ boolean genCert = userData.isGenerateCert();
+ if(genCert) {
+ String userDN = userData.getUserDN();
+ if (userDN == null && "".equals(userDN)){
+ log.warn("Cannot generate cert, falling back to container configured MyProxy credentials");
+ return getDefaultConfiguration(enableMessageLogging);
+ }
+ else {
+ log.info("Generating X.509 certificate for: "+userDN);
+ try {
+
+ String caCertPath = ServerSettings.getSetting(BESConstants.PROP_CA_CERT_PATH, "");
+ String caKeyPath = ServerSettings.getSetting(BESConstants.PROP_CA_KEY_PATH, "");
+ String caKeyPass = ServerSettings.getSetting(BESConstants.PROP_CA_KEY_PASS, "");
+
+ if(caCertPath.equals("") || caKeyPath.equals("")) {
+ throw new Exception("CA certificate or key file path missing in the properties file. "
+ + "Please make sure "+BESConstants.PROP_CA_CERT_PATH+ " or "+BESConstants.PROP_CA_KEY_PATH+" are not empty.");
+ }
+
+ if("".equals(caKeyPass)) {
+ log.warn("Caution: CA key has no password. For security reasons it is highly recommended to set a CA key password");
+ }
+ cred = generateShortLivedCredential(userDN, caCertPath, caKeyPath, caKeyPass);
+ }catch (Exception e){
+ throw new GFacProviderException("Error occured while generating a short lived credential for user:"+userDN, e);
+ }
+
+ }
+ }else {
+ return getDefaultConfiguration(enableMessageLogging);
+ }
+
+ secProperties = new DefaultClientConfiguration(dcValidator, cred);
+ setExtraSettings();
+ }
+ catch (Exception e) {
+ throw new GFacException(e.getMessage(), e);
+ }
+ secProperties.getETDSettings().setExtendTrustDelegation(true);
+ if(enableMessageLogging) secProperties.setMessageLogging(true);
+// secProperties.setDoSignMessage(true);
+ secProperties.getETDSettings().setIssuerCertificateChain(secProperties.getCredential().getCertificateChain());
return secProperties;
}
+
/**
* Get server signed credentials. Each time it is invoked new certificate
http://git-wip-us.apache.org/repos/asf/airavata/blob/80d9df51/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/X509SecurityContext.java
----------------------------------------------------------------------
diff --git a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/X509SecurityContext.java b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/X509SecurityContext.java
index 6d24750..3707ff1 100644
--- a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/X509SecurityContext.java
+++ b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/security/X509SecurityContext.java
@@ -31,20 +31,39 @@ import org.apache.airavata.gfac.Constants;
import org.apache.airavata.gfac.GFacException;
import org.apache.airavata.gfac.RequestData;
import org.apache.airavata.gfac.bes.utils.MyProxyLogon;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.emi.security.authn.x509.X509Credential;
+import eu.emi.security.authn.x509.helpers.CertificateHelpers;
+import eu.emi.security.authn.x509.helpers.proxy.X509v3CertificateBuilder;
+import eu.emi.security.authn.x509.impl.CertificateUtils;
import eu.emi.security.authn.x509.impl.DirectoryCertChainValidator;
import eu.emi.security.authn.x509.impl.KeyAndCertCredential;
import eu.emi.security.authn.x509.impl.CertificateUtils.Encoding;
+import eu.emi.security.authn.x509.impl.X500NameUtils;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.Random;
+
+import javax.security.auth.x500.X500Principal;
/**
* Handles X509 Certificate based security.
@@ -237,7 +256,6 @@ public class X509SecurityContext extends AbstractSecurityContext {
} catch (Exception e) {
throw new GFacException("An error occurred while retrieving default security credentials.", e);
}
-
}
private static DirectoryCertChainValidator getTrustedCerts() throws Exception{
@@ -248,6 +266,79 @@ public class X509SecurityContext extends AbstractSecurityContext {
DirectoryCertChainValidator dcValidator = new DirectoryCertChainValidator(trustedCert, Encoding.PEM, -1, 60000, null);
return dcValidator;
}
+
+ private String getCNFromUserDN(String userDN) {
+ return X500NameUtils.getAttributeValues(userDN, BCStyle.CN)[0];
+ }
+
+ public KeyAndCertCredential generateShortLivedCredential(String userDN, String caCertPath, String caKeyPath,
+ String caPwd) throws Exception {
+ final long CredentialGoodFromOffset = 1000L * 60L * 15L; // 15 minutes
+ // ago
+
+ final long startTime = System.currentTimeMillis() - CredentialGoodFromOffset;
+ final long endTime = startTime + 30 * 3600 * 1000;
+
+ String keyLengthProp = "1024";
+ int keyLength = Integer.parseInt(keyLengthProp);
+ String signatureAlgorithm = "SHA1withRSA";
+
+ KeyAndCertCredential caCred = getCACredential(caCertPath, caKeyPath, caPwd);
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(caCred.getKey().getAlgorithm());
+ kpg.initialize(keyLength);
+ KeyPair pair = kpg.generateKeyPair();
+
+ X500Principal subjectDN = new X500Principal(userDN);
+ Random rand = new Random();
+
+ SubjectPublicKeyInfo publicKeyInfo;
+ try {
+ publicKeyInfo = SubjectPublicKeyInfo.getInstance(new ASN1InputStream(pair.getPublic().getEncoded())
+ .readObject());
+ } catch (IOException e) {
+ throw new InvalidKeyException("Can not parse the public key"
+ + "being included in the short lived certificate", e);
+ }
+
+ X500Name issuerX500Name = CertificateHelpers.toX500Name(caCred.getCertificate().getSubjectX500Principal());
+
+ X500Name subjectX500Name = CertificateHelpers.toX500Name(subjectDN);
+
+ X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(issuerX500Name, new BigInteger(20, rand),
+ new Date(startTime), new Date(endTime), subjectX500Name, publicKeyInfo);
+
+ AlgorithmIdentifier sigAlgId = X509v3CertificateBuilder.extractAlgorithmId(caCred.getCertificate());
+ X509Certificate certificate = certBuilder.build(caCred.getKey(), sigAlgId, signatureAlgorithm, null, null);
+
+ certificate.checkValidity(new Date());
+ certificate.verify(caCred.getCertificate().getPublicKey());
+ KeyAndCertCredential result = new KeyAndCertCredential(pair.getPrivate(), new X509Certificate[] { certificate,
+ caCred.getCertificate() });
+
+ return result;
+ }
+
+ private KeyAndCertCredential getCACredential(String caCertPath, String caKeyPath, String password) throws Exception {
+ InputStream isKey, isCert;
+ isKey = isCert = null;
+ try {
+ isKey = new FileInputStream(caKeyPath);
+ PrivateKey pk = CertificateUtils.loadPrivateKey(isKey, Encoding.PEM, password.toCharArray());
+
+ isCert = new FileInputStream(caCertPath);
+ X509Certificate caCert = CertificateUtils.loadCertificate(isCert, Encoding.PEM);
+ return new KeyAndCertCredential(pk, new X509Certificate[] { caCert });
+ } finally {
+ if (isKey != null){
+ isKey.close();
+ }
+ if (isCert != null) {
+ isCert.close();
+ }
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/airavata/blob/80d9df51/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/utils/BESConstants.java
----------------------------------------------------------------------
diff --git a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/utils/BESConstants.java b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/utils/BESConstants.java
index 654f3bc..ffbf62e 100644
--- a/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/utils/BESConstants.java
+++ b/modules/gfac/gfac-bes/src/main/java/org/apache/airavata/gfac/bes/utils/BESConstants.java
@@ -31,4 +31,11 @@ public interface BESConstants {
public static final String PROP_CLIENT_CONF = "bes.client.config";
+ public static final String PROP_CA_CERT_PATH = "bes.ca.cert.path";
+
+ public static final String PROP_CA_KEY_PATH = "bes.ca.key.path";
+
+ public static final String PROP_CA_KEY_PASS = "bes.ca.key.pass";
+
+
}
\ No newline at end of file