You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by di...@apache.org on 2019/06/20 17:59:48 UTC
[airavata] branch master updated: Adding user email to groovy map
This is an automated email from the ASF dual-hosted git repository.
dimuthuupe pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata.git
The following commit(s) were added to refs/heads/master by this push:
new ca6a54f Adding user email to groovy map
ca6a54f is described below
commit ca6a54f5f8c503368c25d95d1405529f3de8869d
Author: Dimuthu Wannipurage <di...@gmail.com>
AuthorDate: Thu Jun 20 13:59:35 2019 -0400
Adding user email to groovy map
---
airavata-services/services-security/pom.xml | 5 +
.../service/security/AiravataSecurityManager.java | 2 +
.../service/security/KeyCloakSecurityManager.java | 105 ++++++++++++++++++++-
.../participant/airavata-server.properties.j2 | 6 ++
modules/airavata-helix/helix-spectator/pom.xml | 10 ++
.../airavata/helix/impl/task/AiravataTask.java | 14 +++
.../airavata/helix/impl/task/TaskContext.java | 41 +++++++-
.../task/submission/config/GroovyMapBuilder.java | 6 +-
.../impl/task/submission/config/GroovyMapData.java | 11 +++
9 files changed, 193 insertions(+), 7 deletions(-)
diff --git a/airavata-services/services-security/pom.xml b/airavata-services/services-security/pom.xml
index 7ac3532..d5aa334 100644
--- a/airavata-services/services-security/pom.xml
+++ b/airavata-services/services-security/pom.xml
@@ -57,6 +57,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.airavata</groupId>
+ <artifactId>airavata-sharing-registry-stubs</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4</version>
diff --git a/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/AiravataSecurityManager.java b/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/AiravataSecurityManager.java
index dcd04fb..895c4a6 100644
--- a/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/AiravataSecurityManager.java
+++ b/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/AiravataSecurityManager.java
@@ -39,4 +39,6 @@ public interface AiravataSecurityManager {
* @throws AiravataSecurityException
*/
public boolean isUserAuthorized(AuthzToken authzToken, Map<String, String> metaData) throws AiravataSecurityException;
+
+ public AuthzToken getUserManagementServiceAccountAuthzToken(String gatewayId) throws AiravataSecurityException;
}
diff --git a/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/KeyCloakSecurityManager.java b/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/KeyCloakSecurityManager.java
index 38b70c5..f7987b6 100644
--- a/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/KeyCloakSecurityManager.java
+++ b/airavata-services/services-security/src/main/java/org/apache/airavata/service/security/KeyCloakSecurityManager.java
@@ -22,18 +22,33 @@ package org.apache.airavata.service.security;
import org.apache.airavata.common.exception.ApplicationSettingsException;
import org.apache.airavata.common.utils.Constants;
import org.apache.airavata.common.utils.ServerSettings;
+import org.apache.airavata.common.utils.ThriftUtils;
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.gatewayprofile.GatewayResourceProfile;
import org.apache.airavata.model.credential.store.PasswordCredential;
import org.apache.airavata.model.security.AuthzToken;
+import org.apache.airavata.model.workspace.Gateway;
import org.apache.airavata.registry.api.client.RegistryServiceClientFactory;
import org.apache.airavata.registry.api.exception.RegistryServiceException;
import org.apache.airavata.security.AiravataSecurityException;
import org.apache.airavata.security.util.TrustStoreManager;
import org.apache.airavata.service.security.authzcache.*;
import org.apache.airavata.registry.api.RegistryService;
+import org.apache.airavata.sharing.registry.client.SharingRegistryServiceClientFactory;
+import org.apache.airavata.sharing.registry.models.SharingRegistryException;
+import org.apache.airavata.sharing.registry.service.cpi.SharingRegistryService;
+import org.apache.http.Consts;
+import org.apache.http.HttpHeaders;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
import org.apache.thrift.TException;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -41,11 +56,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
+import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -71,6 +87,9 @@ public class KeyCloakSecurityManager implements AiravataSecurityManager {
// configured for a gateway's compute resource preference
"/airavata/getGatewayResourceProfile";
+ private RegistryService.Client registryServiceClient = null;
+ private SharingRegistryService.Client sharingRegistryServiceClient = null;
+
public KeyCloakSecurityManager() throws AiravataSecurityException {
rolePermissionConfig.put("admin", "/airavata/.*");
rolePermissionConfig.put("gateway-provider", "/airavata/.*");
@@ -200,6 +219,25 @@ public class KeyCloakSecurityManager implements AiravataSecurityManager {
}
}
+ @Override
+ public AuthzToken getUserManagementServiceAccountAuthzToken(String gatewayId) throws AiravataSecurityException {
+ try {
+ initServiceClients();
+ Gateway gateway = registryServiceClient.getGateway(gatewayId);
+ String tokenURL = getTokenEndpoint(gatewayId);
+ JSONObject clientCredentials = getClientCredentials(tokenURL, gateway.getOauthClientId(), gateway.getOauthClientSecret());
+ String accessToken = clientCredentials.getString("access_token");
+ AuthzToken authzToken = new AuthzToken(accessToken);
+ authzToken.putToClaimsMap(Constants.GATEWAY_ID, gatewayId);
+ authzToken.putToClaimsMap(Constants.USER_NAME, gateway.getOauthClientId());
+ return authzToken;
+ } catch (Exception e) {
+ throw new AiravataSecurityException("Failed to fetch authorization token for user management service for gateway " + gatewayId, e);
+ } finally {
+ closeServiceClients();
+ }
+ }
+
private String[] getUserRolesFromOAuthToken(String username, String token, String gatewayId) throws Exception {
GatewayResourceProfile gwrp = getRegistryServiceClient().getGatewayResourceProfile(gatewayId);
String identityServerRealm = gwrp.getIdentityServerTenant();
@@ -306,4 +344,67 @@ public class KeyCloakSecurityManager implements AiravataSecurityManager {
throw new TException("Unable to create credential store client...", e);
}
}
+
+ private JSONObject getClientCredentials(String tokenURL, String clientId, String clientSecret) throws ApplicationSettingsException, AiravataSecurityException {
+
+ CloseableHttpClient httpClient = HttpClients.createSystem();
+
+ HttpPost httpPost = new HttpPost(tokenURL);
+ String encoded = Base64.getEncoder().encodeToString((clientId+":"+clientSecret).getBytes(StandardCharsets.UTF_8));
+ httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoded);
+ List<NameValuePair> formParams = new ArrayList<>();
+ formParams.add(new BasicNameValuePair("grant_type", "client_credentials"));
+ UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
+ httpPost.setEntity(entity);
+ try {
+ CloseableHttpResponse response = httpClient.execute(httpPost);
+ try {
+ String responseBody = EntityUtils.toString(response.getEntity());
+ JSONObject tokenInfo = new JSONObject(responseBody);
+ return tokenInfo;
+ } finally {
+ response.close();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+
+ private String getTokenEndpoint(String gatewayId) throws Exception {
+ String openIdConnectUrl = getOpenIDConfigurationUrl(gatewayId);
+ JSONObject openIdConnectConfig = new JSONObject(getFromUrl(openIdConnectUrl, null));
+ return openIdConnectConfig.getString("token_endpoint");
+ }
+
+ private void initServiceClients() throws TException, ApplicationSettingsException {
+ registryServiceClient = getRegistryServiceClient();
+ sharingRegistryServiceClient = getSharingRegistryServiceClient();
+ }
+
+ private void closeServiceClients() {
+ if (registryServiceClient != null) {
+ ThriftUtils.close(registryServiceClient);
+ }
+ if (sharingRegistryServiceClient != null) {
+ ThriftUtils.close(sharingRegistryServiceClient);
+ }
+ }
+
+
+ private SharingRegistryService.Client getSharingRegistryServiceClient() throws TException, ApplicationSettingsException {
+ final int serverPort = Integer.parseInt(ServerSettings.getSharingRegistryPort());
+ final String serverHost = ServerSettings.getSharingRegistryHost();
+ try {
+ return SharingRegistryServiceClientFactory.createSharingRegistryClient(serverHost, serverPort);
+ } catch (SharingRegistryException e) {
+ throw new TException("Unable to create sharing registry client...", e);
+ }
+ }
}
\ No newline at end of file
diff --git a/dev-tools/ansible/roles/helix_setup/templates/participant/airavata-server.properties.j2 b/dev-tools/ansible/roles/helix_setup/templates/participant/airavata-server.properties.j2
index 5aee4df..517c1ec 100644
--- a/dev-tools/ansible/roles/helix_setup/templates/participant/airavata-server.properties.j2
+++ b/dev-tools/ansible/roles/helix_setup/templates/participant/airavata-server.properties.j2
@@ -29,6 +29,12 @@ credential.store.server.host={{ cred_store_server_host }}
credential.store.server.port={{ cred_store_port }}
###########################################################################
+# Profile Server Configuration
+###########################################################################
+profile.service.server.host={{ profile_service_host }}
+profile.service.server.port={{ profile_service_port }}
+
+###########################################################################
# Monitoring module Configuration
###########################################################################
email.based.monitor.address={{ monitor_email_address }}
diff --git a/modules/airavata-helix/helix-spectator/pom.xml b/modules/airavata-helix/helix-spectator/pom.xml
index 2d2c26d..7101a7a 100644
--- a/modules/airavata-helix/helix-spectator/pom.xml
+++ b/modules/airavata-helix/helix-spectator/pom.xml
@@ -75,6 +75,16 @@
</dependency>
<dependency>
<groupId>org.apache.airavata</groupId>
+ <artifactId>profile-service-stubs</artifactId>
+ <version>0.18-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.airavata</groupId>
+ <artifactId>services-security</artifactId>
+ <version>0.18-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.airavata</groupId>
<artifactId>airavata-messaging-core</artifactId>
<version>0.18-SNAPSHOT</version>
</dependency>
diff --git a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/AiravataTask.java b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/AiravataTask.java
index 5041d63..230764a 100644
--- a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/AiravataTask.java
+++ b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/AiravataTask.java
@@ -43,6 +43,9 @@ import org.apache.airavata.model.status.*;
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.airavata.service.profile.client.ProfileServiceClientFactory;
+import org.apache.airavata.service.profile.user.cpi.UserProfileService;
+import org.apache.airavata.service.profile.user.cpi.exception.UserProfileServiceException;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.helix.HelixManager;
import org.apache.helix.task.TaskResult;
@@ -394,6 +397,7 @@ public abstract class AiravataTask extends AbstractTask {
TaskContext.TaskContextBuilder taskContextBuilder = new TaskContext.TaskContextBuilder(getProcessId(), getGatewayId(), getTaskId())
.setRegistryClient(getRegistryServiceClient())
+ .setProfileClient(getUserProfileClient())
.setProcessModel(getProcessModel())
.setGatewayResourceProfile(getRegistryServiceClient().getGatewayResourceProfile(gatewayId))
.setGatewayComputeResourcePreference(
@@ -495,4 +499,14 @@ public abstract class AiravataTask extends AbstractTask {
throw new RuntimeException("Unable to create registry client...", e);
}
}
+
+ public static UserProfileService.Client getUserProfileClient() {
+ try {
+ final int serverPort = Integer.parseInt(ServerSettings.getProfileServiceServerPort());
+ final String serverHost = ServerSettings.getProfileServiceServerHost();
+ return ProfileServiceClientFactory.createUserProfileServiceClient(serverHost, serverPort);
+ } catch (UserProfileServiceException | ApplicationSettingsException e) {
+ throw new RuntimeException("Unable to create profile service client...", e);
+ }
+ }
}
diff --git a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java
index 6c4a1bb..b686b71 100644
--- a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java
+++ b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java
@@ -38,16 +38,17 @@ import org.apache.airavata.model.data.movement.DataMovementProtocol;
import org.apache.airavata.model.job.JobModel;
import org.apache.airavata.model.process.ProcessModel;
import org.apache.airavata.model.scheduling.ComputationalResourceSchedulingModel;
+import org.apache.airavata.model.security.AuthzToken;
import org.apache.airavata.model.status.ProcessState;
import org.apache.airavata.model.status.ProcessStatus;
import org.apache.airavata.model.status.TaskState;
import org.apache.airavata.model.status.TaskStatus;
import org.apache.airavata.model.task.TaskModel;
+import org.apache.airavata.model.user.UserProfile;
import org.apache.airavata.registry.api.RegistryService;
-import org.apache.airavata.registry.cpi.AppCatalog;
-import org.apache.airavata.registry.cpi.AppCatalogException;
-import org.apache.airavata.registry.cpi.ExperimentCatalog;
-import org.apache.airavata.registry.cpi.ExperimentCatalogModelType;
+import org.apache.airavata.service.profile.user.cpi.UserProfileService;
+import org.apache.airavata.service.security.AiravataSecurityManager;
+import org.apache.airavata.service.security.SecurityManagerFactory;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -102,6 +103,8 @@ public class TaskContext {
private String taskId;
private Object subTaskModel = null;
private RegistryService.Client registryClient;
+ private UserProfileService.Client profileClient;
+ private UserProfile userProfile;
/**
@@ -564,6 +567,29 @@ public class TaskContext {
return registryClient;
}
+ public UserProfileService.Client getProfileClient() {
+ return profileClient;
+ }
+
+ public void setProfileClient(UserProfileService.Client profileClient) {
+ this.profileClient = profileClient;
+ }
+
+ public UserProfile getUserProfile() throws TaskOnFailException {
+
+ if (this.userProfile == null) {
+ try {
+ AiravataSecurityManager securityManager = SecurityManagerFactory.getSecurityManager();
+ AuthzToken authzToken = securityManager.getUserManagementServiceAccountAuthzToken(getGatewayId());
+ this.userProfile = getProfileClient().getUserProfileById(authzToken, getProcessModel().getUserName(), getGatewayId());
+ } catch (Exception e) {
+ logger.error("Failed to fetch the user profile for user id " + processModel.getUserName(), e);
+ throw new TaskOnFailException("Failed to fetch the user profile for user id " + processModel.getUserName(), true, e);
+ }
+ }
+ return this.userProfile;
+ }
+
private boolean isValid(String str) {
return str != null && !str.trim().isEmpty();
}
@@ -686,6 +712,7 @@ public class TaskContext {
private final String gatewayId;
private final String taskId;
private RegistryService.Client registryClient;
+ private UserProfileService.Client profileClient;
private GatewayResourceProfile gatewayResourceProfile;
private ComputeResourcePreference gatewayComputeResourcePreference;
private StoragePreference gatewayStorageResourcePreference;
@@ -726,6 +753,11 @@ public class TaskContext {
return this;
}
+ public TaskContextBuilder setProfileClient(UserProfileService.Client profileClient) {
+ this.profileClient = profileClient;
+ return this;
+ }
+
public TaskContext build() throws Exception {
if (notValid(gatewayResourceProfile)) {
throwError("Invalid GatewayResourceProfile");
@@ -746,6 +778,7 @@ public class TaskContext {
TaskContext ctx = new TaskContext(processId, gatewayId, taskId);
ctx.setRegistryClient(registryClient);
ctx.setProcessModel(processModel);
+ ctx.setProfileClient(profileClient);
ctx.setGatewayResourceProfile(gatewayResourceProfile);
ctx.setGatewayComputeResourcePreference(gatewayComputeResourcePreference);
ctx.setGatewayStorageResourcePreference(gatewayStorageResourcePreference);
diff --git a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapBuilder.java b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapBuilder.java
index 2d1a7bc..d849ba4 100644
--- a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapBuilder.java
+++ b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapBuilder.java
@@ -36,7 +36,6 @@ import org.apache.airavata.model.parallelism.ApplicationParallelismType;
import org.apache.airavata.model.process.ProcessModel;
import org.apache.airavata.model.scheduling.ComputationalResourceSchedulingModel;
import org.apache.airavata.model.task.JobSubmissionTaskModel;
-import org.apache.airavata.registry.cpi.AppCatalogException;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -81,6 +80,11 @@ public class GroovyMapBuilder {
mapData.setTaskId(taskContext.getTaskId());
mapData.setExperimentDataDir(taskContext.getProcessModel().getExperimentDataDir());
+ List<String> emails = taskContext.getUserProfile().getEmails();
+ if (emails != null && emails.size() > 0) {
+ mapData.setGatewayUserEmail(emails.get(0));
+ }
+
List<String> inputValues = getProcessInputValues(taskContext.getProcessModel().getProcessInputs(), true);
inputValues.addAll(getProcessOutputValues(taskContext.getProcessModel().getProcessOutputs(), true));
mapData.setInputs(inputValues);
diff --git a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapData.java b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapData.java
index 7f74361..663687d 100644
--- a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapData.java
+++ b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/submission/config/GroovyMapData.java
@@ -60,6 +60,9 @@ public class GroovyMapData {
@ScriptTag(name = "gatewayUserName")
private String gatewayUserName;
+ @ScriptTag(name = "gatewayUserEmail")
+ private String gatewayUserEmail;
+
@ScriptTag(name = "applicationName")
private String applicationName;
@@ -231,6 +234,14 @@ public class GroovyMapData {
return this;
}
+ public String getGatewayUserEmail() {
+ return gatewayUserEmail;
+ }
+
+ public void setGatewayUserEmail(String gatewayUserEmail) {
+ this.gatewayUserEmail = gatewayUserEmail;
+ }
+
public String getApplicationName() {
return applicationName;
}