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 2018/10/02 18:37:40 UTC
[airavata] 01/04: IU LDAP ssh account: add user to cybergateway
group
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata.git
commit 18d0e4e10f27a4b189eab0a234fb02dd0edff439
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Tue Oct 2 12:36:59 2018 -0400
IU LDAP ssh account: add user to cybergateway group
---
.../accountprovisioning/SSHAccountProvisioner.java | 9 ++
.../provisioner/IULdapSSHAccountProvisioner.java | 165 +++++++++++++++------
.../IULdapSSHAccountProvisionerProvider.java | 6 +-
.../provisioner/TestSSHAccountProvisioner.java | 5 +
4 files changed, 142 insertions(+), 43 deletions(-)
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java
index 6ad076d..fe1499f 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java
@@ -56,6 +56,15 @@ public interface SSHAccountProvisioner {
String createAccount(String userId, String sshPublicKey) throws InvalidUsernameException;
/**
+ * Return true if this sshPublicKey has been installed for this user account and all other related setup tasks are complete.
+ * @param userId
+ * @param sshPublicKey
+ * @return
+ * @throws InvalidUsernameException
+ */
+ boolean isSSHAccountProvisioningComplete(String userId, String sshPublicKey) throws InvalidUsernameException;
+
+ /**
* Install an SSH key for the user on the compute host.
* @param userId the Airavata user id
* @param sshPublicKey the public key part of an Airavata managed SSH credential
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 e35c118..83d7f3a 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
@@ -24,14 +24,12 @@ import org.apache.airavata.accountprovisioning.ConfigParam;
import org.apache.airavata.accountprovisioning.InvalidUsernameException;
import org.apache.airavata.accountprovisioning.SSHAccountManager;
import org.apache.airavata.accountprovisioning.SSHAccountProvisioner;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
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.ModificationOperation;
import org.apache.directory.api.ldap.model.exception.LdapException;
-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.apache.directory.api.ldap.model.message.*;
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;
@@ -48,8 +46,9 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
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";
+ public static final String GROUP_MEMBER_ATTRIBUTE_NAME = "memberUid";
- private String ldapHost, ldapUsername, ldapPassword, ldapBaseDN, canonicalScratchLocation;
+ private String ldapHost, ldapUsername, ldapPassword, ldapBaseDN, canonicalScratchLocation, cybergatewayGroupDN;
private int ldapPort;
@Override
public void init(Map<ConfigParam, String> config) {
@@ -60,6 +59,7 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
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"
+ cybergatewayGroupDN = config.get(IULdapSSHAccountProvisionerProvider.CYBERGATEWAY_GROUP_DN); // "cn=cybergateway,ou=Group,dc=rt,dc=iu,dc=edu"
}
@Override
@@ -67,7 +67,7 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
String username = getUsername(userId);
boolean result = withLdapConnection(ldapConnection -> {
try {
- return ldapConnection.exists("uid=" + username + "," + ldapBaseDN);
+ return hasClusterAccount(ldapConnection, username);
} catch (LdapException e) {
throw new RuntimeException(e);
}
@@ -75,6 +75,27 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
return result;
}
+ private boolean hasClusterAccount(LdapConnection ldapConnection, String username) throws LdapException {
+
+ return ldapConnection.exists("uid=" + username + "," + ldapBaseDN);
+ }
+
+ private boolean isInCybergatewayGroup(LdapConnection ldapConnection, String username) throws LdapException {
+
+ final String filter = "(memberUid=" + username + ")";
+ try(EntryCursor entryCursor = ldapConnection.search(this.cybergatewayGroupDN, filter, SearchScope.OBJECT)) {
+
+ int count = 0;
+ for (Entry entry : entryCursor) {
+ count++;
+ logger.info("Found {} in cybergateway group", username);
+ }
+ return count == 1;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@Override
public String createAccount(String userId, String sshPublicKey) throws InvalidUsernameException {
@@ -82,47 +103,40 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
}
@Override
+ public boolean isSSHAccountProvisioningComplete(String userId, String sshPublicKey) throws InvalidUsernameException {
+ String username = getUsername(userId);
+ boolean result = withLdapConnection(ldapConnection -> {
+ try {
+ return hasClusterAccount(ldapConnection, username)
+ && isInCybergatewayGroup(ldapConnection, username)
+ && isSSHKeyInstalled(ldapConnection, username, sshPublicKey);
+ } catch (LdapException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ return result;
+ }
+
+ public boolean isSSHKeyInstalled(LdapConnection ldapConnection, String username, String sshPublicKey) throws LdapException {
+
+ String ldapPublicKey = getLdapPublicKey(ldapConnection, username);
+ return ldapPublicKey != null && ldapPublicKey.equals(sshPublicKey.trim());
+ }
+
+ @Override
public String installSSHKey(String userId, String sshPublicKey) throws InvalidUsernameException {
String username = getUsername(userId);
String finalSSHPublicKey = sshPublicKey.trim();
boolean success = withLdapConnection(ldapConnection -> {
try {
- 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, finalSSHPublicKey),
- ModificationOperation.ADD_ATTRIBUTE);
- } else {
-
- String oldSshPublicKey = entry.get(SSH_PUBLIC_KEY_ATTRIBUTE_NAME).getString();
- if (!oldSshPublicKey.equals(finalSSHPublicKey)) {
- // Disallow overwriting the SSH key
- throw new RuntimeException("User [" + username + "] already has an SSH public key in LDAP for ["
- + ldapBaseDN + "] and overwriting it isn't allowed.");
- // modifyRequest.addModification(new DefaultAttribute(SSH_PUBLIC_KEY_ATTRIBUTE_NAME,
- // sshPublicKey), ModificationOperation.REPLACE_ATTRIBUTE);
- } else {
- // SSH key is already installed so just return
- return true;
- }
+ // 1) Check to see if key is installed, and if not, install it
+ // 2) Check to see if user is in cybergateway group and if not add the user
+ // This is because the user may have the key installed but not be in the group
+ if (!isSSHKeyInstalled(ldapConnection, username, finalSSHPublicKey)) {
+ installLdapPublicKey(ldapConnection, username, finalSSHPublicKey);
}
- 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);
+ if (!isInCybergatewayGroup(ldapConnection, username)) {
+ addUserToCybergatewayGroup(ldapConnection, username);
}
return true;
} catch (LdapException e) {
@@ -132,6 +146,65 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
return username;
}
+ private void addUserToCybergatewayGroup(LdapConnection ldapConnection, String username) throws LdapException {
+
+ ModifyRequest modifyRequest = new ModifyRequestImpl();
+ modifyRequest.setName(new Dn(cybergatewayGroupDN));
+ modifyRequest.addModification(new DefaultAttribute(GROUP_MEMBER_ATTRIBUTE_NAME, username),
+ ModificationOperation.ADD_ATTRIBUTE);
+ ModifyResponse modifyResponse = ldapConnection.modify(modifyRequest);
+ if (modifyResponse.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS) {
+ logger.warn("add member to cybergateway group ldap operation reported not being successful: " + modifyResponse);
+ } else {
+ logger.debug("add member to cybergateway group ldap operation was successful: " + modifyResponse);
+ }
+ }
+
+ private void installLdapPublicKey(LdapConnection ldapConnection, String username, String finalSSHPublicKey) throws LdapException {
+ String dn = "uid=" + username + "," + ldapBaseDN;
+
+ String ldapPublicKey = getLdapPublicKey(ldapConnection, username);
+ Entry entry = ldapConnection.lookup(dn);
+ if (entry == null) {
+ throw new RuntimeException("User [" + username + "] has no entry for " + dn);
+ }
+
+ ModifyRequest modifyRequest = new ModifyRequestImpl();
+ modifyRequest.setName(new Dn(dn));
+
+ // Add or Replace, depending on whether there is already an ldapPublicKey on the entry
+ if (ldapPublicKey == null) {
+
+ modifyRequest.addModification(new DefaultAttribute("objectclass", LDAP_PUBLIC_KEY_OBJECT_CLASS), ModificationOperation.ADD_ATTRIBUTE);
+ modifyRequest.addModification(new DefaultAttribute(SSH_PUBLIC_KEY_ATTRIBUTE_NAME, finalSSHPublicKey),
+ ModificationOperation.ADD_ATTRIBUTE);
+ } else {
+
+ if (!ldapPublicKey.equals(finalSSHPublicKey)) {
+ modifyRequest.addModification(new DefaultAttribute(SSH_PUBLIC_KEY_ATTRIBUTE_NAME,
+ finalSSHPublicKey), 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);
+ }
+ }
+
+ private String getLdapPublicKey(LdapConnection ldapConnection, String username) throws LdapException {
+
+ 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);
+ return hasLdapPublicKey ? entry.get(SSH_PUBLIC_KEY_ATTRIBUTE_NAME).getString() : null;
+ }
+
@Override
public String getScratchLocation(String userId) throws InvalidUsernameException {
String username = getUsername(userId);
@@ -183,10 +256,18 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
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");
+ config.put(IULdapSSHAccountProvisionerProvider.CYBERGATEWAY_GROUP_DN, "cn=cybergateway,ou=Group,dc=rt,dc=iu,dc=edu");
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");
+ String sshPublicKey = "foobar12345";
+ boolean sshAccountProvisioningComplete = sshAccountProvisioner.isSSHAccountProvisioningComplete(userId, sshPublicKey);
+ System.out.println("isSSHAccountProvisioningComplete=" + sshAccountProvisioningComplete);
+ if (!sshAccountProvisioningComplete) {
+ sshAccountProvisioner.installSSHKey(userId, sshPublicKey);
+ sshAccountProvisioningComplete = sshAccountProvisioner.isSSHAccountProvisioningComplete(userId, sshPublicKey);
+ System.out.println("isSSHAccountProvisioningComplete=" + sshAccountProvisioningComplete);
+ }
}
}
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 9089ac3..b09334d 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
@@ -54,7 +54,11 @@ public class IULdapSSHAccountProvisionerProvider implements SSHAccountProvisione
.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);
+ public static final ConfigParam CYBERGATEWAY_GROUP_DN = new ConfigParam("cybergateway-group-dn")
+ .setDescription("Cybergateway group DN")
+ .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, CYBERGATEWAY_GROUP_DN);
@Override
public List<ConfigParam> getConfigParams() {
diff --git a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java
index 4cdcbd6..0df60de 100644
--- a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java
+++ b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java
@@ -48,6 +48,11 @@ public class TestSSHAccountProvisioner implements SSHAccountProvisioner {
}
@Override
+ public boolean isSSHAccountProvisioningComplete(String userId, String sshPublicKey) throws InvalidUsernameException {
+ return false;
+ }
+
+ @Override
public String installSSHKey(String userId, String sshPublicKey) throws InvalidUsernameException {
return userId;