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