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/06/01 20:15:14 UTC
[3/3] airavata git commit: AIRAVATA-2402 Migrate user roles to
Keycloak
AIRAVATA-2402 Migrate user roles to Keycloak
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/bd526ade
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/bd526ade
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/bd526ade
Branch: refs/heads/develop
Commit: bd526ade0ac87f9b3673cebd1e029761ee018a57
Parents: 020ecae
Author: Marcus Christie <ma...@apache.org>
Authored: Thu Jun 1 16:13:10 2017 -0400
Committer: Marcus Christie <ma...@apache.org>
Committed: Thu Jun 1 16:13:10 2017 -0400
----------------------------------------------------------------------
.../airavata/KeycloakIdentityServerClient.java | 76 ++++++++++++++++++--
.../org/apache/airavata/MigrationManager.java | 46 +++++++++---
.../org/apache/airavata/UserProfileDAO.java | 9 +++
3 files changed, 119 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/airavata/blob/bd526ade/modules/user-profile-migration/src/main/java/org/apache/airavata/KeycloakIdentityServerClient.java
----------------------------------------------------------------------
diff --git a/modules/user-profile-migration/src/main/java/org/apache/airavata/KeycloakIdentityServerClient.java b/modules/user-profile-migration/src/main/java/org/apache/airavata/KeycloakIdentityServerClient.java
index cd55487..ed1bb8a 100644
--- a/modules/user-profile-migration/src/main/java/org/apache/airavata/KeycloakIdentityServerClient.java
+++ b/modules/user-profile-migration/src/main/java/org/apache/airavata/KeycloakIdentityServerClient.java
@@ -21,28 +21,79 @@ package org.apache.airavata;
*
*/
+import org.apache.airavata.common.utils.ServerSettings;
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
+import javax.management.relation.Role;
import javax.ws.rs.core.Response;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
public class KeycloakIdentityServerClient {
private Keycloak client;
- public KeycloakIdentityServerClient(String adminUrl, String realm, String adminUserName, String adminUserPassword) {
- this.client = Keycloak.getInstance(
+ public KeycloakIdentityServerClient(String adminUrl, String realm, String adminUserName, String adminUserPassword, String trustStorePath, String trustStorePassword) {
+ KeyStore trustKeyStore = loadKeyStore(trustStorePath, trustStorePassword);
+ this.client = getClient(
adminUrl,
realm, // the realm to log in to
adminUserName, adminUserPassword, // the user
- "admin-cli"); // admin-cli is the client ID used for keycloak admin operations.
+ "admin-cli", // admin-cli is the client ID used for keycloak admin operations.
+ trustKeyStore);
}
+ private Keycloak getClient(String adminUrl, String realm, String adminUserName, String adminUserPassword, String clientId, KeyStore trustKeyStore) {
- boolean migrateUserStore(List<UserProfileDAO> userProfiles, String targetRealm, String tempPassword){
+ ResteasyClient resteasyClient = new ResteasyClientBuilder()
+ .connectionPoolSize(10)
+ .trustStore(trustKeyStore)
+ .build();
+ return KeycloakBuilder.builder()
+ .serverUrl(adminUrl)
+ .realm(realm)
+ .username(adminUserName)
+ .password(adminUserPassword)
+ .clientId(clientId)
+ .resteasyClient(resteasyClient)
+ .build();
+ }
+
+ private KeyStore loadKeyStore(String trustStorePath, String trustStorePassword) {
+
+ FileInputStream fis = null;
+ try {
+ fis = new java.io.FileInputStream(trustStorePath);
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ ks.load(fis, trustStorePassword.toCharArray());
+ return ks;
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to load trust store KeyStore instance", e);
+ } finally {
+ if (fis != null) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to close trust store FileInputStream", e);
+ }
+ }
+ }
+ }
+
+ boolean migrateUserStore(List<UserProfileDAO> userProfiles, String targetRealm, String tempPassword, Map<String,String> roleConversionMap){
+
+ Map<String, RoleRepresentation> allRealmRoles = getRealmRoleNameMap(targetRealm);
for(UserProfileDAO userProfile : userProfiles){
UserRepresentation user = new UserRepresentation();
@@ -63,6 +114,17 @@ public class KeycloakIdentityServerClient {
user.getEmail(),
0,1);
UserResource retirievedUser = this.client.realm(targetRealm).users().get(retrieveCreatedUserList.get(0).getId());
+
+ // Add user to realm roles
+ List<RoleRepresentation> userRealmRoles = userProfile.getRoles().stream()
+ .filter(r -> roleConversionMap.containsKey(r))
+ // Convert from IS role name to Keycloak role name
+ .map(r -> roleConversionMap.get(r))
+ // Convert from Keycloak role name to RoleRepresentation
+ .map(r -> allRealmRoles.get(r))
+ .collect(Collectors.toList());
+ retirievedUser.roles().realmLevel().add(userRealmRoles);
+
CredentialRepresentation credential = new CredentialRepresentation();
credential.setType(CredentialRepresentation.PASSWORD);
credential.setValue(tempPassword);
@@ -74,4 +136,10 @@ public class KeycloakIdentityServerClient {
return true;
}
+ private Map<String,RoleRepresentation> getRealmRoleNameMap(String targetRealm) {
+ return this.client.realm(targetRealm).roles().list()
+ .stream()
+ .collect(Collectors.toMap(r -> r.getName(), r -> r));
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/bd526ade/modules/user-profile-migration/src/main/java/org/apache/airavata/MigrationManager.java
----------------------------------------------------------------------
diff --git a/modules/user-profile-migration/src/main/java/org/apache/airavata/MigrationManager.java b/modules/user-profile-migration/src/main/java/org/apache/airavata/MigrationManager.java
index 85353ce..2cfbe59 100644
--- a/modules/user-profile-migration/src/main/java/org/apache/airavata/MigrationManager.java
+++ b/modules/user-profile-migration/src/main/java/org/apache/airavata/MigrationManager.java
@@ -21,6 +21,7 @@ package org.apache.airavata;
import org.apache.airavata.common.exception.ApplicationSettingsException;
import org.apache.airavata.model.security.AuthzToken;
+import org.apache.airavata.model.user.Status;
import org.apache.airavata.model.user.UserProfile;
import org.apache.airavata.service.profile.user.cpi.UserProfileService;
import org.apache.thrift.TException;
@@ -29,8 +30,8 @@ import org.wso2.carbon.um.ws.api.stub.RemoteUserStoreManagerServiceStub;
import org.wso2.carbon.um.ws.api.stub.RemoteUserStoreManagerServiceUserStoreExceptionException;
import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
public class MigrationManager {
@@ -38,10 +39,21 @@ public class MigrationManager {
private static AuthzToken authzToken = new AuthzToken("empy_token");
private String profileServiceServerHost = "localhost";
private int profileServiceServerPort = 8962;
+ private Map<String,String> roleConversionMap = createDefaultRoleConversionMap();
+
+ private Map<String,String> createDefaultRoleConversionMap() {
+ Map<String,String> roleConversionMap = new HashMap<>();
+ roleConversionMap.put("admin", "admin");
+ roleConversionMap.put("admin-read-only", "admin-read-only");
+ roleConversionMap.put("gateway-user", "gateway-user");
+ roleConversionMap.put("user-pending", "user-pending");
+ roleConversionMap.put("gateway-provider", "gateway-provider");
+ return roleConversionMap;
+ }
/*Add the credentials for all the tenants from which the profile should be migrated to Airavata DB*/
public void setISLoginCredentials(){
- adminCredentials.add(new Wso2ISLoginCredentialsDAO("prod.seagrid","username","password"));
+ adminCredentials.add(new Wso2ISLoginCredentialsDAO("gateway-id","username","password"));
// new credential records here...
}
@@ -55,7 +67,7 @@ public class MigrationManager {
System.out.println("Fetching User Profiles for " + creds.getGateway() + " tenant ...");
try {
userList = isClient.getUserList("http://wso2.org/claims/givenname", "*", "default");
- System.out.println("FirstName\tLastName\tEmail\t\t\tuserName\tCountry\tOrganization\tphone");
+ System.out.println("FirstName\tLastName\tEmail\t\t\tuserName\tCountry\tOrganization\tphone\tRoles");
String[] claims = {"http://wso2.org/claims/givenname",
"http://wso2.org/claims/lastname",
"http://wso2.org/claims/emailaddress",
@@ -63,7 +75,8 @@ public class MigrationManager {
"http://wso2.org/claims/organization",
"http://wso2.org/claims/mobile",
"http://wso2.org/claims/telephone",
- "http://wso2.org/claims/streetaddress"};
+ "http://wso2.org/claims/streetaddress",
+ "http://wso2.org/claims/role"};
for (String user : userList) {
UserProfileDAO userProfile = new UserProfileDAO();
ClaimValue[] retrievedClaimValues = isClient.getUserClaimValuesForClaims(user, claims, null);
@@ -83,12 +96,14 @@ public class MigrationManager {
phones.add(claim.getValue());
} else if(claim.getClaimURI().equals(claims[7])){
userProfile.setAddress(claim.getValue());
+ } else if(claim.getClaimURI().equals(claims[8])){
+ userProfile.setRoles(convertCommaSeparatedRolesToList(claim.getValue()));
}
}
userProfile.setUserName(user);
userProfile.setGatewayID(creds.getGateway());
userProfile.setPhones(phones);
- System.out.println(userProfile.getFirstName()+"\t"+userProfile.getLastName()+"\t"+userProfile.getUserName()+"\t"+userProfile.getEmail()+"\t"+userProfile.getCountry()+"\t"+userProfile.getOrganization() + userProfile.getAddress());
+ System.out.println(userProfile.getFirstName()+"\t"+userProfile.getLastName()+"\t"+userProfile.getUserName()+"\t"+userProfile.getEmail()+"\t"+userProfile.getCountry()+"\t"+userProfile.getOrganization() + "\t" + userProfile.getAddress() + "\t" + userProfile.getRoles());
userProfileList.add(userProfile);
}
} catch (RemoteException e) {
@@ -105,6 +120,14 @@ public class MigrationManager {
return userProfileList;
}
+ private List<String> convertCommaSeparatedRolesToList(String roles) {
+
+ return Arrays.stream(roles.split(","))
+ .filter(s -> !"Internal/everyone".equals(s))
+ .filter(s -> !"Internal/identity".equals(s))
+ .collect(Collectors.toList());
+ }
+
/* Method used to migrate User profiles to Airavata DB by making a call to User profile thrift Service */
private boolean migrateUserProfilesToAiravata(List<UserProfileDAO> ISProfileList) throws TException, ApplicationSettingsException {
System.out.println("Initiating migration to Airavata internal DB ...");
@@ -113,6 +136,7 @@ public class MigrationManager {
UserProfile airavataUserProfile = new UserProfile();
// Here are the data associations...
for(UserProfileDAO ISProfile : ISProfileList){
+ airavataUserProfile.setAiravataInternalUserId(ISProfile.getUserName() + "@" + ISProfile.getGatewayID());
airavataUserProfile.setFirstName(ISProfile.getFirstName());
airavataUserProfile.setLastName(ISProfile.getLastName());
airavataUserProfile.setUserId(ISProfile.getUserName());
@@ -123,6 +147,10 @@ public class MigrationManager {
airavataUserProfile.setHomeOrganization(ISProfile.getOrganization());
airavataUserProfile.setPhones(ISProfile.getPhones());
airavataUserProfile.setCountry(ISProfile.getCountry());
+ airavataUserProfile.setCreationTime(new Date().getTime());
+ airavataUserProfile.setLastAccessTime(new Date().getTime());
+ airavataUserProfile.setValidUntil(-1);
+ airavataUserProfile.setState(Status.ACTIVE);
//TODO: fix authtzToken, for now we are using empty token
client.addUserProfile(authzToken, airavataUserProfile);
}
@@ -133,8 +161,10 @@ public class MigrationManager {
KeycloakIdentityServerClient client = new KeycloakIdentityServerClient("https://iam.scigap.org/auth",
"master",
"SuperRealmUsername",
- "MasterRealmPassword");
- client.migrateUserStore(Wso2ISProfileList,"keycloakTargetRealm","tempPassword");
+ "MasterRealmPassword",
+ "trustStorePath",
+ "trustStorePassword");
+ client.migrateUserStore(Wso2ISProfileList,"keycloakTargetRealm","tempPassword", roleConversionMap);
}
public static void main(String[] args) {
http://git-wip-us.apache.org/repos/asf/airavata/blob/bd526ade/modules/user-profile-migration/src/main/java/org/apache/airavata/UserProfileDAO.java
----------------------------------------------------------------------
diff --git a/modules/user-profile-migration/src/main/java/org/apache/airavata/UserProfileDAO.java b/modules/user-profile-migration/src/main/java/org/apache/airavata/UserProfileDAO.java
index cb000cf..12571b2 100644
--- a/modules/user-profile-migration/src/main/java/org/apache/airavata/UserProfileDAO.java
+++ b/modules/user-profile-migration/src/main/java/org/apache/airavata/UserProfileDAO.java
@@ -32,6 +32,7 @@ public class UserProfileDAO {
private List<String> Phones;
private String gatewayID;
private String address;
+ private List<String> roles;
public String getAddress() {
return address;
@@ -115,4 +116,12 @@ public class UserProfileDAO {
public void setEmail(String email) {
this.email = email;
}
+
+ public List<String> getRoles() {
+ return roles;
+ }
+
+ public void setRoles(List<String> roles) {
+ this.roles = roles;
+ }
}