Browse Source

AMBARI-7737. User in group with cluster operate permission have only read permission functionality.

Siddharth Wagle 10 năm trước cách đây
mục cha
commit
4bbaf7f2a5
17 tập tin đã thay đổi với 695 bổ sung16 xóa
  1. 5 1
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
  2. 5 3
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java
  3. 79 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/UserPrivilegeService.java
  4. 4 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
  5. 2 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
  6. 8 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
  7. 215 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
  8. 3 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
  9. 13 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterDAO.java
  10. 17 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
  11. 17 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
  12. 27 6
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewInstanceDAO.java
  13. 5 1
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
  14. 11 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
  15. 48 0
      ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java
  16. 111 0
      ambari-server/src/test/java/org/apache/ambari/server/api/services/UserPrivilegeServiceTest.java
  17. 125 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java

+ 5 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java

@@ -140,7 +140,7 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
       case StackVersion:
         resourceDefinition = new StackVersionResourceDefinition();
         break;
-        
+
       case StackLevelConfiguration:
         resourceDefinition = new StackLevelConfigurationResourceDefinition();
         break;
@@ -278,6 +278,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new PrivilegeResourceDefinition(Resource.Type.ViewPrivilege);
         break;
 
+      case UserPrivilege:
+        resourceDefinition = new PrivilegeResourceDefinition(Resource.Type.UserPrivilege);
+        break;
+
       case ViewPermission:
         resourceDefinition = new ViewPermissionResourceDefinition();
         break;

+ 5 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java

@@ -17,7 +17,7 @@
  */
 package org.apache.ambari.server.api.resources;
 
-import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.ambari.server.controller.spi.Resource;
@@ -30,7 +30,7 @@ public class UserResourceDefinition extends BaseResourceDefinition {
   public UserResourceDefinition() {
     super(Resource.Type.User);
   }
-  
+
   @Override
   public String getPluralName() {
     return "users";
@@ -43,7 +43,9 @@ public class UserResourceDefinition extends BaseResourceDefinition {
 
   @Override
   public Set<SubResourceDefinition> getSubResourceDefinitions() {
-    return Collections.emptySet();
+    final Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
+    subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.UserPrivilege));
+    return subResourceDefinitions;
   }
 
 }

+ 79 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/UserPrivilegeService.java

@@ -0,0 +1,79 @@
+/**
+ * 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 privileges and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ *  Service responsible for user privilege resource requests.
+ */
+public class UserPrivilegeService extends PrivilegeService {
+
+  private final String userName;
+
+  public UserPrivilegeService(String userName) {
+    this.userName = userName;
+  }
+
+  // ----- PrivilegeService --------------------------------------------------
+
+  @Override
+  public Response createPrivilege(String body, HttpHeaders headers, UriInfo ui) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response updatePrivilege(String body, HttpHeaders headers, UriInfo ui,
+      String privilegeId) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response updatePrivileges(String body, HttpHeaders headers, UriInfo ui) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response deletePrivilege(HttpHeaders headers, UriInfo ui,
+      String privilegeId) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response deletePrivileges(String body, HttpHeaders headers, UriInfo ui) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  protected ResourceInstance createPrivilegeResource(String privilegeId) {
+    final Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.User, userName);
+    mapIds.put(Resource.Type.UserPrivilege, privilegeId);
+    return createResource(Resource.Type.UserPrivilege, mapIds);
+  }
+}

+ 4 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java

@@ -59,6 +59,7 @@ import org.apache.ambari.server.controller.internal.PrivilegeResourceProvider;
 import org.apache.ambari.server.controller.internal.StackAdvisorResourceProvider;
 import org.apache.ambari.server.controller.internal.StackDefinedPropertyProvider;
 import org.apache.ambari.server.controller.internal.StackDependencyResourceProvider;
+import org.apache.ambari.server.controller.internal.UserPrivilegeResourceProvider;
 import org.apache.ambari.server.controller.internal.ViewPermissionResourceProvider;
 import org.apache.ambari.server.controller.nagios.NagiosPropertyProvider;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
@@ -72,6 +73,7 @@ import org.apache.ambari.server.orm.dao.PrincipalDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ResourceDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.MetainfoEntity;
 import org.apache.ambari.server.resources.ResourceManager;
 import org.apache.ambari.server.resources.api.rest.GetResource;
@@ -583,6 +585,8 @@ public class AmbariServer {
     PrivilegeResourceProvider.init(injector.getInstance(PrivilegeDAO.class), injector.getInstance(UserDAO.class),
         injector.getInstance(GroupDAO.class), injector.getInstance(PrincipalDAO.class),
         injector.getInstance(PermissionDAO.class), injector.getInstance(ResourceDAO.class));
+    UserPrivilegeResourceProvider.init(injector.getInstance(UserDAO.class), injector.getInstance(ClusterDAO.class),
+        injector.getInstance(GroupDAO.class), injector.getInstance(ViewInstanceDAO.class));
     ClusterPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     AmbariPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
   }

+ 2 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java

@@ -81,6 +81,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new ClusterPrivilegeResourceProvider();
       case LdapSyncEvent:
         return new LdapSyncEventResourceProvider(managementController);
+      case UserPrivilege:
+        return new UserPrivilegeResourceProvider();
       default:
         return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,
             keyPropertyIds, managementController);

+ 8 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java

@@ -385,6 +385,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
               " permission on a " + entity.getResource().getResourceType().getName() + " resource.");
         }
         privilegeDAO.create(entity);
+        entity.getPrincipal().getPrivileges().add(entity);
+        principalDAO.merge(entity.getPrincipal());
         return null;
       }
     };
@@ -406,6 +408,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
                 throw new AmbariException("Can't remove " + entity.getPermission().getResourceType().getName() +
                     " permission from a " + entity.getResource().getResourceType().getName() + " resource.");
               }
+              entity.getPrincipal().getPrivileges().remove(entity);
+              principalDAO.merge(entity.getPrincipal());
               privilegeDAO.remove(entity);
             }
           }
@@ -461,6 +465,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
             }
 
             privilegeDAO.create(requiredPrivilege);
+            requiredPrivilege.getPrincipal().getPrivileges().add(requiredPrivilege);
+            principalDAO.merge(requiredPrivilege.getPrincipal());
           }
         }
         for (PrivilegeEntity currentPrivilege: currentPrivileges) {
@@ -477,6 +483,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
               throw new AmbariException("Can't remove " + currentPrivilege.getPermission().getResourceType().getName() +
                   " permission from a " + currentPrivilege.getResource().getResourceType().getName() + " resource.");
             }
+            currentPrivilege.getPrincipal().getPrivileges().remove(currentPrivilege);
+            principalDAO.merge(currentPrivilege.getPrincipal());
             privilegeDAO.remove(currentPrivilege);
           }
         }

+ 215 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java

@@ -0,0 +1,215 @@
+/**
+ * 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 privileges and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller.internal;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.GroupEntity;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
+import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+
+/**
+ * Resource provider for user privilege resources.
+ */
+public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
+
+  protected static final String PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID    = PrivilegeResourceProvider.PRIVILEGE_ID_PROPERTY_ID;
+  protected static final String PRIVILEGE_PERMISSION_NAME_PROPERTY_ID = PrivilegeResourceProvider.PERMISSION_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID  = PrivilegeResourceProvider.PRINCIPAL_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_PRINCIPAL_TYPE_PROPERTY_ID  = PrivilegeResourceProvider.PRINCIPAL_TYPE_PROPERTY_ID;
+  protected static final String PRIVILEGE_VIEW_NAME_PROPERTY_ID       = ViewPrivilegeResourceProvider.PRIVILEGE_VIEW_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_VIEW_VERSION_PROPERTY_ID    = ViewPrivilegeResourceProvider.PRIVILEGE_VIEW_VERSION_PROPERTY_ID;
+  protected static final String PRIVILEGE_INSTANCE_NAME_PROPERTY_ID   = ViewPrivilegeResourceProvider.PRIVILEGE_INSTANCE_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_CLUSTER_NAME_PROPERTY_ID    = ClusterPrivilegeResourceProvider.PRIVILEGE_CLUSTER_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_TYPE_PROPERTY_ID            = AmbariPrivilegeResourceProvider.PRIVILEGE_TYPE_PROPERTY_ID;
+  protected static final String PRIVILEGE_USER_NAME_PROPERTY_ID       = "PrivilegeInfo/user_name";
+
+  /**
+   * Data access object used to obtain user entities.
+   */
+  protected static UserDAO userDAO;
+
+  /**
+   * Data access object used to obtain cluster entities.
+   */
+  protected static ClusterDAO clusterDAO;
+
+  /**
+   * Data access object used to obtain group entities.
+   */
+  protected static GroupDAO groupDAO;
+
+  /**
+   * Data access object used to obtain view instance entities.
+   */
+  protected static ViewInstanceDAO viewInstanceDAO;
+
+  /**
+   * The property ids for a privilege resource.
+   */
+  private static Set<String> propertyIds = new HashSet<String>();
+  static {
+    propertyIds.add(PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_PERMISSION_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_PRINCIPAL_TYPE_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_VIEW_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_VIEW_VERSION_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_INSTANCE_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_CLUSTER_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_TYPE_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_USER_NAME_PROPERTY_ID);
+  }
+
+  /**
+   * Static initialization.
+   *
+   * @param userDAO         the user data access object
+   * @param clusterDAO      the cluster data access object
+   * @param groupDAO        the group data access object
+   * @param viewInstanceDAO the view instance data access object
+   */
+  public static void init(UserDAO userDAO, ClusterDAO clusterDAO, GroupDAO groupDAO,
+                          ViewInstanceDAO viewInstanceDAO) {
+    UserPrivilegeResourceProvider.userDAO         = userDAO;
+    UserPrivilegeResourceProvider.clusterDAO      = clusterDAO;
+    UserPrivilegeResourceProvider.groupDAO        = groupDAO;
+    UserPrivilegeResourceProvider.viewInstanceDAO = viewInstanceDAO;
+  }
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>() {
+    {
+      add(PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID);
+    }
+  };
+
+  /**
+   * The key property ids for a privilege resource.
+   */
+  private static Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
+  static {
+    keyPropertyIds.put(Resource.Type.User, PRIVILEGE_USER_NAME_PROPERTY_ID);
+    keyPropertyIds.put(Resource.Type.UserPrivilege, PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID);
+  }
+
+
+  /**
+   * Constructor.
+   */
+  public UserPrivilegeResourceProvider() {
+    super(propertyIds, keyPropertyIds, null);
+  }
+
+  // ----- PrivilegeResourceProvider -----------------------------------------
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Resource> resources = new HashSet<Resource>();
+    final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+
+    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+      final String userName = (String) propertyMap.get(PRIVILEGE_USER_NAME_PROPERTY_ID);
+
+      if (userName != null) {
+        UserEntity userEntity = userDAO.findLocalUserByName(userName);
+        if (userEntity == null) {
+          userEntity = userDAO.findLdapUserByName(userName);
+        }
+        if (userEntity == null) {
+          throw new SystemException("User " + userName + " was not found");
+        }
+
+        final Set<PrivilegeEntity> privileges = userEntity.getPrincipal().getPrivileges();
+        for (MemberEntity membership : userEntity.getMemberEntities()) {
+          privileges.addAll(membership.getGroup().getPrincipal().getPrivileges());
+        }
+
+        for (PrivilegeEntity privilegeEntity : privileges) {
+          final ResourceImpl resource = new ResourceImpl(Resource.Type.UserPrivilege);
+
+          setResourceProperty(resource, PRIVILEGE_USER_NAME_PROPERTY_ID, userName, requestedIds);
+          setResourceProperty(resource, PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID, privilegeEntity.getId(), requestedIds);
+          setResourceProperty(resource, PRIVILEGE_PERMISSION_NAME_PROPERTY_ID, privilegeEntity.getPermission().getPermissionName(), requestedIds);
+          setResourceProperty(resource, PRIVILEGE_PRINCIPAL_TYPE_PROPERTY_ID, privilegeEntity.getPrincipal().getPrincipalType().getName(), requestedIds);
+
+          final String principalTypeName = privilegeEntity.getPrincipal().getPrincipalType().getName();
+          if (principalTypeName.equals(PrincipalTypeEntity.USER_PRINCIPAL_TYPE_NAME)) {
+            final UserEntity user = userDAO.findUserByPrincipal(privilegeEntity.getPrincipal());
+            setResourceProperty(resource, PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID, user.getUserName(), requestedIds);
+          } else if (principalTypeName.equals(PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE_NAME)) {
+            final GroupEntity groupEntity = groupDAO.findGroupByPrincipal(privilegeEntity.getPrincipal());
+            setResourceProperty(resource, PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID, groupEntity.getGroupName(), requestedIds);
+          }
+
+          String privilegeType;
+          switch (privilegeEntity.getResource().getResourceType().getId()) {
+          case ResourceTypeEntity.CLUSTER_RESOURCE_TYPE:
+            final ClusterEntity clusterEntity = clusterDAO.findByResourceId(privilegeEntity.getResource().getId());
+            privilegeType = ResourceTypeEntity.CLUSTER_RESOURCE_TYPE_NAME;
+            setResourceProperty(resource, PRIVILEGE_CLUSTER_NAME_PROPERTY_ID, clusterEntity.getClusterName(), requestedIds);
+            break;
+          case ResourceTypeEntity.AMBARI_RESOURCE_TYPE:
+            privilegeType = ResourceTypeEntity.AMBARI_RESOURCE_TYPE_NAME;
+            break;
+          default:
+            privilegeType = ResourceTypeEntity.VIEW_RESOURCE_TYPE_NAME;
+            final ViewInstanceEntity viewInstanceEntity = viewInstanceDAO.findByResourceId(privilegeEntity.getResource().getId());
+            final ViewEntity viewEntity = viewInstanceEntity.getViewEntity();
+
+            setResourceProperty(resource, PRIVILEGE_VIEW_NAME_PROPERTY_ID, viewEntity.getCommonName(), requestedIds);
+            setResourceProperty(resource, PRIVILEGE_VIEW_VERSION_PROPERTY_ID, viewEntity.getVersion(), requestedIds);
+            setResourceProperty(resource, PRIVILEGE_INSTANCE_NAME_PROPERTY_ID, viewInstanceEntity.getName(), requestedIds);
+            break;
+          }
+          setResourceProperty(resource, PRIVILEGE_TYPE_PROPERTY_ID, privilegeType, requestedIds);
+
+          resources.add(resource);
+        }
+      }
+    }
+    return resources;
+  }
+}

+ 3 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java

@@ -124,7 +124,8 @@ public interface Resource {
     ViewPermission,
     ClientConfig,
     StackLevelConfiguration,
-    LdapSyncEvent;
+    LdapSyncEvent,
+    UserPrivilege;
 
     /**
      * Get the {@link Type} that corresponds to this InternalType.
@@ -210,6 +211,7 @@ public interface Resource {
     public static final Type ClientConfig = InternalType.ClientConfig.getType();
     public static final Type StackLevelConfiguration = InternalType.StackLevelConfiguration.getType();
     public static final Type LdapSyncEvent = InternalType.LdapSyncEvent.getType();
+    public static final Type UserPrivilege = InternalType.UserPrivilege.getType();
 
     /**
      * The type name.

+ 13 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterDAO.java

@@ -28,7 +28,6 @@ import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Root;
 
 import com.google.inject.Singleton;
-import org.apache.ambari.server.controller.ivory.Cluster;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
@@ -66,6 +65,18 @@ public class ClusterDAO {
     }
   }
 
+
+  @RequiresSession
+  public ClusterEntity findByResourceId(long resourceId) {
+    TypedQuery<ClusterEntity> query = entityManagerProvider.get().createNamedQuery("clusterByResourceId", ClusterEntity.class);
+    query.setParameter("resourceId", resourceId);
+    try {
+      return query.getSingleResult();
+    } catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
   @RequiresSession
   public List<ClusterEntity> findAll() {
     TypedQuery<ClusterEntity> query = entityManagerProvider.get().createNamedQuery("allClusters", ClusterEntity.class);
@@ -126,7 +137,7 @@ public class ClusterDAO {
   public void createConfig(ClusterConfigEntity entity) {
     entityManagerProvider.get().persist(entity);
   }
-  
+
   /**
    * Remove a cluster configuration in the DB.
    */

+ 17 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java

@@ -81,6 +81,23 @@ public class GroupDAO {
     return daoUtils.selectList(query);
   }
 
+  /**
+   * Find the group entity for the given admin principal entity.
+   *
+   * @param principal the principal entity
+   *
+   * @return the matching gropu entity
+   */
+  public GroupEntity findGroupByPrincipal(PrincipalEntity principal) {
+    if (principal == null) {
+      return null;
+    }
+    final TypedQuery<GroupEntity> query = entityManagerProvider.get().createQuery("SELECT group_entity FROM GroupEntity group_entity WHERE group_entity.principal.id=:principalId", GroupEntity.class);
+    query.setParameter("principalId", principal.getId());
+    return daoUtils.selectSingle(query);
+  }
+
+
   @Transactional
   public void create(GroupEntity group) {
     create(new HashSet<GroupEntity>(Arrays.asList(group)));

+ 17 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java

@@ -104,6 +104,23 @@ public class UserDAO {
     return daoUtils.selectList(query);
   }
 
+  /**
+   * Find the user entity for the given admin principal entity.
+   *
+   * @param principal the principal entity
+   *
+   * @return the matching user entity
+   */
+  public UserEntity findUserByPrincipal(PrincipalEntity principal) {
+    if (principal == null) {
+      return null;
+    }
+    final TypedQuery<UserEntity> query = entityManagerProvider.get().createQuery("SELECT user_entity FROM UserEntity user_entity WHERE user_entity.principal.id=:principalId", UserEntity.class);
+    query.setParameter("principalId", principal.getId());
+    return daoUtils.selectSingle(query);
+  }
+
+
   @Transactional
   public void create(UserEntity user) {
     create(new HashSet<UserEntity>(Arrays.asList(user)));

+ 27 - 6
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewInstanceDAO.java

@@ -18,16 +18,20 @@
 
 package org.apache.ambari.server.orm.dao;
 
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
-import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-import java.util.List;
 
 /**
  * View Instance Data Access Object.
@@ -57,6 +61,23 @@ public class ViewInstanceDAO {
     return daoUtils.selectSingle(query, viewName, instanceName);
   }
 
+  /**
+   * Find a view instance by given resource id.
+   *
+   * @param resourceId resource id
+   * @return a matching view instance or null
+   */
+  @RequiresSession
+  public ViewInstanceEntity findByResourceId(long resourceId) {
+    TypedQuery<ViewInstanceEntity> query = entityManagerProvider.get().createNamedQuery("viewInstanceByResourceId", ViewInstanceEntity.class);
+    query.setParameter("resourceId", resourceId);
+    try {
+      return query.getSingleResult();
+    } catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
   /**
    * Find all view instances.
    *

+ 5 - 1
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java

@@ -52,7 +52,11 @@ import org.apache.ambari.server.state.State;
             "WHERE cluster.clusterName=:clusterName"),
     @NamedQuery(name = "allClusters", query =
         "SELECT clusters " +
-            "FROM ClusterEntity clusters")
+            "FROM ClusterEntity clusters"),
+    @NamedQuery(name = "clusterByResourceId", query =
+        "SELECT cluster " +
+            "FROM ClusterEntity cluster " +
+            "WHERE cluster.resource.id=:resourceId")
 })
 @Entity
 @TableGenerator(name = "cluster_id_generator",

+ 11 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java

@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -33,6 +34,7 @@ import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
@@ -58,8 +60,15 @@ import org.apache.ambari.view.ViewInstanceDefinition;
     name = "UQ_viewinstance_name", columnNames = {"view_name", "name"}
   )
 )
-@NamedQuery(name = "allViewInstances",
-  query = "SELECT viewInstance FROM ViewInstanceEntity viewInstance")
+@NamedQueries({
+  @NamedQuery(name = "allViewInstances",
+      query = "SELECT viewInstance FROM ViewInstanceEntity viewInstance"),
+  @NamedQuery(name = "viewInstanceByResourceId", query =
+      "SELECT viewInstance " +
+          "FROM ViewInstanceEntity viewInstance " +
+          "WHERE viewInstance.resource.id=:resourceId")
+})
+
 @TableGenerator(name = "view_instance_id_generator",
   table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
   , pkColumnValue = "view_instance_id_seq"

+ 48 - 0
ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java

@@ -0,0 +1,48 @@
+/**
+ * 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.ambari.server.api.resources;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Set;
+
+/**
+ * UserResourceDefinition tests.
+ */
+public class UserResourceDefinitionTest {
+  @Test
+  public void testGetPluralName() throws Exception {
+    final UserResourceDefinition userResourceDefinition = new UserResourceDefinition();
+    Assert.assertEquals("users", userResourceDefinition.getPluralName());
+  }
+
+  @Test
+  public void testGetSingularName() throws Exception {
+    final UserResourceDefinition userResourceDefinition = new UserResourceDefinition();
+    Assert.assertEquals("user", userResourceDefinition.getSingularName());
+  }
+
+  @Test
+  public void testGetSubResourceDefinitions() throws Exception {
+    final UserResourceDefinition userResourceDefinition = new UserResourceDefinition();
+    Set<SubResourceDefinition> subResourceDefinitions = userResourceDefinition.getSubResourceDefinitions();
+    Assert.assertEquals(1, subResourceDefinitions.size());
+  }
+}

+ 111 - 0
ambari-server/src/test/java/org/apache/ambari/server/api/services/UserPrivilegeServiceTest.java

@@ -0,0 +1,111 @@
+/**
+ * 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.ambari.server.api.services;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import junit.framework.Assert;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ * Unit tests for GroupService.
+ */
+public class UserPrivilegeServiceTest extends BaseServiceTest {
+
+  public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+    List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+    UserPrivilegeService userPrivilegeService;
+    Method m;
+    Object[] args;
+
+    //getPrivilege
+    userPrivilegeService = new TestUserPrivilegeService();
+    m = userPrivilegeService.getClass().getMethod("getPrivilege", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "id"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, userPrivilegeService, m, args, null));
+
+    //getPrivileges
+    userPrivilegeService = new TestUserPrivilegeService();
+    m = userPrivilegeService.getClass().getMethod("getPrivileges", HttpHeaders.class, UriInfo.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, userPrivilegeService, m, args, null));
+
+    return listInvocations;
+  }
+
+  @Test
+  public void testDisabledMethods() {
+    final HttpHeaders headers = EasyMock.createNiceMock(HttpHeaders.class);
+    final UriInfo uriInfo = EasyMock.createNiceMock(UriInfo.class);
+    final UserPrivilegeService service = new TestUserPrivilegeService();
+
+    final List<Response> disabledMethods = new ArrayList<Response>();
+    disabledMethods.add(service.createPrivilege("test", headers, uriInfo));
+    disabledMethods.add(service.updatePrivilege("test", headers, uriInfo, "test"));
+    disabledMethods.add(service.updatePrivileges("test", headers, uriInfo));
+    disabledMethods.add(service.deletePrivilege(headers, uriInfo, "test"));
+    disabledMethods.add(service.deletePrivileges("test", headers, uriInfo));
+
+    for (Response response: disabledMethods) {
+      Assert.assertEquals(HttpServletResponse.SC_NOT_IMPLEMENTED, response.getStatus());
+    }
+  }
+
+  private class TestUserPrivilegeService extends UserPrivilegeService {
+
+    public TestUserPrivilegeService() {
+      super("user");
+    }
+
+    @Override
+    protected ResourceInstance createResource(Type type, Map<Type, String> mapIds) {
+      return getTestResource();
+    }
+
+    @Override
+    RequestFactory getRequestFactory() {
+      return getTestRequestFactory();
+    }
+
+    @Override
+    protected RequestBodyParser getBodyParser() {
+      return getTestBodyParser();
+    }
+
+    @Override
+    protected ResultSerializer getResultSerializer() {
+      return getTestResultSerializer();
+    }
+  }
+}

+ 125 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java

@@ -0,0 +1,125 @@
+/**
+ * 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.ambari.server.controller.internal;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
+import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
+import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ResourceEntity;
+import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ * UserPrivilegeResourceProvider tests.
+ */
+public class UserPrivilegeResourceProviderTest {
+
+  @Test(expected = SystemException.class)
+  public void testCreateResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    resourceProvider.createResources(EasyMock.createNiceMock(Request.class));
+  }
+
+  @SuppressWarnings("serial")
+  @Test
+  public void testGetResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    final UserDAO userDAO = EasyMock.createNiceMock(UserDAO.class);
+    final GroupDAO groupDAO = EasyMock.createNiceMock(GroupDAO.class);
+    final ClusterDAO clusterDAO = EasyMock.createNiceMock(ClusterDAO.class);
+    final ViewInstanceDAO viewInstanceDAO = EasyMock.createNiceMock(ViewInstanceDAO.class);
+    final UserEntity userEntity = EasyMock.createNiceMock(UserEntity.class);
+    final PrincipalEntity principalEntity = EasyMock.createNiceMock(PrincipalEntity.class);
+    final PrivilegeEntity privilegeEntity = EasyMock.createNiceMock(PrivilegeEntity.class);
+    final PermissionEntity permissionEntity = EasyMock.createNiceMock(PermissionEntity.class);
+    final PrincipalTypeEntity principalTypeEntity = EasyMock.createNiceMock(PrincipalTypeEntity.class);
+    final ResourceEntity resourceEntity = EasyMock.createNiceMock(ResourceEntity.class);
+    final ResourceTypeEntity resourceTypeEntity = EasyMock.createNiceMock(ResourceTypeEntity.class);
+
+    EasyMock.expect(userDAO.findLocalUserByName("user")).andReturn(userEntity).anyTimes();
+    EasyMock.expect(userEntity.getPrincipal()).andReturn(principalEntity).anyTimes();
+    EasyMock.expect(userEntity.getMemberEntities()).andReturn(Collections.<MemberEntity> emptySet()).anyTimes();
+    EasyMock.expect(privilegeEntity.getPermission()).andReturn(permissionEntity).anyTimes();
+    EasyMock.expect(privilegeEntity.getPrincipal()).andReturn(principalEntity).anyTimes();
+    EasyMock.expect(principalEntity.getPrincipalType()).andReturn(principalTypeEntity).anyTimes();
+    EasyMock.expect(principalTypeEntity.getName()).andReturn(PrincipalTypeEntity.USER_PRINCIPAL_TYPE_NAME).anyTimes();
+    EasyMock.expect(principalEntity.getPrivileges()).andReturn(new HashSet<PrivilegeEntity>() {
+      {
+        add(privilegeEntity);
+      }
+    }).anyTimes();
+    EasyMock.expect(userDAO.findUserByPrincipal(EasyMock.<PrincipalEntity>anyObject())).andReturn(userEntity).anyTimes();
+    EasyMock.expect(userEntity.getUserName()).andReturn("user").anyTimes();
+    EasyMock.expect(privilegeEntity.getResource()).andReturn(resourceEntity).anyTimes();
+    EasyMock.expect(resourceEntity.getResourceType()).andReturn(resourceTypeEntity).anyTimes();
+    EasyMock.expect(resourceTypeEntity.getId()).andReturn(ResourceTypeEntity.AMBARI_RESOURCE_TYPE);
+
+    EasyMock.replay(userDAO, userEntity, principalEntity, privilegeEntity, permissionEntity, principalTypeEntity, resourceEntity, resourceTypeEntity);
+
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO);
+
+    final Set<String> propertyIds = new HashSet<String>();
+    propertyIds.add(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID);
+    //propertyIds.add(UserResourceProvider.USER_PASSWORD_PROPERTY_ID);
+
+    final Predicate predicate = new PredicateBuilder().property(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID).equals("user").toPredicate();
+    Request request = PropertyHelper.getReadRequest(propertyIds);
+    Set<Resource> resources = resourceProvider.getResources(request, predicate);
+
+    Assert.assertEquals(1, resources.size());
+    for (Resource resource : resources) {
+      String userName = (String) resource.getPropertyValue(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID);
+      Assert.assertEquals("user", userName);
+    }
+
+    EasyMock.verify(userDAO, userEntity, principalEntity, privilegeEntity, permissionEntity, principalTypeEntity, resourceEntity, resourceTypeEntity);
+  }
+
+  @Test(expected = SystemException.class)
+  public void testUpdateResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    resourceProvider.updateResources(EasyMock.createNiceMock(Request.class), EasyMock.createNiceMock(Predicate.class));
+  }
+
+  @Test(expected = SystemException.class)
+  public void testDeleteResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    resourceProvider.deleteResources(EasyMock.createNiceMock(Predicate.class));
+  }
+}