You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2017/09/18 19:16:30 UTC

[1/2] airavata git commit: AIRAVATA-2500 Partial Implementation

Repository: airavata
Updated Branches:
  refs/heads/AIRAVATA-2500 99e27566e -> daedef2eb


AIRAVATA-2500 Partial Implementation


Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/8dbe2703
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/8dbe2703
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/8dbe2703

Branch: refs/heads/AIRAVATA-2500
Commit: 8dbe27035d73a89bc738b8270674cd597010bff9
Parents: 99e2756
Author: spamidig <pa...@iu.edu>
Authored: Fri Sep 15 09:56:05 2017 -0400
Committer: spamidig <pa...@iu.edu>
Committed: Fri Sep 15 09:56:05 2017 -0400

----------------------------------------------------------------------
 modules/compute-account-provisioning/pom.xml    |   6 +
 .../IULdapSSHAccountProvisioner.java            | 120 ++++++++++++++++++-
 .../SSHAccountProvisionerFactoryTest.java       |  10 +-
 .../TestSSHAccountProvisionerProvider.java      |   8 +-
 4 files changed, 136 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata/blob/8dbe2703/modules/compute-account-provisioning/pom.xml
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/pom.xml b/modules/compute-account-provisioning/pom.xml
index ee89d33..de963df 100644
--- a/modules/compute-account-provisioning/pom.xml
+++ b/modules/compute-account-provisioning/pom.xml
@@ -52,6 +52,12 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <!-- apache directory ldap api! -->
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-all</artifactId>
+            <version>1.0.0</version>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>

http://git-wip-us.apache.org/repos/asf/airavata/blob/8dbe2703/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
index 03fa803..331c01c 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
@@ -22,20 +22,92 @@ package org.apache.airavata.accountprovisioning.provisioner;
 
 import org.apache.airavata.accountprovisioning.ConfigParam;
 import org.apache.airavata.accountprovisioning.SSHAccountProvisioner;
-
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.ldap.client.api.*;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.message.DeleteResponse;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.junit.Assert;
 import java.util.Map;
+import java.util.List;
 
-public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
+public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner  {
 
+    String ldaphost, adminDN, ldap_username, ldap_password, adminPass, ldapBaseDN;
+    int ldapport, ldapPortId;
+    LdapConnection connection;
     @Override
     public void init(Map<ConfigParam, String> config) {
 
         // TODO: implement
+        ldapServerName =  config.get(new ConfigParam("ldaphost"));//"bazooka.hps.iu.edu"
+        ldapPortId = config.get(new ConfigParam("ldapport"));//"636"
+        ldap_username = config.get(new ConfigParam("ldap_username"));//"cn=sgrcusr"
+        ldap_password = config.get(new ConfigParam("ldap_password"));//"lore footwork engorge"
+        ldapBaseDN = config.get(new ConfigParam( "ldapBaseDN" ));//"dc=rt,dc=iu,dc=edu"
+        try {
+            connection = new LdapNetworkConnection(ldaphost, ldapport, true);
+
+
+            System.out.println( "binding connection:" );
+            String AuthDN=ldap_username+","+ldapBaseDN;
+            connection.bind(AuthDN,ldap_password);
+            //check that we're auth'ed and connected
+            System.out.println("asserting bound:");
+            Assert.assertTrue( connection.isAuthenticated() );
+            Assert.assertTrue( connection.isConnected() );
+            }  catch (Exception e) {
+            System.out.println("Exception caught!");
+            System.out.println(e.getClass().getCanonicalName());
+            System.out.println(e.getMessage());
+            System.out.println(e.getCause());
+
+            }
+            //catch (LdapException le) {
+            //System.out.println("Ldap Exception caught!", le);
+            //}
+
     }
 
     @Override
     public boolean hasAccount(String username) {
         // TODO: implement
+        // To verify if the user has a login on a remote host
+        // if not advice the user to get an account (if possible) before returning.
+        // a search at the ldap is used to set the value
+        System.out.println("attempting search:");
+        String uidName="uid="+username;
+        List<String>  userClusters = new ArrayList();
+        try {
+            EntryCursor cursor = connection.search( ldapBaseDN, uidName, SearchScope.SUBTREE, "*" );
+            System.out.println( "Printing LDAP-wide results for " + username + ":" );
+            while (cursor.next()) {
+                Entry entry = cursor.get();
+                String DNName = entry.getDn().getName();
+                String[] words=DNName.split(",");
+                String cluster = words[1].replace("ou=");
+                userClusters.add(cluster);
+                //System.out.println( entry.getDn().getName() );
+                //System.out.println( entry.getAttributes() );
+                return true;
+            }
+            cursor.close();
+        }catch (Exception e) {
+            System.out.println( "Exception caught!" );
+            System.out.println( e.getClass().getCanonicalName() );
+            System.out.println( e.getMessage() );
+            System.out.println( e.getCause() );
+        } catch (CursorException ce) {
+            System.out.println( "Cursor Exception caught!" );
+        }catch (LdapException le) {
+            System.out.println( "Ldap Exception caught!" );
+        }
         return false;
     }
 
@@ -48,11 +120,53 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
     @Override
     public void installSSHKey(String username, String sshPublicKey) {
         // TODO: implement
+        // use Eric Coulter's LdapBazookaSearchAndAdd to accomplsih this
+        String GatewaySSHPublicKey = sshPublicKey;
+        String IULocalUserName = username;
+
+
+        /*
+        LdapConnectionConfig lcconfig = new LdapConnectionConfig();
+        lcconfig.setLdapHost(ldapservername);// LdapServerName = ldapserverName;//from ConfigParam should be like bazooka.hpc.iu.edu
+        lcconfig.setLdapPort(ldapPortId);// LdapPortID = ldapPortId;//from ConfigParam 636
+        lcconfig.setName(adminDN);// = adminName;//from ConfigParam sgrcusr
+        lcconfig.setCredentials(AdminPass);//from ConfigParam "lore footwork engorge"
+
+        DefaultLdapConnectionFactory lcfactory = new DefaultLdapConnectionFactory( lcconfig );
+        lcfactory.setTimeOut( connectionTimeout );
+        */
+
+            Modification addSSHPublicKeyAdd = new DefaultModification(ModificationOperation.ADD_ATTRIBUTE,"add","sshPublicKey");
+            Modification SSHPublicKey = new DefaultModification(ModificationOperation.ADD_ATTRIBUTE, "sshPublicKey",GatewaySSHPublicKey);
+            /*
+            Entry modentry = New DefaultEntry(
+                    "cn=sgrcusr,dc=rt,dc=iu,dc=edu",
+                    "ObjectClass: person",
+                    "ObjectClass: ldapPublicKey",
+                    "cn", username,
+                    "dn", "uid=",username, "ou=bigred2-sgrc,dc=rt,dc=iu,dc=edu",
+                    "add: sshPublicKey",
+                    "sshPublicKey", GatewaySSHPublicKey );
+                    */
+            try {
+                connection.modify(ldapBaseDN, addSSHPublicKeyAdd );//ldapmodify
+                connection.modify(ldapBaseDN, SSHPublicKey );
+            } catch (Exception e) {
+                System.out.println("Exception caught!", e);
+                System.out.println( e.getClass().getCanonicalName() );
+                System.out.println( e.getMessage() );
+                System.out.println( e.getCause() );
+            }
+
     }
 
     @Override
     public String getScratchLocation(String username) {
         // TODO: implement
-        return null;
+        //if scratch location is available get it or else set a new scratch location for the user
+        String canonicalScratch =  config.get(new ConfigParam("canonicalScratch"));//"/N/cd2/_USER_/scratch"
+        String scratchLocation = canonicalScratch.replace("_USER_",username);
+        return scratchLocation;
+        //return null;
     }
 }

http://git-wip-us.apache.org/repos/asf/airavata/blob/8dbe2703/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
index 89e9ff7..54d5f1c 100644
--- a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
+++ b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
@@ -43,7 +43,7 @@ public class SSHAccountProvisionerFactoryTest {
     public void testGetSSHAccountProvisionerConfigParams() {
 
         List<ConfigParam> configParams = SSHAccountProvisionerFactory.getSSHAccountProvisionerConfigParams("TestSSHAccountProvisioner");
-        Assert.assertEquals(4, configParams.size());
+        Assert.assertEquals(5, configParams.size());
         ConfigParam ldaphost = configParams.get(0);
         Assert.assertEquals("ldaphost", ldaphost.getName());
         Assert.assertEquals(ConfigParam.ConfigParamType.STRING, ldaphost.getType());
@@ -51,11 +51,15 @@ public class SSHAccountProvisionerFactoryTest {
         Assert.assertEquals("ldapport", ldapport.getName());
         Assert.assertEquals(ConfigParam.ConfigParamType.STRING, ldapport.getType());
         ConfigParam ldapUsername = configParams.get(2);
-        Assert.assertEquals("ldap-username", ldapUsername.getName());
+        Assert.assertEquals("ldap_username", ldapUsername.getName());
         Assert.assertEquals(ConfigParam.ConfigParamType.STRING, ldapUsername.getType());
         ConfigParam ldapPassword = configParams.get(3);
-        Assert.assertEquals("ldap-password", ldapPassword.getName());
+        Assert.assertEquals("ldap_password", ldapPassword.getName());
         Assert.assertEquals(ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN, ldapPassword.getType());
+        ConfigParam ldapBaseDN = configParams.get(4);
+        Assert.assertArrayEquals("ldapBaseDN", ldapBaseDN.getName()  );
+        Assert.assertArrayEquals( ConfigParam.ConfigParamType.STRING,ldapBaseDN.getType() );
+
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/airavata/blob/8dbe2703/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
index a8d2cb5..7eb4250 100644
--- a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
+++ b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
@@ -46,14 +46,18 @@ public class TestSSHAccountProvisionerProvider implements SSHAccountProvisionerP
                 .setDescription("Port of LDAP server")
                 .setOptional(false)
                 .setType(ConfigParam.ConfigParamType.STRING));
-        configParams.add(new ConfigParam("ldap-username")
+        configParams.add(new ConfigParam("ldap_username")
                 .setDescription("Username for LDAP server")
                 .setOptional(false)
                 .setType(ConfigParam.ConfigParamType.STRING));
-        configParams.add(new ConfigParam("ldap-password")
+        configParams.add(new ConfigParam("ldap_password")
                 .setDescription("Password for LDAP server")
                 .setOptional(false)
                 .setType(ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN));
+        configParams.add(new ConfigParam("ldapBaseDN")
+                .setDescription( "Base DN for the ldap entry" )
+                .setOptional( false )
+                .setType( ConfigParam.ConfigParamType.STRING );
         return configParams;
     }
 


[2/2] airavata git commit: Integrate IULdapSSHAccountProvisioner with fixes

Posted by ma...@apache.org.
Integrate IULdapSSHAccountProvisioner with fixes


Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/daedef2e
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/daedef2e
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/daedef2e

Branch: refs/heads/AIRAVATA-2500
Commit: daedef2ebe2f7eaa39e78d5b49f7bdeb45b4b8d0
Parents: 8dbe270
Author: Marcus Christie <ma...@apache.org>
Authored: Mon Sep 18 15:12:16 2017 -0400
Committer: Marcus Christie <ma...@apache.org>
Committed: Mon Sep 18 15:14:46 2017 -0400

----------------------------------------------------------------------
 .../IULdapSSHAccountProvisioner.java            | 242 ++++++++++---------
 .../IULdapSSHAccountProvisionerProvider.java    |  47 ++--
 .../SSHAccountProvisionerFactoryTest.java       |   4 -
 .../TestSSHAccountProvisionerProvider.java      |   2 +-
 4 files changed, 153 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata/blob/daedef2e/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
index 331c01c..d0c204f 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
@@ -21,152 +21,158 @@
 package org.apache.airavata.accountprovisioning.provisioner;
 
 import org.apache.airavata.accountprovisioning.ConfigParam;
+import org.apache.airavata.accountprovisioning.SSHAccountManager;
 import org.apache.airavata.accountprovisioning.SSHAccountProvisioner;
-import org.apache.directory.api.ldap.model.cursor.CursorException;
-import org.apache.directory.ldap.client.api.*;
-import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.entry.Modification;
-import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.message.DeleteResponse;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
+import org.apache.directory.api.ldap.model.message.ModifyResponse;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
-import org.junit.Assert;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
 import java.util.Map;
-import java.util.List;
+import java.util.function.Function;
 
 public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner  {
 
-    String ldaphost, adminDN, ldap_username, ldap_password, adminPass, ldapBaseDN;
-    int ldapport, ldapPortId;
-    LdapConnection connection;
+    private final static Logger logger = LoggerFactory.getLogger(SSHAccountManager.class);
+    public static final String LDAP_PUBLIC_KEY_OBJECT_CLASS = "ldapPublicKey";
+    public static final String SSH_PUBLIC_KEY_ATTRIBUTE_NAME = "sshPublicKey";
+
+    private String ldapHost, ldapUsername, ldapPassword, ldapBaseDN, canonicalScratchLocation;
+    private int ldapPort;
     @Override
     public void init(Map<ConfigParam, String> config) {
 
-        // TODO: implement
-        ldapServerName =  config.get(new ConfigParam("ldaphost"));//"bazooka.hps.iu.edu"
-        ldapPortId = config.get(new ConfigParam("ldapport"));//"636"
-        ldap_username = config.get(new ConfigParam("ldap_username"));//"cn=sgrcusr"
-        ldap_password = config.get(new ConfigParam("ldap_password"));//"lore footwork engorge"
-        ldapBaseDN = config.get(new ConfigParam( "ldapBaseDN" ));//"dc=rt,dc=iu,dc=edu"
-        try {
-            connection = new LdapNetworkConnection(ldaphost, ldapport, true);
-
-
-            System.out.println( "binding connection:" );
-            String AuthDN=ldap_username+","+ldapBaseDN;
-            connection.bind(AuthDN,ldap_password);
-            //check that we're auth'ed and connected
-            System.out.println("asserting bound:");
-            Assert.assertTrue( connection.isAuthenticated() );
-            Assert.assertTrue( connection.isConnected() );
-            }  catch (Exception e) {
-            System.out.println("Exception caught!");
-            System.out.println(e.getClass().getCanonicalName());
-            System.out.println(e.getMessage());
-            System.out.println(e.getCause());
-
-            }
-            //catch (LdapException le) {
-            //System.out.println("Ldap Exception caught!", le);
-            //}
-
+        ldapHost =  config.get(IULdapSSHAccountProvisionerProvider.LDAP_HOST);//"bazooka.hps.iu.edu"
+        ldapPort = Integer.valueOf(config.get(IULdapSSHAccountProvisionerProvider.LDAP_PORT));//"636"
+        ldapUsername = config.get(IULdapSSHAccountProvisionerProvider.LDAP_USERNAME);//"cn=sgrcusr"
+        ldapPassword = config.get(IULdapSSHAccountProvisionerProvider.LDAP_PASSWORD); //"secret password"
+        ldapBaseDN = config.get(IULdapSSHAccountProvisionerProvider.LDAP_BASE_DN);//"dc=rt,dc=iu,dc=edu"
+        canonicalScratchLocation = config.get(IULdapSSHAccountProvisionerProvider.CANONICAL_SCRATCH_LOCATION); //"/N/dc2/scratch/username/iu-gateway"
     }
 
     @Override
-    public boolean hasAccount(String username) {
-        // TODO: implement
-        // To verify if the user has a login on a remote host
-        // if not advice the user to get an account (if possible) before returning.
-        // a search at the ldap is used to set the value
-        System.out.println("attempting search:");
-        String uidName="uid="+username;
-        List<String>  userClusters = new ArrayList();
-        try {
-            EntryCursor cursor = connection.search( ldapBaseDN, uidName, SearchScope.SUBTREE, "*" );
-            System.out.println( "Printing LDAP-wide results for " + username + ":" );
-            while (cursor.next()) {
-                Entry entry = cursor.get();
-                String DNName = entry.getDn().getName();
-                String[] words=DNName.split(",");
-                String cluster = words[1].replace("ou=");
-                userClusters.add(cluster);
-                //System.out.println( entry.getDn().getName() );
-                //System.out.println( entry.getAttributes() );
-                return true;
+    public boolean hasAccount(String userId) {
+        String username = getUsername(userId);
+        boolean result = withLdapConnection(ldapConnection -> {
+            try {
+                return ldapConnection.exists("uid=" + username + "," + ldapBaseDN);
+            } catch (LdapException e) {
+                throw new RuntimeException(e);
             }
-            cursor.close();
-        }catch (Exception e) {
-            System.out.println( "Exception caught!" );
-            System.out.println( e.getClass().getCanonicalName() );
-            System.out.println( e.getMessage() );
-            System.out.println( e.getCause() );
-        } catch (CursorException ce) {
-            System.out.println( "Cursor Exception caught!" );
-        }catch (LdapException le) {
-            System.out.println( "Ldap Exception caught!" );
-        }
-        return false;
+        });
+        return result;
     }
 
     @Override
-    public void createAccount(String username, String sshPublicKey) {
+    public void createAccount(String userId, String sshPublicKey) {
 
         throw new UnsupportedOperationException("IULdapSSHAccountProvisioner does not support creating cluster accounts at this time.");
     }
 
     @Override
-    public void installSSHKey(String username, String sshPublicKey) {
-        // TODO: implement
-        // use Eric Coulter's LdapBazookaSearchAndAdd to accomplsih this
-        String GatewaySSHPublicKey = sshPublicKey;
-        String IULocalUserName = username;
-
-
-        /*
-        LdapConnectionConfig lcconfig = new LdapConnectionConfig();
-        lcconfig.setLdapHost(ldapservername);// LdapServerName = ldapserverName;//from ConfigParam should be like bazooka.hpc.iu.edu
-        lcconfig.setLdapPort(ldapPortId);// LdapPortID = ldapPortId;//from ConfigParam 636
-        lcconfig.setName(adminDN);// = adminName;//from ConfigParam sgrcusr
-        lcconfig.setCredentials(AdminPass);//from ConfigParam "lore footwork engorge"
-
-        DefaultLdapConnectionFactory lcfactory = new DefaultLdapConnectionFactory( lcconfig );
-        lcfactory.setTimeOut( connectionTimeout );
-        */
-
-            Modification addSSHPublicKeyAdd = new DefaultModification(ModificationOperation.ADD_ATTRIBUTE,"add","sshPublicKey");
-            Modification SSHPublicKey = new DefaultModification(ModificationOperation.ADD_ATTRIBUTE, "sshPublicKey",GatewaySSHPublicKey);
-            /*
-            Entry modentry = New DefaultEntry(
-                    "cn=sgrcusr,dc=rt,dc=iu,dc=edu",
-                    "ObjectClass: person",
-                    "ObjectClass: ldapPublicKey",
-                    "cn", username,
-                    "dn", "uid=",username, "ou=bigred2-sgrc,dc=rt,dc=iu,dc=edu",
-                    "add: sshPublicKey",
-                    "sshPublicKey", GatewaySSHPublicKey );
-                    */
+    public void installSSHKey(String userId, String sshPublicKey) {
+        String username = getUsername(userId);
+        boolean success = withLdapConnection(ldapConnection -> {
             try {
-                connection.modify(ldapBaseDN, addSSHPublicKeyAdd );//ldapmodify
-                connection.modify(ldapBaseDN, SSHPublicKey );
-            } catch (Exception e) {
-                System.out.println("Exception caught!", e);
-                System.out.println( e.getClass().getCanonicalName() );
-                System.out.println( e.getMessage() );
-                System.out.println( e.getCause() );
+                String dn = "uid=" + username + "," + ldapBaseDN;
+
+                Entry entry = ldapConnection.lookup(dn);
+                if (entry == null) {
+                    throw new RuntimeException("User [" + username + "] has no entry for " + dn);
+                }
+                boolean hasLdapPublicKey = entry.hasObjectClass(LDAP_PUBLIC_KEY_OBJECT_CLASS);
+
+                ModifyRequest modifyRequest = new ModifyRequestImpl();
+                modifyRequest.setName(new Dn(dn));
+
+                // Add or Replace, depending on whether there is already an ldapPublicKey on the entry
+                if (!hasLdapPublicKey) {
+
+                    modifyRequest.addModification(new DefaultAttribute("objectclass", LDAP_PUBLIC_KEY_OBJECT_CLASS), ModificationOperation.ADD_ATTRIBUTE);
+                    modifyRequest.addModification(new DefaultAttribute(SSH_PUBLIC_KEY_ATTRIBUTE_NAME, sshPublicKey), ModificationOperation.ADD_ATTRIBUTE);
+                } else {
+
+                    modifyRequest.addModification(new DefaultAttribute(SSH_PUBLIC_KEY_ATTRIBUTE_NAME, sshPublicKey), ModificationOperation.REPLACE_ATTRIBUTE);
+                }
+                ModifyResponse modifyResponse = ldapConnection.modify(modifyRequest);
+                if (modifyResponse.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS) {
+                    logger.warn("installSSHKey ldap operation reported not being successful: " + modifyResponse);
+                } else {
+                    logger.debug("installSSHKey ldap operation was successful: " + modifyResponse);
+                }
+                return true;
+            } catch (LdapException e) {
+                throw new RuntimeException(e);
             }
-
+        });
     }
 
     @Override
-    public String getScratchLocation(String username) {
-        // TODO: implement
-        //if scratch location is available get it or else set a new scratch location for the user
-        String canonicalScratch =  config.get(new ConfigParam("canonicalScratch"));//"/N/cd2/_USER_/scratch"
-        String scratchLocation = canonicalScratch.replace("_USER_",username);
+    public String getScratchLocation(String userId) {
+        String username = getUsername(userId);
+        String scratchLocation = canonicalScratchLocation.replace("${username}",username);
         return scratchLocation;
-        //return null;
+    }
+
+    private <R> R withLdapConnection(Function<LdapConnection,R> function) {
+
+        try (LdapConnection connection = new LdapNetworkConnection(ldapHost, ldapPort, true)) {
+
+            connection.bind(ldapUsername, ldapPassword);
+
+            R result = function.apply(connection);
+
+            connection.unBind();
+
+            return result;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } catch (LdapException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Convert from Airavata userId to cluster username. The assumption here is that a userId will be
+     * an IU email address and the username is just the username portion of the email address.
+     */
+    private String getUsername(String userId) {
+        int atSignIndex = userId.indexOf("@");
+        if (atSignIndex < 0) {
+            throw new RuntimeException("userId is not an email address: " + userId);
+        }
+        return userId.substring(0, atSignIndex);
+    }
+
+    public static void main(String[] args) {
+        String ldapPassword = args[0];
+        IULdapSSHAccountProvisioner sshAccountProvisioner = new IULdapSSHAccountProvisioner();
+        Map<ConfigParam,String> config = new HashMap<>();
+        // Create SSH tunnel to server that has firewall access to bazooka:
+        //   ssh airavata@apidev.scigap.org -L 9000:bazooka.hps.iu.edu:636 -N &
+        // Put entry in /etc/hosts with the following
+        //   127.0.0.1	bazooka.hps.iu.edu
+        config.put(IULdapSSHAccountProvisionerProvider.LDAP_HOST, "bazooka.hps.iu.edu");
+        config.put(IULdapSSHAccountProvisionerProvider.LDAP_PORT, "9000"); // ssh tunnel port
+        config.put(IULdapSSHAccountProvisionerProvider.LDAP_USERNAME, "cn=sgrcusr,dc=rt,dc=iu,dc=edu");
+        config.put(IULdapSSHAccountProvisionerProvider.LDAP_PASSWORD, ldapPassword);
+        config.put(IULdapSSHAccountProvisionerProvider.LDAP_BASE_DN, "ou=bigred2-sgrc,dc=rt,dc=iu,dc=edu");
+        config.put(IULdapSSHAccountProvisionerProvider.CANONICAL_SCRATCH_LOCATION, "/N/dc2/scratch/${username}/iu-gateway");
+        sshAccountProvisioner.init(config);
+        String userId = "machrist@iu.edu";
+        System.out.println("hasAccount=" + sshAccountProvisioner.hasAccount(userId));
+        System.out.println("scratchLocation=" + sshAccountProvisioner.getScratchLocation(userId));
+        sshAccountProvisioner.installSSHKey(userId, "foobar1234");
     }
 }

http://git-wip-us.apache.org/repos/asf/airavata/blob/daedef2e/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisionerProvider.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisionerProvider.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisionerProvider.java
index 45dc0a6..9089ac3 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisionerProvider.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisionerProvider.java
@@ -24,32 +24,41 @@ import org.apache.airavata.accountprovisioning.ConfigParam;
 import org.apache.airavata.accountprovisioning.SSHAccountProvisioner;
 import org.apache.airavata.accountprovisioning.SSHAccountProvisionerProvider;
 
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
 public class IULdapSSHAccountProvisionerProvider implements SSHAccountProvisionerProvider {
 
+    public static final ConfigParam LDAP_HOST = new ConfigParam("ldap-host")
+            .setDescription("Hostname of LDAP server")
+            .setOptional(false)
+            .setType(ConfigParam.ConfigParamType.STRING);
+    public static final ConfigParam LDAP_PORT = new ConfigParam("ldap-port")
+            .setDescription("Port of LDAP server")
+            .setOptional(false)
+            .setType(ConfigParam.ConfigParamType.STRING);
+    public static final ConfigParam LDAP_USERNAME = new ConfigParam("ldap-username")
+            .setDescription("Username for LDAP server")
+            .setOptional(false)
+            .setType(ConfigParam.ConfigParamType.STRING);
+    public static final ConfigParam LDAP_PASSWORD = new ConfigParam("ldap-password")
+            .setDescription("Password for LDAP server")
+            .setOptional(false)
+            .setType(ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN);
+    public static final ConfigParam LDAP_BASE_DN = new ConfigParam("ldap-base-dn")
+            .setDescription("Base DN for searching, modifying cluster LDAP")
+            .setOptional(false)
+            .setType(ConfigParam.ConfigParamType.STRING);
+    public static final ConfigParam CANONICAL_SCRATCH_LOCATION = new ConfigParam("canonical-scratch-location")
+            .setDescription("Pattern for scratch location. Use ${username} as replacement for username. For example, '/N/dc2/scratch/${username}/iu-gateway'.")
+            .setOptional(false)
+            .setType(ConfigParam.ConfigParamType.STRING);
+    public static final List<ConfigParam> CONFIG_PARAMS = Arrays.asList(LDAP_HOST, LDAP_PORT, LDAP_USERNAME, LDAP_PASSWORD, LDAP_BASE_DN, CANONICAL_SCRATCH_LOCATION);
+
     @Override
     public List<ConfigParam> getConfigParams() {
-        List<ConfigParam> configParams = new ArrayList<>();
-        configParams.add(new ConfigParam("ldap-host")
-                .setDescription("Hostname of LDAP server")
-                .setOptional(false)
-                .setType(ConfigParam.ConfigParamType.STRING));
-        configParams.add(new ConfigParam("ldap-port")
-                .setDescription("Port of LDAP server")
-                .setOptional(false)
-                .setType(ConfigParam.ConfigParamType.STRING));
-        configParams.add(new ConfigParam("ldap-username")
-                .setDescription("Username for LDAP server")
-                .setOptional(false)
-                .setType(ConfigParam.ConfigParamType.STRING));
-        configParams.add(new ConfigParam("ldap-password")
-                .setDescription("Password for LDAP server")
-                .setOptional(false)
-                .setType(ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN));
-        return configParams;
+        return CONFIG_PARAMS;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/airavata/blob/daedef2e/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
index 54d5f1c..34171af 100644
--- a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
+++ b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/SSHAccountProvisionerFactoryTest.java
@@ -56,10 +56,6 @@ public class SSHAccountProvisionerFactoryTest {
         ConfigParam ldapPassword = configParams.get(3);
         Assert.assertEquals("ldap_password", ldapPassword.getName());
         Assert.assertEquals(ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN, ldapPassword.getType());
-        ConfigParam ldapBaseDN = configParams.get(4);
-        Assert.assertArrayEquals("ldapBaseDN", ldapBaseDN.getName()  );
-        Assert.assertArrayEquals( ConfigParam.ConfigParamType.STRING,ldapBaseDN.getType() );
-
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/airavata/blob/daedef2e/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
index 7eb4250..3b11a91 100644
--- a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
+++ b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisionerProvider.java
@@ -57,7 +57,7 @@ public class TestSSHAccountProvisionerProvider implements SSHAccountProvisionerP
         configParams.add(new ConfigParam("ldapBaseDN")
                 .setDescription( "Base DN for the ldap entry" )
                 .setOptional( false )
-                .setType( ConfigParam.ConfigParamType.STRING );
+                .setType( ConfigParam.ConfigParamType.STRING ));
         return configParams;
     }