You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by is...@apache.org on 2020/04/08 20:36:22 UTC

[airavata-custos] branch develop updated: Add admin user privilage grant methods

This is an automated email from the ASF dual-hosted git repository.

isjarana pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git


The following commit(s) were added to refs/heads/develop by this push:
     new a1c4db6  Add admin user privilage grant methods
     new cb3cbbc  Merge pull request #38 from isururanawaka/microservices_based_impl
a1c4db6 is described below

commit a1c4db6cf88cf247d01c11049e3bc4722939bf12
Author: Isuru Ranawaka <ir...@gmail.com>
AuthorDate: Wed Apr 8 16:35:11 2020 -0400

    Add admin user privilage grant methods
---
 .../iam/admin/client/IamAdminServiceClient.java    |   8 ++
 .../apache/custos/iam/service/IamAdminService.java |  88 ++++++++++++++++-
 .../org/apache/custos/iam/utils/IAMOperations.java |   2 +
 .../custos/iam/validator/InputValidator.java       |   5 +-
 .../src/main/proto/IamAdminService.proto           |   2 +
 .../services/clients/keycloak/KeycloakClient.java  |  65 ++++++++++++
 .../src/main/resources/user-management-service.pb  | Bin 115591 -> 117657 bytes
 .../interceptors/UserAuthInterceptorImpl.java      |   3 +-
 .../management/service/UserManagementService.java  | 110 ++++++++++++++++++++-
 .../src/main/proto/UserManagementService.proto     |  13 +++
 10 files changed, 287 insertions(+), 9 deletions(-)

diff --git a/custos-core-services-client-stubs/iam-admin-core-service-client-stub/src/main/java/org/apache/custos/iam/admin/client/IamAdminServiceClient.java b/custos-core-services-client-stubs/iam-admin-core-service-client-stub/src/main/java/org/apache/custos/iam/admin/client/IamAdminServiceClient.java
index 3a590bb..bbf37d8 100644
--- a/custos-core-services-client-stubs/iam-admin-core-service-client-stub/src/main/java/org/apache/custos/iam/admin/client/IamAdminServiceClient.java
+++ b/custos-core-services-client-stubs/iam-admin-core-service-client-stub/src/main/java/org/apache/custos/iam/admin/client/IamAdminServiceClient.java
@@ -313,6 +313,14 @@ public class IamAdminServiceClient {
         return iamAdminServiceBlockingStub.enableAgent(request);
     }
 
+    public OperationStatus grantAdminPrivilege(UserSearchRequest request) {
+        return iamAdminServiceBlockingStub.grantAdminPrivilege(request);
+    }
+
+    public OperationStatus removeAdminPrivilege(UserSearchRequest request) {
+        return iamAdminServiceBlockingStub.removeAdminPrivilege(request);
+    }
+
     public SetUpTenantResponse updateTenant(SetUpTenantRequest request) {
         return iamAdminServiceBlockingStub.updateTenant(request);
     }
diff --git a/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/service/IamAdminService.java b/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/service/IamAdminService.java
index 06313d9..1eb4275 100644
--- a/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/service/IamAdminService.java
+++ b/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/service/IamAdminService.java
@@ -255,7 +255,7 @@ public class IamAdminService extends IamAdminServiceImplBase {
             LOGGER.debug("Request received to enableUser for " + request.getTenantId());
 
             boolean status = keycloakClient.isValidEndUser(String.valueOf(request.getTenantId()),
-                    request.getUser().getId(), request.getAccessToken());
+                    request.getUser().getUsername(), request.getAccessToken());
 
             if (!status) {
                 statusUpdater.updateStatus(IAMOperations.ENABLE_USER.name(),
@@ -317,7 +317,7 @@ public class IamAdminService extends IamAdminServiceImplBase {
             LOGGER.debug("Request received to disable for " + request.getTenantId());
 
             boolean status = keycloakClient.isValidEndUser(String.valueOf(request.getTenantId()),
-                    request.getUser().getId(), request.getAccessToken());
+                    request.getUser().getUsername(), request.getAccessToken());
 
 
             if (!status) {
@@ -1957,6 +1957,90 @@ public class IamAdminService extends IamAdminServiceImplBase {
         }
     }
 
+
+    @Override
+    public void grantAdminPrivilege(UserSearchRequest request, StreamObserver<org.apache.custos.iam.service.OperationStatus> responseObserver) {
+        try {
+            LOGGER.debug("Request received to grantAdminPrivilege " + request.getTenantId());
+
+            boolean validationStatus = keycloakClient.isValidEndUser(String.valueOf(request.getTenantId()),
+                    request.getUser().getUsername(), request.getAccessToken());
+
+            if (validationStatus) {
+
+                boolean status = keycloakClient.grantAdminPrivilege(String.valueOf(request.getTenantId()), request.getUser().getUsername());
+
+                statusUpdater.updateStatus(IAMOperations.GRANT_ADMIN_PRIVILEGE.name(),
+                        OperationStatus.FAILED,
+                        request.getTenantId(), request.getPerformedBy());
+
+                org.apache.custos.iam.service.OperationStatus operationStatus =
+                        org.apache.custos.iam.service.OperationStatus.newBuilder().setStatus(status).build();
+
+                responseObserver.onNext(operationStatus);
+                responseObserver.onCompleted();
+            } else {
+                String msg = " Not a valid user";
+                LOGGER.error(msg);
+                responseObserver.onError(io.grpc.Status.NOT_FOUND.withDescription(msg).asRuntimeException());
+            }
+
+        } catch (Exception ex) {
+            String msg = " Grant admin privilege " + request.getTenantId() + " " + ex.getMessage();
+            LOGGER.error(msg, ex);
+            statusUpdater.updateStatus(IAMOperations.GRANT_ADMIN_PRIVILEGE.name(),
+                    OperationStatus.SUCCESS,
+                    request.getTenantId(), request.getPerformedBy());
+            if (ex.getMessage().contains("HTTP 401 Unauthorized")) {
+                responseObserver.onError(io.grpc.Status.UNAUTHENTICATED.withDescription(msg).asRuntimeException());
+            } else {
+                responseObserver.onError(io.grpc.Status.INTERNAL.withDescription(msg).asRuntimeException());
+            }
+        }
+    }
+
+
+    @Override
+    public void removeAdminPrivilege(UserSearchRequest request, StreamObserver<org.apache.custos.iam.service.OperationStatus> responseObserver) {
+        try {
+            LOGGER.debug("Request received to removeAdminPrivilege " + request.getTenantId());
+
+            boolean validationStatus = keycloakClient.isValidEndUser(String.valueOf(request.getTenantId()),
+                    request.getUser().getUsername(), request.getAccessToken());
+
+            if (validationStatus) {
+
+                boolean status = keycloakClient.removeAdminPrivilege(String.valueOf(request.getTenantId()), request.getUser().getUsername());
+
+                statusUpdater.updateStatus(IAMOperations.REMOVE_ADMIN_PRIVILEGE.name(),
+                        OperationStatus.FAILED,
+                        request.getTenantId(), request.getPerformedBy());
+
+                org.apache.custos.iam.service.OperationStatus operationStatus =
+                        org.apache.custos.iam.service.OperationStatus.newBuilder().setStatus(status).build();
+
+                responseObserver.onNext(operationStatus);
+                responseObserver.onCompleted();
+            } else {
+                String msg = " Not a valid user";
+                LOGGER.error(msg);
+                responseObserver.onError(io.grpc.Status.NOT_FOUND.withDescription(msg).asRuntimeException());
+            }
+
+        } catch (Exception ex) {
+            String msg = " Remove admin privilege " + request.getTenantId() + " " + ex.getMessage();
+            LOGGER.error(msg, ex);
+            statusUpdater.updateStatus(IAMOperations.REMOVE_ADMIN_PRIVILEGE.name(),
+                    OperationStatus.SUCCESS,
+                    request.getTenantId(), request.getPerformedBy());
+            if (ex.getMessage().contains("HTTP 401 Unauthorized")) {
+                responseObserver.onError(io.grpc.Status.UNAUTHENTICATED.withDescription(msg).asRuntimeException());
+            } else {
+                responseObserver.onError(io.grpc.Status.INTERNAL.withDescription(msg).asRuntimeException());
+            }
+        }
+    }
+
     private OperationMetadata convertFromEntity(StatusEntity entity) {
         return OperationMetadata.newBuilder()
                 .setEvent(entity.getEvent())
diff --git a/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/utils/IAMOperations.java b/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/utils/IAMOperations.java
index 29903c7..20390d2 100644
--- a/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/utils/IAMOperations.java
+++ b/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/utils/IAMOperations.java
@@ -56,5 +56,7 @@ public enum IAMOperations {
     DELETE_ROLE_FROM_AGENT,
     ADD_AGENT_ATTRIBUTES,
     DELETE_AGENT_ATTRIBUTES,
+    GRANT_ADMIN_PRIVILEGE,
+    REMOVE_ADMIN_PRIVILEGE
 
 }
diff --git a/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/validator/InputValidator.java b/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/validator/InputValidator.java
index 707f605..2058673 100644
--- a/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/validator/InputValidator.java
+++ b/custos-core-services/iam-admin-core-service/src/main/java/org/apache/custos/iam/validator/InputValidator.java
@@ -56,6 +56,7 @@ public class InputValidator implements Validator {
             case "getUser":
             case "deleteUser":
             case "isUsernameAvailable":
+            case "grantAdminPrivilege":
                 validateUserAccess(obj);
                 break;
             case "resetPassword":
@@ -117,7 +118,7 @@ public class InputValidator implements Validator {
             case "deleteAgent":
             case "disableAgent":
             case "enableAgent":
-                validateUserSearchRequest(obj);
+                validateUserSearchRequestForAgent(obj);
                 break;
             case "registerAndEnableAgent":
                 validateRegisterAndEnableAgent(obj);
@@ -708,7 +709,7 @@ public class InputValidator implements Validator {
     }
 
 
-    private boolean   validateUserSearchRequest(Object obj) {
+    private boolean validateUserSearchRequestForAgent(Object obj) {
         if (obj instanceof UserSearchRequest) {
             UserSearchRequest request = (UserSearchRequest) obj;
             if (request.getTenantId() == 0) {
diff --git a/custos-core-services/iam-admin-core-service/src/main/proto/IamAdminService.proto b/custos-core-services/iam-admin-core-service/src/main/proto/IamAdminService.proto
index 4257cf5..d0474f3 100644
--- a/custos-core-services/iam-admin-core-service/src/main/proto/IamAdminService.proto
+++ b/custos-core-services/iam-admin-core-service/src/main/proto/IamAdminService.proto
@@ -394,6 +394,8 @@ service IamAdminService {
     rpc getUser (UserSearchRequest) returns (UserRepresentation);
     rpc findUsers (FindUsersRequest) returns (FindUsersResponse);
     rpc resetPassword (ResetUserPassword) returns (OperationStatus);
+    rpc grantAdminPrivilege (UserSearchRequest) returns (OperationStatus);
+    rpc removeAdminPrivilege (UserSearchRequest) returns (OperationStatus);
 
     rpc registerAndEnableUsers (RegisterUsersRequest) returns (RegisterUsersResponse);
     rpc addUserAttributes (AddUserAttributesRequest) returns (OperationStatus);
diff --git a/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakClient.java b/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakClient.java
index abdb172..8dfb3e0 100644
--- a/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakClient.java
+++ b/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakClient.java
@@ -246,6 +246,71 @@ public class KeycloakClient {
     }
 
 
+    public boolean grantAdminPrivilege(String realmId, String username) {
+        Keycloak client = null;
+        try {
+            client = getClient(iamServerURL, superAdminRealmID, superAdminUserName, superAdminPassword);
+            UserRepresentation representation = getUserByUsername(client, realmId, username);
+            if (representation != null) {
+
+                UserResource retrievedUser = client.realm(realmId).users().get(representation.getId());
+                RoleResource adminRoleResource = client.realm(realmId).roles().get("admin");
+                retrievedUser.roles().realmLevel().add(Arrays.asList(adminRoleResource.toRepresentation()));
+
+                String realmManagementClientId = getRealmManagementClientId(client, realmId);
+
+                retrievedUser.roles().clientLevel(realmManagementClientId).add(retrievedUser.roles().clientLevel(realmManagementClientId).listAvailable());
+                return true;
+
+            } else {
+                String msg = "Cannot find existing user with username " + username;
+                LOGGER.error(msg);
+                throw new RuntimeException(msg);
+            }
+        } catch (Exception ex) {
+            String msg = "Error granting admin privilege, reason: " + ex.getMessage();
+            LOGGER.error(msg, ex);
+            throw new RuntimeException(msg, ex);
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    public boolean removeAdminPrivilege(String realmId, String username) {
+        Keycloak client = null;
+        try {
+            client = getClient(iamServerURL, superAdminRealmID, superAdminUserName, superAdminPassword);
+            UserRepresentation representation = getUserByUsername(client, realmId, username);
+            if (representation != null) {
+
+                UserResource retrievedUser = client.realm(realmId).users().get(representation.getId());
+                RoleResource adminRoleResource = client.realm(realmId).roles().get("admin");
+                retrievedUser.roles().realmLevel().remove(Arrays.asList(adminRoleResource.toRepresentation()));
+                String realmManagementClientId = getRealmManagementClientId(client, realmId);
+                List<RoleRepresentation> representations = retrievedUser.roles().clientLevel(realmManagementClientId).listEffective();
+
+                retrievedUser.roles().clientLevel(realmManagementClientId).remove(retrievedUser.roles().clientLevel(realmManagementClientId).listEffective());
+                return true;
+
+            } else {
+                String msg = "Cannot find existing user with username " + username;
+                LOGGER.error(msg);
+                throw new RuntimeException(msg);
+            }
+        } catch (Exception ex) {
+            String msg = "Error removing admin privilege, reason: " + ex.getMessage();
+            LOGGER.error(msg, ex);
+            throw new RuntimeException(msg, ex);
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+
     public KeycloakClientSecret configureClient(String realmId, String clientName, @NotNull String tenantURL, List<String> redirectUris) {
         Keycloak client = null;
         try {
diff --git a/custos-integration-services/user-management-service-parent/user-management-service-sidecar/src/main/resources/user-management-service.pb b/custos-integration-services/user-management-service-parent/user-management-service-sidecar/src/main/resources/user-management-service.pb
index 70db73a..daaa3f1 100644
Binary files a/custos-integration-services/user-management-service-parent/user-management-service-sidecar/src/main/resources/user-management-service.pb and b/custos-integration-services/user-management-service-parent/user-management-service-sidecar/src/main/resources/user-management-service.pb differ
diff --git a/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/interceptors/UserAuthInterceptorImpl.java b/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/interceptors/UserAuthInterceptorImpl.java
index fb5a573..17d6121 100644
--- a/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/interceptors/UserAuthInterceptorImpl.java
+++ b/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/interceptors/UserAuthInterceptorImpl.java
@@ -178,7 +178,8 @@ public class UserAuthInterceptorImpl extends AuthInterceptor {
                     .setPerformedBy(claim.getPerformedBy())
                     .build();
 
-        } else if (method.equals("deleteUser")) {
+        } else if (method.equals("deleteUser") || method.equals("grantAdminPrivileges") ||
+                method.equals("removeAdminPrivileges")) {
             String token = getToken(headers);
             AuthClaim claim = authorizeUsingUserToken(headers);
 
diff --git a/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/service/UserManagementService.java b/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/service/UserManagementService.java
index c6f86c7..a999607 100644
--- a/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/service/UserManagementService.java
+++ b/custos-integration-services/user-management-service-parent/user-management-service/src/main/java/org/apache/custos/user/management/service/UserManagementService.java
@@ -517,7 +517,7 @@ public class UserManagementService extends UserManagementServiceGrpc.UserManagem
             LOGGER.error(msg);
             if (ex.getMessage().contains("UNAUTHENTICATED")) {
                 responseObserver.onError(Status.UNAUTHENTICATED.withDescription(msg).asRuntimeException());
-            } else if  (ex.getMessage().contains("NOT_FOUND")) {
+            } else if (ex.getMessage().contains("NOT_FOUND")) {
                 responseObserver.onError(Status.NOT_FOUND.withDescription(msg).asRuntimeException());
             } else {
                 responseObserver.onError(Status.INTERNAL.withDescription(msg).asRuntimeException());
@@ -1131,8 +1131,13 @@ public class UserManagementService extends UserManagementServiceGrpc.UserManagem
                                             .setProfile(profile)
                                             .build();
 
-                            userProfileClient.updateUserProfile(req);
+                            UserProfile exsistingProfile = userProfileClient.getUser(req);
 
+                            if (exsistingProfile == null || exsistingProfile.getUsername().equals("")) {
+                                userProfileClient.createUserProfile(req);
+                            } else {
+                                userProfileClient.updateUserProfile(req);
+                            }
                         }
 
                         CheckingResponse response = CheckingResponse.newBuilder().setIsExist(true).build();
@@ -1150,8 +1155,8 @@ public class UserManagementService extends UserManagementServiceGrpc.UserManagem
             }
 
         } catch (Exception ex) {
-            String msg = "Error occurred while get all  user profiles in tenant " + ex.getMessage();
-            LOGGER.error(msg);
+            String msg = "Error occurred while linking user profile in tenant " + ex.getMessage();
+            LOGGER.error(msg, ex);
             if (ex.getMessage().contains("UNAUTHENTICATED")) {
                 responseObserver.onError(io.grpc.Status.UNAUTHENTICATED.withDescription(msg).asRuntimeException());
             } else {
@@ -1161,6 +1166,103 @@ public class UserManagementService extends UserManagementServiceGrpc.UserManagem
     }
 
 
+    @Override
+    public void grantAdminPrivileges(UserSearchRequest request, StreamObserver<OperationStatus> responseObserver) {
+        try {
+
+            LOGGER.debug("Request received to grantAdminPrivileges " + request.getUser().getUsername() +
+                    " at" + request.getTenantId());
+
+            iamAdminServiceClient.grantAdminPrivilege(request);
+
+            UserRepresentation representation = iamAdminServiceClient.getUser(request);
+
+            if (representation != null) {
+
+                UserProfile profile = convertToProfile(representation);
+
+                org.apache.custos.user.profile.service.UserProfileRequest profileRequest = org.apache.custos.user.profile.service.UserProfileRequest
+                        .newBuilder()
+                        .setTenantId(request.getTenantId())
+                        .setPerformedBy(request.getPerformedBy())
+                        .setProfile(profile)
+                        .build();
+
+
+                UserProfile exProfile = userProfileClient.getUser(profileRequest);
+
+                if (exProfile == null || exProfile.getUsername().equals("")) {
+
+                    userProfileClient.createUserProfile(profileRequest);
+                } else {
+                    userProfileClient.updateUserProfile(profileRequest);
+
+                }
+
+                OperationStatus status = OperationStatus.newBuilder().setStatus(true).build();
+
+                responseObserver.onNext(status);
+                responseObserver.onCompleted();
+            } else {
+                String msg = "User  not found";
+                LOGGER.error(msg);
+                responseObserver.onError(Status.NOT_FOUND.withDescription(msg).asRuntimeException());
+            }
+
+        } catch (Exception ex) {
+            String msg = "Error occurred while get user profile audit trails " + ex.getMessage();
+            LOGGER.error(msg);
+            responseObserver.onError(Status.INTERNAL.withDescription(msg).asRuntimeException());
+        }
+    }
+
+    @Override
+    public void removeAdminPrivileges(UserSearchRequest request, StreamObserver<OperationStatus> responseObserver) {
+
+        try {
+            LOGGER.debug("Request received to removeAdminPrivileges " + request.getUser().getUsername() +
+                    " at" + request.getTenantId());
+
+            iamAdminServiceClient.removeAdminPrivilege(request);
+
+            UserRepresentation representation = iamAdminServiceClient.getUser(request);
+
+            if (representation != null) {
+
+                UserProfile profile = convertToProfile(representation);
+
+                org.apache.custos.user.profile.service.UserProfileRequest profileRequest = org.apache.custos.user.profile.service.UserProfileRequest
+                        .newBuilder()
+                        .setTenantId(request.getTenantId())
+                        .setPerformedBy(request.getPerformedBy())
+                        .setProfile(profile)
+                        .build();
+
+                UserProfile exProfile = userProfileClient.getUser(profileRequest);
+
+                if (exProfile == null || exProfile.getUsername().equals("")) {
+                    userProfileClient.createUserProfile(profileRequest);
+                } else {
+                    userProfileClient.updateUserProfile(profileRequest);
+                }
+
+                OperationStatus status = OperationStatus.newBuilder().setStatus(true).build();
+                responseObserver.onNext(status);
+                responseObserver.onCompleted();
+            } else {
+                String msg = "User  not found";
+                LOGGER.error(msg);
+                responseObserver.onError(Status.NOT_FOUND.withDescription(msg).asRuntimeException());
+            }
+
+        } catch (Exception ex) {
+            String msg = "Error occurred while get user profile audit trails " + ex.getMessage();
+            LOGGER.error(msg);
+            responseObserver.onError(Status.INTERNAL.withDescription(msg).asRuntimeException());
+
+        }
+    }
+
     private UserProfile convertToProfile(UserRepresentation representation) {
         UserProfile.Builder profileBuilder = UserProfile.newBuilder();
 
diff --git a/custos-integration-services/user-management-service-parent/user-management-service/src/main/proto/UserManagementService.proto b/custos-integration-services/user-management-service-parent/user-management-service/src/main/proto/UserManagementService.proto
index bfa8eea..966c440 100644
--- a/custos-integration-services/user-management-service-parent/user-management-service/src/main/proto/UserManagementService.proto
+++ b/custos-integration-services/user-management-service-parent/user-management-service/src/main/proto/UserManagementService.proto
@@ -120,6 +120,19 @@ service UserManagementService {
          };
     }
 
+    rpc grantAdminPrivileges (org.apache.custos.iam.service.UserSearchRequest) returns (org.apache.custos.iam.service.OperationStatus) {
+        option (google.api.http) = {
+           post: "/user-management/v1.0.0/user/admin"
+           body: "user"
+         };
+    }
+
+    rpc removeAdminPrivileges (org.apache.custos.iam.service.UserSearchRequest) returns (org.apache.custos.iam.service.OperationStatus) {
+        option (google.api.http) = {
+           delete: "/user-management/v1.0.0/user/admin"
+           body: "user"
+         };
+    }
 
     rpc addRolesToUsers (org.apache.custos.iam.service.AddUserRolesRequest) returns (org.apache.custos.iam.service.OperationStatus) {
         option (google.api.http) = {