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/26 19:09:34 UTC
[05/40] airavata git commit: AIRAVATA-2500 SSHAccountManager: install
SSH key and verify
AIRAVATA-2500 SSHAccountManager: install SSH key and verify
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/3d161b81
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/3d161b81
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/3d161b81
Branch: refs/heads/develop
Commit: 3d161b8161975be658259739047e36df3bd6ef38
Parents: 2a90139
Author: Marcus Christie <ma...@apache.org>
Authored: Mon Aug 14 12:38:53 2017 -0400
Committer: Marcus Christie <ma...@apache.org>
Committed: Tue Sep 19 15:07:56 2017 -0400
----------------------------------------------------------------------
.../accountprovisioning/SSHAccountManager.java | 104 ++++++++++++++-----
.../airavata/accountprovisioning/SSHUtil.java | 83 +++++++++++++++
2 files changed, 162 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/airavata/blob/3d161b81/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
index dcb819b..d565fe9 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
@@ -25,43 +25,48 @@ import org.apache.airavata.common.utils.ServerSettings;
import org.apache.airavata.credential.store.client.CredentialStoreClientFactory;
import org.apache.airavata.credential.store.cpi.CredentialStoreService;
import org.apache.airavata.credential.store.exception.CredentialStoreException;
+import org.apache.airavata.model.appcatalog.accountprovisioning.SSHAccountProvisionerConfigParam;
+import org.apache.airavata.model.appcatalog.computeresource.ComputeResourceDescription;
+import org.apache.airavata.model.appcatalog.gatewayprofile.ComputeResourcePreference;
import org.apache.airavata.model.credential.store.PasswordCredential;
+import org.apache.airavata.model.credential.store.SSHCredential;
import org.apache.airavata.registry.api.RegistryService;
import org.apache.airavata.registry.api.client.RegistryServiceClientFactory;
import org.apache.airavata.registry.api.exception.RegistryServiceException;
import org.apache.thrift.TException;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
public class SSHAccountManager {
- // TODO: need private key too to verify
- public static void setupSSHAccount(String gatewayId, String hostname, String username, String sshPublicKey) {
-
- // TODO: finish implementing
+ // TODO: change return type to one that returns some details of the SSH account setup, for example the scratch location
+ public static void setupSSHAccount(String gatewayId, String computeResourceId, String username, SSHCredential sshCredential) {
// get compute resource preferences for the gateway and hostname
+ // TODO: close the registry service client transport when done with it
+ RegistryService.Client registryServiceClient = getRegistryServiceClient();
+ ComputeResourcePreference computeResourcePreference = null;
+ ComputeResourceDescription computeResourceDescription = null;
+ try {
+ computeResourcePreference = registryServiceClient.getGatewayComputeResourcePreference(gatewayId, computeResourceId);
+ computeResourceDescription = registryServiceClient.getComputeResource(computeResourceId);
+ } catch(TException e) {
+ throw new RuntimeException(e);
+ }
// get the account provisioner and config values for the preferences
- String provisionerName = null;
- Map<ConfigParam,String> provisionerConfig = null;
-
- CredentialStoreService.Client credentialStoreServiceClient = getCredentialStoreClient();
- // Resolve any CRED_STORE_PASSWORD_TOKEN config parameters to passwords
- Map<ConfigParam,String> resolvedConfig = new HashMap<>();
- for (Map.Entry<ConfigParam,String> configEntry : provisionerConfig.entrySet() ) {
- if (configEntry.getKey().getType() == ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN) {
- try {
- PasswordCredential password = credentialStoreServiceClient.getPasswordCredential(configEntry.getValue(), gatewayId);
- resolvedConfig.put(configEntry.getKey(), password.getPassword());
- } catch (TException e) {
- throw new RuntimeException("Failed to get password needed to configure " + provisionerName);
- }
- } else {
- resolvedConfig.put(configEntry.getKey(), configEntry.getValue());
- }
+ if (!computeResourcePreference.isSetSshAccountProvisioner()) {
+ // TODO: provide better exception?
+ throw new RuntimeException("Compute resource [" + computeResourceId + "] does not have an SSH Account Provisioner configured for it.");
}
+ String provisionerName = computeResourcePreference.getSshAccountProvisioner();
+ Map<ConfigParam,String> provisionerConfig = convertConfigParams(provisionerName, computeResourcePreference.getSshAccountProvisionerConfig());
+
+ Map<ConfigParam, String> resolvedConfig = resolveProvisionerConfig(gatewayId, provisionerName, provisionerConfig);
// instantiate and init the account provisioner
SSHAccountProvisioner sshAccountProvisioner = SSHAccountProvisionerFactory.createSSHAccountProvisioner(provisionerName, resolvedConfig);
@@ -70,23 +75,72 @@ public class SSHAccountManager {
boolean hasAccount = sshAccountProvisioner.hasAccount(username);
if (!hasAccount && !sshAccountProvisioner.canCreateAccount()) {
- // TODO: throw an exception
+ // TODO: provide better exception
+ throw new RuntimeException("User [" + username + "] doesn't have account and [" + provisionerName + "] doesn't support creating account.");
}
// TODO: first check if SSH key is already installed, or do we care?
// Install SSH key
+ sshAccountProvisioner.installSSHKey(username, sshCredential.getPublicKey());
// Verify can authenticate to host
+ boolean validated = SSHUtil.validate(username, computeResourceDescription.getHostName(), 22, sshCredential);
+ if (!validated) {
+ throw new RuntimeException("Failed to validate installation of key for [" + username
+ + "] on [" + computeResourceDescription.getHostName() + "] using SSH Account Provisioner ["
+ + computeResourcePreference.getSshAccountProvisioner() + "]");
+ }
// create the scratch location on the host
+ // TODO: create the scratch location
String scratchLocation = sshAccountProvisioner.getScratchLocation(username);
}
- private static RegistryService.Client getRegistryServiceClient() throws RegistryServiceException {
+ private static Map<ConfigParam, String> resolveProvisionerConfig(String gatewayId, String provisionerName, Map<ConfigParam, String> provisionerConfig) {
+ CredentialStoreService.Client credentialStoreServiceClient = null;
+ try {
+ credentialStoreServiceClient = getCredentialStoreClient();
+ // Resolve any CRED_STORE_PASSWORD_TOKEN config parameters to passwords
+ Map<ConfigParam, String> resolvedConfig = new HashMap<>();
+ for (Map.Entry<ConfigParam, String> configEntry : provisionerConfig.entrySet()) {
+ if (configEntry.getKey().getType() == ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN) {
+ try {
+ PasswordCredential password = credentialStoreServiceClient.getPasswordCredential(configEntry.getValue(), gatewayId);
+ resolvedConfig.put(configEntry.getKey(), password.getPassword());
+ } catch (TException e) {
+ throw new RuntimeException("Failed to get password needed to configure " + provisionerName);
+ }
+ } else {
+ resolvedConfig.put(configEntry.getKey(), configEntry.getValue());
+ }
+ }
+ return resolvedConfig;
+ } finally {
+ if (credentialStoreServiceClient != null) {
+ if (credentialStoreServiceClient.getInputProtocol().getTransport().isOpen()) {
+ credentialStoreServiceClient.getInputProtocol().getTransport().close();
+ }
+ }
+ }
+ }
+
+ private static Map<ConfigParam, String> convertConfigParams(String provisionerName, Map<SSHAccountProvisionerConfigParam, String> thriftConfigParams) {
+ List<ConfigParam> configParams = SSHAccountProvisionerFactory.getSSHAccountProvisionerConfigParams(provisionerName);
+ Map<String, ConfigParam> configParamMap = configParams.stream().collect(Collectors.toMap(ConfigParam::getName, Function.identity()));
- // TODO: finish implementing
- return RegistryServiceClientFactory.createRegistryClient(null, 0);
+ return thriftConfigParams.entrySet().stream().collect(Collectors.toMap(entry -> configParamMap.get(entry.getKey().getName()), entry -> entry.getValue()));
+ }
+
+ private static RegistryService.Client getRegistryServiceClient() {
+
+ try {
+ String registryServerHost = ServerSettings.getRegistryServerHost();
+ int registryServerPort = Integer.valueOf(ServerSettings.getRegistryServerPort());
+ return RegistryServiceClientFactory.createRegistryClient(registryServerHost, registryServerPort);
+ } catch (ApplicationSettingsException|RegistryServiceException e) {
+ throw new RuntimeException("Failed to create registry service client", e);
+ }
}
private static CredentialStoreService.Client getCredentialStoreClient() {
http://git-wip-us.apache.org/repos/asf/airavata/blob/3d161b81/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java
new file mode 100644
index 0000000..4b5452a
--- /dev/null
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.accountprovisioning;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import org.apache.airavata.model.credential.store.SSHCredential;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.UUID;
+
+/**
+ * Created by machrist on 2/10/17.
+ */
+public class SSHUtil {
+
+ public static boolean validate(String username, String hostname, int port, SSHCredential sshCredential) {
+
+ JSch jSch = new JSch();
+ Session session = null;
+ try {
+ jSch.addIdentity(UUID.randomUUID().toString(), sshCredential.getPrivateKey().getBytes(), sshCredential.getPublicKey().getBytes(), sshCredential.getPassphrase().getBytes());
+ session = jSch.getSession(username, hostname, port);
+ java.util.Properties config = new java.util.Properties();
+ config.put("StrictHostKeyChecking", "no");
+ session.setConfig(config);
+ session.connect();
+ return true;
+ } catch (JSchException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } finally {
+ if (session != null && session.isConnected()) {
+ session.disconnect();
+ }
+ }
+ }
+
+ public static void main(String[] args) throws JSchException {
+
+ // Test the validate method
+ String username = System.getProperty("user.name");
+ String privateKeyFilepath = System.getProperty("user.home") + "/.ssh/id_rsa";
+ String publicKeyFilepath = privateKeyFilepath + ".pub";
+ String passphrase = "changeme";
+ String hostname = "changeme";
+
+ Path privateKeyPath = Paths.get(privateKeyFilepath);
+ Path publicKeyPath = Paths.get(publicKeyFilepath);
+
+ SSHCredential sshCredential = new SSHCredential();
+ sshCredential.setPassphrase(passphrase);
+ try {
+ sshCredential.setPublicKey(new String(Files.readAllBytes(publicKeyPath), "UTF-8"));
+ sshCredential.setPrivateKey(new String(Files.readAllBytes(privateKeyPath), "UTF-8"));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ boolean result = validate(username, hostname, 22, sshCredential);
+ System.out.println(result);
+ }
+}