From 48ea4a0f7be09235011960612c64756ef55e52b7 Mon Sep 17 00:00:00 2001 From: Anuj Bhandar Date: Mon, 24 Oct 2016 20:19:44 -0400 Subject: [PATCH] adding token to credential summary model --- .../server/handler/AiravataServerHandler.java | 2 + .../credentialsummary/CredentialSummary.java | 127 +++++++++++-- .../store/store/impl/db/CredentialsDAO.java | 4 +- .../cpi/SSHSummaryTest/SSHSummaryTest.java | 173 ++++++++++++++++++ .../store/impl/db/CredentialsDAOTest.java | 4 +- .../credential_summary.thrift | 7 +- 6 files changed, 298 insertions(+), 19 deletions(-) create mode 100644 modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/cpi/SSHSummaryTest/SSHSummaryTest.java diff --git a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java index a98e93b43a..9c44de5f05 100644 --- a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java +++ b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java @@ -551,6 +551,7 @@ public List getAllGatewaySSHPubKeysSummary(AuthzToken authzTo summary.setGatewayId(key.getGatewayId()); summary.setUsername(key.getUsername()); summary.setPublicKey(key.getPublicKey()); + summary.setToken(key.getToken()); summary.setDescription(key.getDescription()); summary.setPersistedTime(key.getPersistedTime()); allCredentialSummaries.add(summary); @@ -579,6 +580,7 @@ public List getAllSSHPubKeysSummaryForUserInGateway(AuthzToke userPubKeySummary.setGatewayId(key.getGatewayId()); userPubKeySummary.setUsername(key.getUsername()); userPubKeySummary.setPublicKey(key.getPublicKey()); + userPubKeySummary.setToken(key.getToken()); userPubKeySummary.setDescription(key.getDescription()); userPubKeySummary.setPersistedTime(key.getPersistedTime()); allCredentialSummaries.add(userPubKeySummary); diff --git a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/credentialsummary/CredentialSummary.java b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/credentialsummary/CredentialSummary.java index 5f3fc8221c..280da598fd 100644 --- a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/credentialsummary/CredentialSummary.java +++ b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/credentialsummary/CredentialSummary.java @@ -57,9 +57,10 @@ public class CredentialSummary implements org.apache.thrift.TBase, SchemeFactory> schemes = new HashMap, SchemeFactory>(); static { @@ -69,6 +70,7 @@ public class CredentialSummary implements org.apache.thrift.TBase byName = new HashMap(); @@ -98,11 +101,13 @@ public static _Fields findByThriftId(int fieldId) { return GATEWAY_ID; case 2: // USERNAME return USERNAME; - case 3: // PUBLIC_KEY + case 3: // TOKEN + return TOKEN; + case 4: // PUBLIC_KEY return PUBLIC_KEY; - case 4: // PERSISTED_TIME + case 5: // PERSISTED_TIME return PERSISTED_TIME; - case 5: // DESCRIPTION + case 6: // DESCRIPTION return DESCRIPTION; default: return null; @@ -154,6 +159,8 @@ public String getFieldName() { new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.USERNAME, new org.apache.thrift.meta_data.FieldMetaData("username", org.apache.thrift.TFieldRequirementType.REQUIRED, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.TOKEN, new org.apache.thrift.meta_data.FieldMetaData("token", org.apache.thrift.TFieldRequirementType.REQUIRED, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.PUBLIC_KEY, new org.apache.thrift.meta_data.FieldMetaData("publicKey", org.apache.thrift.TFieldRequirementType.OPTIONAL, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.PERSISTED_TIME, new org.apache.thrift.meta_data.FieldMetaData("persistedTime", org.apache.thrift.TFieldRequirementType.OPTIONAL, @@ -169,11 +176,13 @@ public CredentialSummary() { public CredentialSummary( String gatewayId, - String username) + String username, + String token) { this(); this.gatewayId = gatewayId; this.username = username; + this.token = token; } /** @@ -187,6 +196,9 @@ public CredentialSummary(CredentialSummary other) { if (other.isSetUsername()) { this.username = other.username; } + if (other.isSetToken()) { + this.token = other.token; + } if (other.isSetPublicKey()) { this.publicKey = other.publicKey; } @@ -204,6 +216,7 @@ public CredentialSummary deepCopy() { public void clear() { this.gatewayId = null; this.username = null; + this.token = null; this.publicKey = null; setPersistedTimeIsSet(false); this.persistedTime = 0; @@ -256,6 +269,29 @@ public void setUsernameIsSet(boolean value) { } } + public String getToken() { + return this.token; + } + + public void setToken(String token) { + this.token = token; + } + + public void unsetToken() { + this.token = null; + } + + /** Returns true if field token is set (has been assigned a value) and false otherwise */ + public boolean isSetToken() { + return this.token != null; + } + + public void setTokenIsSet(boolean value) { + if (!value) { + this.token = null; + } + } + public String getPublicKey() { return this.publicKey; } @@ -342,6 +378,14 @@ public void setFieldValue(_Fields field, Object value) { } break; + case TOKEN: + if (value == null) { + unsetToken(); + } else { + setToken((String)value); + } + break; + case PUBLIC_KEY: if (value == null) { unsetPublicKey(); @@ -377,6 +421,9 @@ public Object getFieldValue(_Fields field) { case USERNAME: return getUsername(); + case TOKEN: + return getToken(); + case PUBLIC_KEY: return getPublicKey(); @@ -401,6 +448,8 @@ public boolean isSet(_Fields field) { return isSetGatewayId(); case USERNAME: return isSetUsername(); + case TOKEN: + return isSetToken(); case PUBLIC_KEY: return isSetPublicKey(); case PERSISTED_TIME: @@ -442,6 +491,15 @@ public boolean equals(CredentialSummary that) { return false; } + boolean this_present_token = true && this.isSetToken(); + boolean that_present_token = true && that.isSetToken(); + if (this_present_token || that_present_token) { + if (!(this_present_token && that_present_token)) + return false; + if (!this.token.equals(that.token)) + return false; + } + boolean this_present_publicKey = true && this.isSetPublicKey(); boolean that_present_publicKey = true && that.isSetPublicKey(); if (this_present_publicKey || that_present_publicKey) { @@ -486,6 +544,11 @@ public int hashCode() { if (present_username) list.add(username); + boolean present_token = true && (isSetToken()); + list.add(present_token); + if (present_token) + list.add(token); + boolean present_publicKey = true && (isSetPublicKey()); list.add(present_publicKey); if (present_publicKey) @@ -532,6 +595,16 @@ public int compareTo(CredentialSummary other) { return lastComparison; } } + lastComparison = Boolean.valueOf(isSetToken()).compareTo(other.isSetToken()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetToken()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.token, other.token); + if (lastComparison != 0) { + return lastComparison; + } + } lastComparison = Boolean.valueOf(isSetPublicKey()).compareTo(other.isSetPublicKey()); if (lastComparison != 0) { return lastComparison; @@ -597,6 +670,14 @@ public String toString() { sb.append(this.username); } first = false; + if (!first) sb.append(", "); + sb.append("token:"); + if (this.token == null) { + sb.append("null"); + } else { + sb.append(this.token); + } + first = false; if (isSetPublicKey()) { if (!first) sb.append(", "); sb.append("publicKey:"); @@ -637,6 +718,10 @@ public void validate() throws org.apache.thrift.TException { throw new org.apache.thrift.protocol.TProtocolException("Required field 'username' is unset! Struct:" + toString()); } + if (!isSetToken()) { + throw new org.apache.thrift.protocol.TProtocolException("Required field 'token' is unset! Struct:" + toString()); + } + // check for sub-struct validity } @@ -692,7 +777,15 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, CredentialSummary s org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 3: // PUBLIC_KEY + case 3: // TOKEN + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.token = iprot.readString(); + struct.setTokenIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // PUBLIC_KEY if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.publicKey = iprot.readString(); struct.setPublicKeyIsSet(true); @@ -700,7 +793,7 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, CredentialSummary s org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 4: // PERSISTED_TIME + case 5: // PERSISTED_TIME if (schemeField.type == org.apache.thrift.protocol.TType.I64) { struct.persistedTime = iprot.readI64(); struct.setPersistedTimeIsSet(true); @@ -708,7 +801,7 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, CredentialSummary s org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 5: // DESCRIPTION + case 6: // DESCRIPTION if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.description = iprot.readString(); struct.setDescriptionIsSet(true); @@ -739,6 +832,11 @@ public void write(org.apache.thrift.protocol.TProtocol oprot, CredentialSummary oprot.writeString(struct.username); oprot.writeFieldEnd(); } + if (struct.token != null) { + oprot.writeFieldBegin(TOKEN_FIELD_DESC); + oprot.writeString(struct.token); + oprot.writeFieldEnd(); + } if (struct.publicKey != null) { if (struct.isSetPublicKey()) { oprot.writeFieldBegin(PUBLIC_KEY_FIELD_DESC); @@ -777,6 +875,7 @@ public void write(org.apache.thrift.protocol.TProtocol prot, CredentialSummary s TTupleProtocol oprot = (TTupleProtocol) prot; oprot.writeString(struct.gatewayId); oprot.writeString(struct.username); + oprot.writeString(struct.token); BitSet optionals = new BitSet(); if (struct.isSetPublicKey()) { optionals.set(0); @@ -806,6 +905,8 @@ public void read(org.apache.thrift.protocol.TProtocol prot, CredentialSummary st struct.setGatewayIdIsSet(true); struct.username = iprot.readString(); struct.setUsernameIsSet(true); + struct.token = iprot.readString(); + struct.setTokenIsSet(true); BitSet incoming = iprot.readBitSet(3); if (incoming.get(0)) { struct.publicKey = iprot.readString(); diff --git a/modules/credential-store/credential-store-service/src/main/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAO.java b/modules/credential-store/credential-store-service/src/main/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAO.java index 90e58af3d8..6d783e9110 100644 --- a/modules/credential-store/credential-store-service/src/main/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAO.java +++ b/modules/credential-store/credential-store-service/src/main/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAO.java @@ -316,7 +316,7 @@ public List getCredentials(String gatewayName, Connection connection byte[] certificate = blobCredentials.getBytes(1, (int) blobCredentials.length()); certificateCredential = (Credential) convertByteArrayToObject(certificate); - + certificateCredential.setToken("TOKEN_ID"); certificateCredential.setPortalUserName(resultSet.getString("PORTAL_USER_ID")); certificateCredential.setCertificateRequestedTime(resultSet.getTimestamp("TIME_PERSISTED")); certificateCredential.setDescription(resultSet.getString("DESCRIPTION")); @@ -366,7 +366,7 @@ public List getCredentials(Connection connection) throws CredentialS byte[] certificate = blobCredentials.getBytes(1, (int) blobCredentials.length()); certificateCredential = (Credential) convertByteArrayToObject(certificate); - + certificateCredential.setToken(resultSet.getString("TOKEN_ID")); certificateCredential.setPortalUserName(resultSet.getString("PORTAL_USER_ID")); certificateCredential.setCertificateRequestedTime(resultSet.getTimestamp("TIME_PERSISTED")); certificateCredential.setDescription(resultSet.getString("DESCRIPTION")); diff --git a/modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/cpi/SSHSummaryTest/SSHSummaryTest.java b/modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/cpi/SSHSummaryTest/SSHSummaryTest.java new file mode 100644 index 0000000000..0852023351 --- /dev/null +++ b/modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/cpi/SSHSummaryTest/SSHSummaryTest.java @@ -0,0 +1,173 @@ +package org.apache.airavata.credential.store.cpi.SSHSummaryTest; + +import junit.framework.Assert; +import org.apache.airavata.common.utils.DBUtil; +import org.apache.airavata.common.utils.DatabaseTestCases; +import org.apache.airavata.common.utils.DerbyUtil; +import org.apache.airavata.common.utils.ServerSettings; +import org.apache.airavata.credential.store.credential.impl.ssh.SSHCredential; +import org.apache.airavata.credential.store.store.impl.SSHCredentialWriter; +import org.apache.airavata.credential.store.store.impl.db.CredentialsDAO; +import org.apache.airavata.credential.store.util.TokenGenerator; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.sql.Connection; + +/** + * Created by abhandar on 10/24/16. + */ +public class SSHSummaryTest extends DatabaseTestCases { + private static final Logger logger = LoggerFactory.getLogger(SSHSummaryTest.class); + + private CredentialsDAO credentialsDAO; + + private X509Certificate[] x509Certificates; + private PrivateKey privateKey; + + @BeforeClass + public static void setUpDatabase() throws Exception { + DerbyUtil.startDerbyInServerMode(getHostAddress(), getPort(), getUserName(), getPassword()); + + waitTillServerStarts(); + + /* + * String createTable = "CREATE TABLE CREDENTIALS\n" + "(\n" + " GATEWAY_NAME VARCHAR(256) NOT NULL,\n" + + * " COMMUNITY_USER_NAME VARCHAR(256) NOT NULL,\n" + " CREDENTIAL BLOB NOT NULL,\n" + + * " PRIVATE_KEY BLOB NOT NULL,\n" + " NOT_BEFORE VARCHAR(256) NOT NULL,\n" + + * " NOT_AFTER VARCHAR(256) NOT NULL,\n" + " LIFETIME INTEGER NOT NULL,\n" + + * " REQUESTING_PORTAL_USER_NAME VARCHAR(256) NOT NULL,\n" + + * " REQUESTED_TIME TIMESTAMP DEFAULT '0000-00-00 00:00:00',\n" + + * " PRIMARY KEY (GATEWAY_NAME, COMMUNITY_USER_NAME)\n" + ")"; + */ + // Adding description field as per pull request https://github.com/apache/airavata/pull/54 + String createTable = "CREATE TABLE CREDENTIALS\n" + "(\n" + + " GATEWAY_ID VARCHAR(256) NOT NULL,\n" + + " TOKEN_ID VARCHAR(256) NOT NULL,\n" + + // Actual token used to identify the credential + " CREDENTIAL BLOB NOT NULL,\n" + " PORTAL_USER_ID VARCHAR(256) NOT NULL,\n" + + " TIME_PERSISTED TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n" + + " DESCRIPTION VARCHAR(500),\n" + + " PRIMARY KEY (GATEWAY_ID, TOKEN_ID)\n" + ")"; + + String dropTable = "drop table CREDENTIALS"; + + try { + executeSQL(dropTable); + } catch (Exception e) { + } + + executeSQL(createTable); + + } + + @AfterClass + public static void shutDownDatabase() throws Exception { + DerbyUtil.stopDerbyServer(); + } + + @Before + public void setUp() throws Exception { + + credentialsDAO = new CredentialsDAO(); + + x509Certificates = new X509Certificate[1]; + + // Cleanup tables; + Connection connection = getConnection(); + + try { + DBUtil.truncate("credentials", connection); + } finally { + connection.close(); + } + + initializeKeys(); + } + + private void initializeKeys() throws Exception { + KeyStore ks = KeyStore.getInstance("JKS"); + char[] password = "password".toCharArray(); + + String baseDirectory = System.getProperty("credential.module.directory"); + + String keyStorePath = "src" + File.separator + "test" + File.separator + "resources" + File.separator + + "keystore.jks"; + + if (baseDirectory != null) { + keyStorePath = baseDirectory + File.separator + keyStorePath; + } else { + keyStorePath = "modules" + File.separator + "credential-store" + File.separator + keyStorePath; + } + + File keyStoreFile = new File(keyStorePath); + if (!keyStoreFile.exists()) { + logger.error("Unable to read keystore file " + keyStoreFile); + throw new RuntimeException("Unable to read keystore file " + keyStoreFile); + + } + + java.io.FileInputStream fis = null; + try { + fis = new java.io.FileInputStream(keyStorePath); + ks.load(fis, password); + } finally { + if (fis != null) { + fis.close(); + } + } + + fis.close(); + + privateKey = (PrivateKey) ks.getKey("selfsigned", password); + x509Certificates[0] = (X509Certificate) ks.getCertificate("selfsigned"); + + } + + +// @Test Change the properties in ServerProperties file and give the correct path to run the test + public void testSSHSummary() throws Exception{ + try{ + String jdbcURL = ServerSettings.getCredentialStoreDBURL(); + String jdbcDriver = ServerSettings.getCredentialStoreDBDriver(); + String userName = ServerSettings.getCredentialStoreDBUser(); + String password = ServerSettings.getCredentialStoreDBPassword(); + String gatewayId = "phasta"; + String privateKeyPath = "/home/abhandar/Documents/Airavata/keys/id_rsa_airavata"; + String pubKeyPath = "/home/abhandar/Documents/Airavata/keys/id_rsa_airavata.pub"; + DBUtil dbUtil = new DBUtil(jdbcURL, userName, password, jdbcDriver); + SSHCredentialWriter writer = new SSHCredentialWriter(dbUtil); + SSHCredential sshCredential = new SSHCredential(); + sshCredential.setGateway(gatewayId); + String token = TokenGenerator.generateToken(gatewayId, null); + sshCredential.setToken(token); + sshCredential.setPortalUserName("phasta"); + sshCredential.setDescription("dummy creds for testing"); + FileInputStream privateKeyStream = new FileInputStream(privateKeyPath); + File filePri = new File(privateKeyPath); + byte[] bFilePri = new byte[(int) filePri.length()]; + privateKeyStream.read(bFilePri); + FileInputStream pubKeyStream = new FileInputStream(pubKeyPath); + File filePub = new File(pubKeyPath); + byte[] bFilePub = new byte[(int) filePub.length()]; + pubKeyStream.read(bFilePub); + privateKeyStream.close(); + pubKeyStream.close(); + sshCredential.setPrivateKey(bFilePri); + sshCredential.setPublicKey(bFilePub); + sshCredential.setPassphrase("ultrascan"); + writer.writeCredentials(sshCredential); + Assert.assertEquals(token, sshCredential.getToken()); + }catch (Exception ex){ + ex.printStackTrace(); + } + } +} diff --git a/modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAOTest.java b/modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAOTest.java index 1750adce92..0f6d493db4 100644 --- a/modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAOTest.java +++ b/modules/credential-store/credential-store-service/src/test/java/org/apache/airavata/credential/store/store/impl/db/CredentialsDAOTest.java @@ -39,7 +39,8 @@ import java.io.File; import java.net.URL; -import java.security.*; +import java.security.KeyStore; +import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.sql.Connection; import java.util.Arrays; @@ -419,4 +420,5 @@ public void testGetGatewayCredentials() throws Exception { } } + } diff --git a/thrift-interface-descriptions/data-models/resource-catalog-models/credential_summary.thrift b/thrift-interface-descriptions/data-models/resource-catalog-models/credential_summary.thrift index c7aaa896e9..c60389a901 100644 --- a/thrift-interface-descriptions/data-models/resource-catalog-models/credential_summary.thrift +++ b/thrift-interface-descriptions/data-models/resource-catalog-models/credential_summary.thrift @@ -26,7 +26,8 @@ namespace py apache.airavata.model.appcatalog.credentialsummary struct CredentialSummary { 1: required string gatewayId, 2: required string username, - 3: optional string publicKey, - 4: optional i64 persistedTime, - 5: optional string description + 3: required string token; + 4: optional string publicKey, + 5: optional i64 persistedTime, + 6: optional string description } \ No newline at end of file