You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2015/12/09 18:51:48 UTC

[3/3] ambari git commit: AMBARI-14192. Enforce granular role-based access control for service functions (rlevas)

AMBARI-14192. Enforce granular role-based access control for service functions (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f08db5c9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f08db5c9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f08db5c9

Branch: refs/heads/trunk
Commit: f08db5c996757d265f3fe8d4ecfe5b5e03e693d2
Parents: c17f410
Author: Robert Levas <rl...@hortonworks.com>
Authored: Wed Dec 9 12:51:35 2015 -0500
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Wed Dec 9 12:51:35 2015 -0500

----------------------------------------------------------------------
 .../controller/AmbariManagementController.java  |   4 +-
 .../AmbariManagementControllerImpl.java         | 176 +++++++++++---
 .../AbstractControllerResourceProvider.java     |  14 ++
 .../internal/ComponentResourceProvider.java     |  42 +++-
 .../internal/HostComponentResourceProvider.java |  29 ++-
 .../internal/RequestResourceProvider.java       |  35 ++-
 .../internal/ServiceResourceProvider.java       |  47 +++-
 .../AmbariAuthorizationFilter.java              |   9 +
 .../authorization/AuthorizationHelper.java      |  13 +-
 .../authorization/RoleAuthorization.java        |  51 +++-
 .../server/state/cluster/ClusterImpl.java       |   4 +-
 .../ambari/server/topology/AmbariContext.java   |   3 +-
 .../server/upgrade/UpgradeCatalog220.java       |   2 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   3 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   3 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   3 +
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   3 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   3 +
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   3 +
 .../AmbariCustomCommandExecutionHelperTest.java |  33 ++-
 .../AmbariManagementControllerTest.java         |  39 ++-
 .../BackgroundCustomCommandExecutionTest.java   |  28 ++-
 ...hYarnCapacitySchedulerReleaseConfigTest.java |  12 +-
 .../internal/ClusterResourceProviderTest.java   |  40 +--
 .../internal/ComponentResourceProviderTest.java | 179 ++++++++++++--
 .../HostComponentResourceProviderTest.java      | 101 +++++++-
 .../internal/JMXHostProviderTest.java           |  16 +-
 .../internal/RequestResourceProviderTest.java   | 155 ++++++++++--
 .../internal/ServiceResourceProviderTest.java   | 242 +++++++++++++------
 .../security/TestAuthenticationFactory.java     |  97 +++++++-
 .../authorization/AuthorizationHelperTest.java  |   8 +-
 31 files changed, 1113 insertions(+), 284 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index 4d7eca8..cb197df 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -86,7 +86,7 @@ public interface AmbariManagementController {
    * @throws AmbariException thrown if the host component cannot be created
    */
   public void createHostComponents(
-      Set<ServiceComponentHostRequest> requests) throws AmbariException;
+      Set<ServiceComponentHostRequest> requests) throws AmbariException, AuthorizationException;
 
   /**
    * Creates a configuration.
@@ -281,7 +281,7 @@ public interface AmbariManagementController {
    * @throws AmbariException thrown if the resource cannot be deleted
    */
   public RequestStatusResponse deleteHostComponents(
-      Set<ServiceComponentHostRequest> requests) throws AmbariException;
+      Set<ServiceComponentHostRequest> requests) throws AmbariException, AuthorizationException;
 
   /**
    * Deletes the users specified.

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 5f765bf..3c66127 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -428,7 +428,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
   @Override
   public synchronized void createHostComponents(Set<ServiceComponentHostRequest> requests)
-      throws AmbariException {
+      throws AmbariException, AuthorizationException {
 
     if (requests.isEmpty()) {
       LOG.warn("Received an empty requests set");
@@ -450,6 +450,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
             "Attempted to add a host_component to a cluster which doesn't exist: ", e);
       }
 
+      if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(),
+          EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES,RoleAuthorization.HOST_ADD_DELETE_COMPONENTS))) {
+        throw new AuthorizationException("The authenticated user is not authorized to install service components on to hosts");
+      }
+
       if (StringUtils.isEmpty(request.getServiceName())) {
         request.setServiceName(findServiceName(cluster, request.getComponentName()));
       }
@@ -1479,44 +1484,71 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
     // set or create configuration mapping (and optionally create the map of properties)
     if (isConfigurationCreationNeeded) {
-      Set<Config> configs = new HashSet<Config>();
-      String note = null;
-      for (ConfigurationRequest cr: request.getDesiredConfig()) {
-
-      if (null != cr.getProperties()) {
-        // !!! empty property sets are supported, and need to be able to use
-        // previously-defined configs (revert)
-        Map<String, Config> all = cluster.getConfigsByType(cr.getType());
-        if (null == all ||                              // none set
-            !all.containsKey(cr.getVersionTag()) ||     // tag not set
-            cr.getProperties().size() > 0) {            // properties to set
-
-          LOG.info(MessageFormat.format("Applying configuration with tag ''{0}'' to cluster ''{1}''  for configuration type {2}",
-              cr.getVersionTag(),
-              request.getClusterName(),
-              cr.getType()));
-
-          cr.setClusterName(cluster.getClusterName());
-          configurationResponses.add(createConfiguration(cr));
-        }
-      }
-        note = cr.getServiceConfigVersionNote();
-        configs.add(cluster.getConfig(cr.getType(), cr.getVersionTag()));
-      }
-      if (!configs.isEmpty()) {
-        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), EnumSet.of(RoleAuthorization.SERVICE_MODIFY_CONFIGS))) {
-          throw new AuthorizationException("The authenticated user does not have authorization to modify service configurations");
-        }
+      List<ConfigurationRequest> desiredConfigs = request.getDesiredConfig();
+
+      if (!desiredConfigs.isEmpty()) {
+        Set<Config> configs = new HashSet<Config>();
+        String note = null;
+
+        for (ConfigurationRequest cr : desiredConfigs) {
+          String configType = cr.getType();
+
+          // If the config type is for a service, then allow a user with SERVICE_MODIFY_CONFIGS to
+          // update, else ensure the user has CLUSTER_MODIFY_CONFIGS
+          String service = null;
+
+          try {
+            service = cluster.getServiceForConfigTypes(Collections.singleton(configType));
+          } catch (IllegalArgumentException e) {
+            // Ignore this since we may have hit a config type that spans multiple services. This may
+            // happen in unit test cases but should not happen with later versions of stacks.
+          }
+
+          if(StringUtils.isEmpty(service)) {
+            if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), EnumSet.of(RoleAuthorization.CLUSTER_MODIFY_CONFIGS))) {
+              throw new AuthorizationException("The authenticated user does not have authorization to modify cluster configurations");
+            }
+          }
+          else {
+            if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), EnumSet.of(RoleAuthorization.SERVICE_MODIFY_CONFIGS))) {
+              throw new AuthorizationException("The authenticated user does not have authorization to modify service configurations");
+            }
+          }
+
+          if (null != cr.getProperties()) {
+            // !!! empty property sets are supported, and need to be able to use
+            // previously-defined configs (revert)
+            Map<String, Config> all = cluster.getConfigsByType(configType);
+            if (null == all ||                              // none set
+                !all.containsKey(cr.getVersionTag()) ||     // tag not set
+                cr.getProperties().size() > 0) {            // properties to set
 
-        String authName = getAuthName();
-        serviceConfigVersionResponse = cluster.addDesiredConfig(authName, configs, note);
-        if (serviceConfigVersionResponse != null) {
-          Logger logger = LoggerFactory.getLogger("configchange");
-          for (Config config: configs) {
-            logger.info("cluster '" + request.getClusterName() + "' "
-                + "changed by: '" + authName + "'; "
-                + "type='" + config.getType() + "' "
-                + "tag='" + config.getTag() + "'");
+              // Ensure the user is allowed to update all properties
+              validateAuthorizationToUpdateServiceUsersAndGroups(cluster, cr);
+
+              LOG.info(MessageFormat.format("Applying configuration with tag ''{0}'' to cluster ''{1}''  for configuration type {2}",
+                  cr.getVersionTag(),
+                  request.getClusterName(),
+                  configType));
+
+              cr.setClusterName(cluster.getClusterName());
+              configurationResponses.add(createConfiguration(cr));
+            }
+          }
+          note = cr.getServiceConfigVersionNote();
+          configs.add(cluster.getConfig(configType, cr.getVersionTag()));
+        }
+        if (!configs.isEmpty()) {
+          String authName = getAuthName();
+          serviceConfigVersionResponse = cluster.addDesiredConfig(authName, configs, note);
+          if (serviceConfigVersionResponse != null) {
+            Logger logger = LoggerFactory.getLogger("configchange");
+            for (Config config : configs) {
+              logger.info("cluster '" + request.getClusterName() + "' "
+                  + "changed by: '" + authName + "'; "
+                  + "type='" + config.getType() + "' "
+                  + "tag='" + config.getTag() + "'");
+            }
           }
         }
       }
@@ -2907,7 +2939,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
   @Override
   public RequestStatusResponse deleteHostComponents(
-      Set<ServiceComponentHostRequest> requests) throws AmbariException {
+      Set<ServiceComponentHostRequest> requests) throws AmbariException, AuthorizationException {
 
     Set<ServiceComponentHostRequest> expanded = new HashSet<ServiceComponentHostRequest>();
 
@@ -2920,6 +2952,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         }
         Cluster cluster = clusters.getCluster(request.getClusterName());
 
+        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(),
+            EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES,RoleAuthorization.HOST_ADD_DELETE_COMPONENTS))) {
+          throw new AuthorizationException("The authenticated user is not authorized to delete service components from hosts");
+        }
+
         for (ServiceComponentHost sch : cluster.getServiceComponentHosts(request.getHostname())) {
           ServiceComponentHostRequest schr = new ServiceComponentHostRequest(request.getClusterName(),
               sch.getServiceName(), sch.getServiceComponentName(), sch.getHostName(), null);
@@ -4492,4 +4529,65 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     properties.put("storage.temporary", String.valueOf(credentialStoreService.isInitialized(CredentialStoreType.TEMPORARY)));
     return properties;
   }
+
+  /**
+   * Validates that the authenticated user can set a service's (run-as) user and group.
+   * <p/>
+   * If the user is authorized to set service users and groups, than this method exits quickly.
+   * If the user is not authorized to set service users and groups, then this method verifies that
+   * the properties of types USER and GROUP have not been changed. If they have been, an
+   * AuthorizationException is thrown.
+   *
+   * @param cluster the relevant cluster
+   * @param request the configuration request
+   * @throws AuthorizationException if the user is not authorized to perform this operation
+   */
+  protected void validateAuthorizationToUpdateServiceUsersAndGroups(Cluster cluster, ConfigurationRequest request)
+      throws AuthorizationException {
+    // If the authenticated user is not authorized to set service users or groups, make sure the
+    // relevant properties are not changed. However, if the user is authorized to set service
+    // users and groups, there is nothing to check.
+    if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(),
+        RoleAuthorization.AMBARI_SET_SERVICE_USERS_GROUPS)) {
+
+      Map<String, String> requestProperties = request.getProperties();
+      if (requestProperties != null) {
+        Map<PropertyInfo.PropertyType, Set<String>> propertyTypes = cluster.getConfigPropertiesTypes(
+            request.getType());
+
+        //  Create a composite set of properties to check...
+        Set<String> propertiesToCheck = new HashSet<String>();
+
+        Set<String> userProperties = propertyTypes.get(PropertyType.USER);
+        if (userProperties != null) {
+          propertiesToCheck.addAll(userProperties);
+        }
+
+        Set<String> groupProperties = propertyTypes.get(PropertyType.GROUP);
+        if (groupProperties != null) {
+          propertiesToCheck.addAll(groupProperties);
+        }
+
+        // If there are no USER or GROUP type properties, skip the validation check...
+        if (!propertiesToCheck.isEmpty()) {
+
+          Config existingConfig = cluster.getDesiredConfigByType(request.getType());
+          Map<String, String> existingProperties = (existingConfig == null) ? null : existingConfig.getProperties();
+          if (existingProperties == null) {
+            existingProperties = Collections.emptyMap();
+          }
+
+          for (String propertyName : propertiesToCheck) {
+            String existingProperty = existingProperties.get(propertyName);
+            String requestProperty = requestProperties.get(propertyName);
+
+            // If the properties don't match, so thrown an authorization exception
+            if ((existingProperty == null) ? (requestProperty != null) : !existingProperty.equals(requestProperty)) {
+              throw new AuthorizationException("The authenticated user is not authorized to set service user and groups");
+            }
+          }
+        }
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 60b6901..fdee605 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -21,11 +21,13 @@ package org.apache.ambari.server.controller.internal;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.ResourceProviderFactory;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
+import org.apache.ambari.server.state.Cluster;
 
 /**
  * Abstract resource provider implementation that maps to an Ambari management controller.
@@ -75,6 +77,18 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
   // ----- utility methods ---------------------------------------------------
 
   /**
+   * Gets the cluster id for the named cluster
+   *
+   * @param clusterName the name of the relevant cluster
+   * @return the cluster id or null if not found
+   * @throws AmbariException if the named cluster does not exist
+   */
+  protected Long getClusterId(String clusterName) throws AmbariException {
+    Cluster cluster = managementController.getClusters().getCluster(clusterName);
+    return (cluster == null) ? null : cluster.getClusterId();
+  }
+
+  /**
    * Factory method for obtaining a resource provider based on a given type and management controller.
    *
    * @param type                  the resource type

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
index 59b5fcf..b45ef72 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -47,6 +48,10 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ComponentInfo;
@@ -107,13 +112,20 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
                             MaintenanceStateHelper maintenanceStateHelper) {
     super(propertyIds, keyPropertyIds, managementController);
     this.maintenanceStateHelper = maintenanceStateHelper;
+
+
+    setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES));
+    setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES));
+    setRequiredGetAuthorizations(RoleAuthorization.AUTHORIZATIONS_VIEW_SERVICE);
+    setRequiredGetAuthorizations(RoleAuthorization.AUTHORIZATIONS_VIEW_SERVICE);
+    setRequiredUpdateAuthorizations(RoleAuthorization.AUTHORIZATIONS_UPDATE_CLUSTER);
   }
 
 
   // ----- ResourceProvider ------------------------------------------------
 
   @Override
-  public RequestStatus createResources(Request request)
+  protected RequestStatus createResourcesAuthorized(Request request)
       throws SystemException,
              UnsupportedPropertyException,
              ResourceAlreadyExistsException,
@@ -126,7 +138,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
 
     createResources(new Command<Void>() {
       @Override
-      public Void invoke() throws AmbariException {
+      public Void invoke() throws AmbariException, AuthorizationException {
         createComponents(requests);
         return null;
       }
@@ -191,7 +203,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
 
     RequestStatusResponse response = modifyResources(new Command<RequestStatusResponse>() {
       @Override
-      public RequestStatusResponse invoke() throws AmbariException {
+      public RequestStatusResponse invoke() throws AmbariException, AuthorizationException {
         return updateComponents(requests, request.getRequestInfoProperties(), runSmokeTest);
       }
     });
@@ -202,7 +214,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
   }
 
   @Override
-  public RequestStatus deleteResources(Predicate predicate)
+  protected RequestStatus deleteResourcesAuthorized(Predicate predicate)
       throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
 
     final Set<ServiceComponentRequest> requests = new HashSet<ServiceComponentRequest>();
@@ -211,7 +223,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
       }
     RequestStatusResponse response = modifyResources(new Command<RequestStatusResponse>() {
       @Override
-      public RequestStatusResponse invoke() throws AmbariException {
+      public RequestStatusResponse invoke() throws AmbariException, AuthorizationException {
         return deleteComponents(requests);
       }
     });
@@ -249,7 +261,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
 
   // Create the components for the given requests.
   public synchronized void createComponents(
-      Set<ServiceComponentRequest> requests) throws AmbariException {
+      Set<ServiceComponentRequest> requests) throws AmbariException, AuthorizationException {
 
     if (requests.isEmpty()) {
       LOG.warn("Received an empty requests set");
@@ -284,6 +296,10 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
             "Attempted to add a component to a cluster which doesn't exist:", e);
       }
 
+      if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
+        throw new AuthorizationException("The user is not authorized to create components");
+      }
+
       if (request.getServiceName() == null
           || request.getServiceName().isEmpty()) {
         StackId stackId = cluster.getDesiredStackVersion();
@@ -570,7 +586,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
   // Update the components for the given requests.
   protected synchronized RequestStatusResponse updateComponents(Set<ServiceComponentRequest> requests,
                                                              Map<String, String> requestProperties, boolean runSmokeTest)
-      throws AmbariException {
+      throws AmbariException, AuthorizationException {
 
     if (requests.isEmpty()) {
       LOG.warn("Received an empty requests set");
@@ -723,6 +739,12 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
 
       State oldScState = sc.getDesiredState();
       if (newState != oldScState) {
+        // The if user is trying to start or stop the component, ensure authorization
+        if (((newState == State.INSTALLED) || (newState == State.STARTED)) &&
+            !AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), RoleAuthorization.SERVICE_START_STOP)) {
+          throw new AuthorizationException("The authenticated user is not authorized to start or stop components of services");
+        }
+
         if (!State.isValidDesiredStateTransition(oldScState, newState)) {
           // FIXME throw correct error
           throw new AmbariException("Invalid transition for"
@@ -837,7 +859,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         ignoredScHosts, runSmokeTest, false);
   }
 
-  protected RequestStatusResponse deleteComponents(Set<ServiceComponentRequest> requests) throws AmbariException {
+  protected RequestStatusResponse deleteComponents(Set<ServiceComponentRequest> requests) throws AmbariException, AuthorizationException {
     AmbariManagementController controller = getManagementController();
     Clusters clusters = controller.getClusters();
     AmbariMetaInfo ambariMetaInfo = controller.getAmbariMetaInfo();
@@ -860,6 +882,10 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
               "Attempted to add a component to a cluster which doesn't exist:", e);
       }
 
+      if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
+        throw new AuthorizationException("The user is not authorized to delete components");
+      }
+
       if (request.getServiceName() == null || request.getServiceName().isEmpty()) {
         StackId stackId = cluster.getDesiredStackVersion();
         String serviceName = ambariMetaInfo.getComponentToService(stackId.getStackName(),

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
index af39076..760dcbc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
@@ -52,6 +52,10 @@ import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.MaintenanceState;
@@ -157,12 +161,15 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
             PropertyHelper.getPropertyId("HostRoles", "component_name"));
 
     HOST_COMPONENT_PROPERTIES_PROVIDER.put("RESOURCEMANAGER", httpPropertyProvider);
+
+    setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES,RoleAuthorization.HOST_ADD_DELETE_COMPONENTS));
+    setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES,RoleAuthorization.HOST_ADD_DELETE_COMPONENTS));
   }
 
   // ----- ResourceProvider ------------------------------------------------
 
   @Override
-  public RequestStatus createResources(Request request)
+  protected RequestStatus createResourcesAuthorized(Request request)
       throws SystemException,
       UnsupportedPropertyException,
       ResourceAlreadyExistsException,
@@ -175,7 +182,7 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
 
     createResources(new Command<Void>() {
       @Override
-      public Void invoke() throws AmbariException {
+      public Void invoke() throws AmbariException, AuthorizationException {
         getManagementController().createHostComponents(requests);
         return null;
       }
@@ -309,7 +316,7 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
   }
 
   @Override
-  public RequestStatus deleteResources(Predicate predicate)
+  protected RequestStatus deleteResourcesAuthorized(Predicate predicate)
       throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
     final Set<ServiceComponentHostRequest> requests = new HashSet<ServiceComponentHostRequest>();
     for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
@@ -317,7 +324,7 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
     }
     RequestStatusResponse response = modifyResources(new Command<RequestStatusResponse>() {
       @Override
-      public RequestStatusResponse invoke() throws AmbariException {
+      public RequestStatusResponse invoke() throws AmbariException, AuthorizationException {
         return getManagementController().deleteHostComponents(requests);
       }
     });
@@ -449,7 +456,7 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
   protected synchronized RequestStageContainer updateHostComponents(RequestStageContainer stages,
                                                                     Set<ServiceComponentHostRequest> requests,
                                                                     Map<String, String> requestProperties,
-                                                                    boolean runSmokeTest) throws AmbariException {
+                                                                    boolean runSmokeTest) throws AmbariException, AuthorizationException {
 
     Clusters clusters = getManagementController().getClusters();
 
@@ -472,6 +479,12 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
 
       Cluster cluster = clusters.getCluster(request.getClusterName());
 
+      if(runSmokeTest) {
+        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), RoleAuthorization.SERVICE_RUN_SERVICE_CHECK)) {
+          throw new AuthorizationException("The authenticated user is not authorized to run service checks");
+        }
+      }
+
       if (StringUtils.isEmpty(request.getServiceName())) {
         request.setServiceName(getManagementController().findServiceName(cluster, request.getComponentName()));
       }
@@ -554,6 +567,12 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
         continue;
       }
 
+      if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(),
+          EnumSet.of(RoleAuthorization.SERVICE_START_STOP, RoleAuthorization.SERVICE_ADD_DELETE_SERVICES,
+              RoleAuthorization.HOST_ADD_DELETE_COMPONENTS, RoleAuthorization.HOST_ADD_DELETE_HOSTS))) {
+        throw new AuthorizationException("The authenticated user is not authorized to change the state of service components");
+      }
+
       // STARTED state is invalid for the client component, but this shouldn't cancel the whole stage
       if (sc.isClientComponent() && newState == State.STARTED &&
             !requestProperties.containsKey(sch.getServiceComponentName().toLowerCase())) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
index 061b27d..a356236 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
@@ -50,6 +50,10 @@ import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
 import org.apache.ambari.server.orm.dao.HostRoleCommandStatusSummaryDTO;
 import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.entities.RequestEntity;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 
@@ -159,9 +163,38 @@ public class RequestResourceProvider extends AbstractControllerResourceProvider
     }
     final ExecuteActionRequest actionRequest = getActionRequest(request);
     final Map<String, String> requestInfoProperties = request.getRequestInfoProperties();
+
     return getRequestStatus(createResources(new Command<RequestStatusResponse>() {
       @Override
-      public RequestStatusResponse invoke() throws AmbariException {
+      public RequestStatusResponse invoke() throws AmbariException, AuthorizationException {
+
+        String clusterName = actionRequest.getClusterName();
+
+        if(clusterName == null) {
+          // This must be an administrative action?
+          // TODO: Perform authorization check for this?
+        }
+        else if(actionRequest.isCommand()) {
+          if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, getClusterId(clusterName), RoleAuthorization.SERVICE_RUN_CUSTOM_COMMAND)) {
+            throw new AuthorizationException("The authenticated user is not authorized to execute custom service commands.");
+          }
+        }
+        else {
+          String actionName = actionRequest.getActionName();
+
+          // actionName is expected to not be null since the action request is not a command
+          if(actionName.contains("SERVICE_CHECK")) {
+            if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, getClusterId(clusterName), RoleAuthorization.SERVICE_RUN_SERVICE_CHECK)) {
+              throw new AuthorizationException("The authenticated user is not authorized to execute service checks.");
+            }
+          }
+          else if(actionName.equals("DECOMMISSION")) {
+            if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, getClusterId(clusterName), RoleAuthorization.SERVICE_DECOMMISSION_RECOMMISSION)) {
+              throw new AuthorizationException("The authenticated user is not authorized to decommission services.");
+            }
+          }
+        }
+
         return getManagementController().createAction(actionRequest, requestInfoProperties);
       }
     }));

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
index 0df2507..28af9cb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
@@ -48,6 +48,10 @@ import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.serveraction.kerberos.KerberosAdminAuthenticationException;
 import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
 import org.apache.ambari.server.serveraction.kerberos.KerberosMissingAdminCredentialsException;
@@ -142,12 +146,17 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
                           MaintenanceStateHelper maintenanceStateHelper) {
     super(propertyIds, keyPropertyIds, managementController);
     this.maintenanceStateHelper = maintenanceStateHelper;
+
+    setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES));
+    setRequiredUpdateAuthorizations(RoleAuthorization.AUTHORIZATIONS_UPDATE_SERVICE);
+    setRequiredGetAuthorizations(RoleAuthorization.AUTHORIZATIONS_VIEW_SERVICE);
+    setRequiredDeleteAuthorizations(EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES));
   }
 
   // ----- ResourceProvider ------------------------------------------------
 
   @Override
-  public RequestStatus createResources(Request request)
+  protected RequestStatus createResourcesAuthorized(Request request)
       throws SystemException,
              UnsupportedPropertyException,
              ResourceAlreadyExistsException,
@@ -159,7 +168,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
     }
     createResources(new Command<Void>() {
       @Override
-      public Void invoke() throws AmbariException {
+      public Void invoke() throws AmbariException, AuthorizationException {
         createServices(requests);
         return null;
       }
@@ -170,7 +179,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
   }
 
   @Override
-  public Set<Resource> getResources(Request request, Predicate predicate) throws
+  protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws
       SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
 
     final Set<ServiceRequest> requests = new HashSet<ServiceRequest>();
@@ -214,7 +223,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
   }
 
   @Override
-  public RequestStatus updateResources(final Request request, Predicate predicate)
+  protected RequestStatus updateResourcesAuthorized(final Request request, Predicate predicate)
       throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
 
     RequestStageContainer requestStages = doUpdateResources(null, request, predicate);
@@ -234,7 +243,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
   }
 
   @Override
-  public RequestStatus deleteResources(Predicate predicate)
+  protected RequestStatus deleteResourcesAuthorized(Predicate predicate)
       throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
 
     final Set<ServiceRequest> requests = new HashSet<ServiceRequest>();
@@ -243,7 +252,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
     }
     RequestStatusResponse response = modifyResources(new Command<RequestStatusResponse>() {
       @Override
-      public RequestStatusResponse invoke() throws AmbariException {
+      public RequestStatusResponse invoke() throws AmbariException, AuthorizationException {
         return deleteServices(requests);
       }
     });
@@ -305,7 +314,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
       requestStages = modifyResources(new Command<RequestStageContainer>() {
         @Override
-        public RequestStageContainer invoke() throws AmbariException {
+        public RequestStageContainer invoke() throws AmbariException, AuthorizationException {
           return updateServices(stages, requests, request.getRequestInfoProperties(),
               runSmokeTest, reconfigureClients, startDependencies);
         }
@@ -337,7 +346,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
   // Create services from the given request.
   public synchronized void createServices(Set<ServiceRequest> requests)
-      throws AmbariException {
+      throws AmbariException, AuthorizationException {
 
     if (requests.isEmpty()) {
       LOG.warn("Received an empty requests set");
@@ -366,6 +375,10 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
             + ", request=" + request);
       }
 
+      if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, getClusterId(request.getClusterName()), RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
+        throw new AuthorizationException("The user is not authorized to create services");
+      }
+
       if (!serviceNames.containsKey(request.getClusterName())) {
         serviceNames.put(request.getClusterName(), new HashSet<String>());
       }
@@ -537,7 +550,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
   // Update services based on the given requests.
   protected synchronized RequestStageContainer updateServices(RequestStageContainer requestStages, Set<ServiceRequest> requests,
                                                       Map<String, String> requestProperties, boolean runSmokeTest,
-                                                      boolean reconfigureClients, boolean startDependencies) throws AmbariException {
+                                                      boolean reconfigureClients, boolean startDependencies) throws AmbariException, AuthorizationException {
 
     AmbariManagementController controller = getManagementController();
 
@@ -624,6 +637,10 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
       // Setting Maintenance state for service
       if (null != request.getMaintenanceState()) {
+        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), RoleAuthorization.SERVICE_TOGGLE_MAINTENANCE)) {
+          throw new AuthorizationException("The authenticated user is not authorized to toggle the maintainence state of services");
+        }
+
         MaintenanceState newMaint = MaintenanceState.valueOf(request.getMaintenanceState());
         if (newMaint  != s.getMaintenanceState()) {
           if (newMaint.equals(MaintenanceState.IMPLIED_FROM_HOST)
@@ -656,6 +673,12 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
       seenNewStates.add(newState);
 
       if (newState != oldState) {
+        // The if user is trying to start or stop the service, ensure authorization
+        if (((newState == State.INSTALLED) || (newState == State.STARTED)) &&
+            !AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), RoleAuthorization.SERVICE_START_STOP)) {
+          throw new AuthorizationException("The authenticated user is not authorized to start or stop services");
+        }
+
         if (!State.isValidDesiredStateTransition(oldState, newState)) {
           throw new AmbariException("Invalid transition for"
               + " service"
@@ -849,7 +872,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
   // Delete services based on the given set of requests
   protected RequestStatusResponse deleteServices(Set<ServiceRequest> request)
-      throws AmbariException {
+      throws AmbariException, AuthorizationException {
 
     Clusters clusters    = getManagementController().getClusters();
 
@@ -861,6 +884,10 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
         throw new AmbariException("invalid arguments");
       } else {
 
+        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, getClusterId(serviceRequest.getClusterName()), RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
+          throw new AuthorizationException("The user is not authorized to delete services");
+        }
+
         Service service = clusters.getCluster(
             serviceRequest.getClusterName()).getService(
                 serviceRequest.getServiceName());

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
index c87c338..21745b4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
@@ -65,12 +65,16 @@ public class AmbariAuthorizationFilter implements Filter {
   private static final String API_PRIVILEGES_ALL_PATTERN = API_VERSION_PREFIX + "/privileges.*";
   private static final String API_GROUPS_ALL_PATTERN = API_VERSION_PREFIX + "/groups.*";
   private static final String API_CLUSTERS_PATTERN = API_VERSION_PREFIX + "/clusters/(\\w+)?";
+  private static final String API_WIDGET_LAYOUTS_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/widget_layouts.*?";
   private static final String API_CLUSTERS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters.*";
   private static final String API_VIEWS_ALL_PATTERN = API_VERSION_PREFIX + "/views.*";
   private static final String API_PERSIST_ALL_PATTERN = API_VERSION_PREFIX + "/persist.*";
   private static final String API_LDAP_SYNC_EVENTS_ALL_PATTERN = API_VERSION_PREFIX + "/ldap_sync_events.*";
   private static final String API_CREDENTIALS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/credentials.*";
   private static final String API_CREDENTIALS_AMBARI_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/credentials/ambari\\..*";
+  private static final String API_CLUSTER_REQUESTS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/requests.*";
+  private static final String API_CLUSTER_SERVICES_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/services.*";
+  private static final String API_HOSTS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/hosts.*";
   private static final String API_STACK_VERSIONS_PATTERN = API_VERSION_PREFIX + "/stacks/.*?/versions/.*";
 
   protected static final String LOGIN_REDIRECT_BASE = "/#/login?targetURI=";
@@ -254,8 +258,13 @@ public class AmbariAuthorizationFilter implements Filter {
     return requestURI.matches(API_USERS_ALL_PATTERN) ||
         requestURI.matches(API_GROUPS_ALL_PATTERN) ||
         requestURI.matches(API_CREDENTIALS_ALL_PATTERN) ||
+        requestURI.matches(API_PRIVILEGES_ALL_PATTERN) ||
+        requestURI.matches(API_CLUSTER_REQUESTS_ALL_PATTERN) ||
+        requestURI.matches(API_CLUSTER_SERVICES_ALL_PATTERN) ||
         requestURI.matches(API_CLUSTERS_PATTERN) ||
         requestURI.matches(API_STACK_VERSIONS_PATTERN) ||
+        requestURI.matches(API_WIDGET_LAYOUTS_PATTERN) ||
+        requestURI.matches(API_HOSTS_ALL_PATTERN) ||
         requestURI.matches(API_PRIVILEGES_ALL_PATTERN);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
index e303066..1b3e6f4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
@@ -21,6 +21,7 @@ import com.google.inject.Singleton;
 import org.apache.ambari.server.orm.entities.PermissionEntity;
 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.RoleAuthorizationEntity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -163,7 +164,17 @@ public class AuthorizationHelper {
           // This resource type indicates administrative access
           resourceOK = true;
         } else if (resourceType == privilegeResourceType) {
-          resourceOK = (resourceId == null) || resourceId.equals(privilegeResource.getId());
+          if(resourceId == null) {
+            resourceOK = true;
+          }
+          else {
+            // Note: This will be an issue for multiple clusters. Apparently we assume only one cluster
+            // and it's resource id is 2.
+            // TODO: Change adminresource to include a reference to the resource instance, not just the type
+            ResourceTypeEntity privilegeResourceResourceType = privilegeResource.getResourceType();
+            Integer privilegeResourceId = privilegeResourceResourceType.getId();
+            resourceOK = resourceId.equals(privilegeResourceId.longValue());
+          }
         } else {
           // This is not an expected resource type, so skip this authority
           resourceOK = false;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java
index 1f53b06..02eb5b4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java
@@ -39,6 +39,7 @@ public enum RoleAuthorization {
   AMBARI_RENAME_CLUSTER("AMBARI.RENAME_CLUSTER"),
   AMBARI_SET_SERVICE_USERS_GROUPS("AMBARI.SET_SERVICE_USERS_GROUPS"),
   CLUSTER_MANAGE_CREDENTIALS("CLUSTER.MANAGE_CREDENTIALS"),
+  CLUSTER_MODIFY_CONFIGS("CLUSTER.MODIFY_CONFIGS"),
   CLUSTER_TOGGLE_ALERTS("CLUSTER.TOGGLE_ALERTS"),
   CLUSTER_TOGGLE_KERBEROS("CLUSTER.TOGGLE_KERBEROS"),
   CLUSTER_UPGRADE_DOWNGRADE_STACK("CLUSTER.UPGRADE_DOWNGRADE_STACK"),
@@ -71,8 +72,54 @@ public enum RoleAuthorization {
   SERVICE_VIEW_STATUS_INFO("SERVICE.VIEW_STATUS_INFO"),
   VIEW_USE("VIEW.USE");
 
-  public static final Set<RoleAuthorization> AUTHORIZATIONS_VIEW_CLUSTER = EnumSet.of(CLUSTER_VIEW_STATUS_INFO, CLUSTER_VIEW_ALERTS, CLUSTER_VIEW_CONFIGS, CLUSTER_VIEW_METRICS, CLUSTER_VIEW_STACK_DETAILS);
-  public static final Set<RoleAuthorization> AUTHORIZATIONS_UPDATE_CLUSTER = EnumSet.of(CLUSTER_TOGGLE_ALERTS, CLUSTER_TOGGLE_KERBEROS, CLUSTER_UPGRADE_DOWNGRADE_STACK);
+  public static final Set<RoleAuthorization> AUTHORIZATIONS_VIEW_CLUSTER = EnumSet.of(
+      CLUSTER_VIEW_STATUS_INFO,
+      CLUSTER_VIEW_ALERTS,
+      CLUSTER_VIEW_CONFIGS,
+      CLUSTER_VIEW_METRICS,
+      CLUSTER_VIEW_STACK_DETAILS,
+      CLUSTER_MODIFY_CONFIGS,
+      CLUSTER_TOGGLE_ALERTS,
+      CLUSTER_TOGGLE_KERBEROS,
+      CLUSTER_UPGRADE_DOWNGRADE_STACK);
+
+  public static final Set<RoleAuthorization> AUTHORIZATIONS_UPDATE_CLUSTER = EnumSet.of(
+      CLUSTER_TOGGLE_ALERTS,
+      CLUSTER_TOGGLE_KERBEROS,
+      CLUSTER_UPGRADE_DOWNGRADE_STACK,
+      CLUSTER_MODIFY_CONFIGS,
+      SERVICE_MODIFY_CONFIGS);
+
+  public static final Set<RoleAuthorization> AUTHORIZATIONS_VIEW_SERVICE = EnumSet.of(
+      SERVICE_VIEW_ALERTS,
+      SERVICE_VIEW_CONFIGS,
+      SERVICE_VIEW_METRICS,
+      SERVICE_VIEW_STATUS_INFO,
+      SERVICE_COMPARE_CONFIGS,
+      SERVICE_ADD_DELETE_SERVICES,
+      SERVICE_DECOMMISSION_RECOMMISSION,
+      SERVICE_ENABLE_HA,
+      SERVICE_MANAGE_CONFIG_GROUPS,
+      SERVICE_MODIFY_CONFIGS,
+      SERVICE_START_STOP,
+      SERVICE_TOGGLE_MAINTENANCE,
+      SERVICE_TOGGLE_ALERTS,
+      SERVICE_MOVE,
+      SERVICE_RUN_CUSTOM_COMMAND,
+      SERVICE_RUN_SERVICE_CHECK);
+
+  public static final Set<RoleAuthorization> AUTHORIZATIONS_UPDATE_SERVICE = EnumSet.of(
+      SERVICE_ADD_DELETE_SERVICES,
+      SERVICE_DECOMMISSION_RECOMMISSION,
+      SERVICE_ENABLE_HA,
+      SERVICE_MANAGE_CONFIG_GROUPS,
+      SERVICE_MODIFY_CONFIGS,
+      SERVICE_START_STOP,
+      SERVICE_TOGGLE_MAINTENANCE,
+      SERVICE_TOGGLE_ALERTS,
+      SERVICE_MOVE,
+      SERVICE_RUN_CUSTOM_COMMAND,
+      SERVICE_RUN_SERVICE_CHECK);
 
   private final String id;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index 1078343..911d8d7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -2261,8 +2261,8 @@ public class ClusterImpl implements Cluster {
         if (StringUtils.equals(entry.getValue(), configType)) {
           if (serviceName != null) {
             if (entry.getKey()!=null && !StringUtils.equals(serviceName, entry.getKey())) {
-              throw new IllegalArgumentException("Config type {} belongs to {} service, " +
-                "but config group qualified for {}");
+              throw new IllegalArgumentException(String.format("Config type %s belongs to %s service, " +
+                "but also qualified for %s", configType, serviceName, entry.getKey()));
             }
           } else {
             serviceName = entry.getKey();

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
index d9ac183..0a2bd18 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
@@ -47,6 +47,7 @@ import org.apache.ambari.server.controller.spi.ClusterController;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
@@ -188,7 +189,7 @@ public class AmbariContext {
     try {
       getServiceResourceProvider().createServices(serviceRequests);
       getComponentResourceProvider().createComponents(componentRequests);
-    } catch (AmbariException e) {
+    } catch (AmbariException | AuthorizationException e) {
       throw new RuntimeException("Failed to persist service and component resources: " + e, e);
     }
     // set all services state to INSTALLED->STARTED

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
index f83501c..ab0b3cd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
@@ -196,6 +196,7 @@ public class UpgradeCatalog220 extends AbstractUpgradeCatalog {
     dbAccessor.insertRow(ROLE_AUTHORIZATION_TABLE, columnNames, new String[]{"'CLUSTER.VIEW_STACK_DETAILS'", "'View stack version details'"}, false);
     dbAccessor.insertRow(ROLE_AUTHORIZATION_TABLE, columnNames, new String[]{"'CLUSTER.VIEW_ALERTS'", "'View alerts'"}, false);
     dbAccessor.insertRow(ROLE_AUTHORIZATION_TABLE, columnNames, new String[]{"'CLUSTER.MANAGE_CREDENTIALS'", "'Manage external credentials'"}, false);
+    dbAccessor.insertRow(ROLE_AUTHORIZATION_TABLE, columnNames, new String[]{"'CLUSTER.MODIFY_CONFIGS'", "'Modify cluster configurations'"}, false);
     dbAccessor.insertRow(ROLE_AUTHORIZATION_TABLE, columnNames, new String[]{"'CLUSTER.TOGGLE_ALERTS'", "'Enable/disable alerts'"}, false);
     dbAccessor.insertRow(ROLE_AUTHORIZATION_TABLE, columnNames, new String[]{"'CLUSTER.TOGGLE_KERBEROS'", "'Enable/disable Kerberos'"}, false);
     dbAccessor.insertRow(ROLE_AUTHORIZATION_TABLE, columnNames, new String[]{"'CLUSTER.UPGRADE_DOWNGRADE_STACK'", "'Upgrade/downgrade stack'"}, false);
@@ -288,6 +289,7 @@ public class UpgradeCatalog220 extends AbstractUpgradeCatalog {
     map.put("CLUSTER.VIEW_STACK_DETAILS", clusterUserAndUp);
     map.put("CLUSTER.VIEW_ALERTS", clusterUserAndUp);
     map.put("CLUSTER.MANAGE_CREDENTIALS", clusterAdministratorAndUp);
+    map.put("CLUSTER.MODIFY_CONFIGS", clusterAdministratorAndUp);
     map.put("CLUSTER.TOGGLE_ALERTS", clusterAdministratorAndUp);
     map.put("CLUSTER.TOGGLE_KERBEROS", clusterAdministratorAndUp);
     map.put("CLUSTER.UPGRADE_DOWNGRADE_STACK", clusterAdministratorAndUp);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 5d65665..788c2a7 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -1048,6 +1048,7 @@ INSERT INTO roleauthorization(authorization_id, authorization_name)
   SELECT 'CLUSTER.VIEW_STACK_DETAILS', 'View stack version details' UNION ALL
   SELECT 'CLUSTER.VIEW_ALERTS', 'View alerts' UNION ALL
   SELECT 'CLUSTER.MANAGE_CREDENTIALS', 'Manage external credentials' UNION ALL
+  SELECT 'CLUSTER.MODIFY_CONFIGS', 'Modify cluster configurations' UNION ALL
   SELECT 'CLUSTER.TOGGLE_ALERTS', 'Enable/disable alerts' UNION ALL
   SELECT 'CLUSTER.TOGGLE_KERBEROS', 'Enable/disable Kerberos' UNION ALL
   SELECT 'CLUSTER.UPGRADE_DOWNGRADE_STACK', 'Upgrade/downgrade stack' UNION ALL
@@ -1187,6 +1188,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR';
@@ -1222,6 +1224,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 7aab3f7..ae560d9 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -1040,6 +1040,7 @@ INSERT INTO roleauthorization(authorization_id, authorization_name)
   SELECT 'CLUSTER.VIEW_STACK_DETAILS', 'View stack version details' FROM dual UNION ALL
   SELECT 'CLUSTER.VIEW_ALERTS', 'View alerts' FROM dual UNION ALL
   SELECT 'CLUSTER.MANAGE_CREDENTIALS', 'Manage external credentials' from dual UNION ALL
+  SELECT 'CLUSTER.MODIFY_CONFIGS', 'Modify cluster configurations' from dual UNION ALL
   SELECT 'CLUSTER.TOGGLE_ALERTS', 'Enable/disable alerts' FROM dual UNION ALL
   SELECT 'CLUSTER.TOGGLE_KERBEROS', 'Enable/disable Kerberos' FROM dual UNION ALL
   SELECT 'CLUSTER.UPGRADE_DOWNGRADE_STACK', 'Upgrade/downgrade stack' FROM dual UNION ALL
@@ -1179,6 +1180,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR';
@@ -1214,6 +1216,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 6c56a85..155a6a7 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -1084,6 +1084,7 @@ INSERT INTO roleauthorization(authorization_id, authorization_name)
   SELECT 'CLUSTER.VIEW_STACK_DETAILS', 'View stack version details' UNION ALL
   SELECT 'CLUSTER.VIEW_ALERTS', 'View alerts' UNION ALL
   SELECT 'CLUSTER.MANAGE_CREDENTIALS', 'Manage external credentials' UNION ALL
+  SELECT 'CLUSTER.MODIFY_CONFIGS', 'Modify cluster configurations' UNION ALL
   SELECT 'CLUSTER.TOGGLE_ALERTS', 'Enable/disable alerts' UNION ALL
   SELECT 'CLUSTER.TOGGLE_KERBEROS', 'Enable/disable Kerberos' UNION ALL
   SELECT 'CLUSTER.UPGRADE_DOWNGRADE_STACK', 'Upgrade/downgrade stack' UNION ALL
@@ -1223,6 +1224,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR';
@@ -1258,6 +1260,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index 3413285..4c20767 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -1182,6 +1182,7 @@ INSERT INTO ambari.roleauthorization(authorization_id, authorization_name)
   SELECT 'CLUSTER.VIEW_STACK_DETAILS', 'View stack version details' UNION ALL
   SELECT 'CLUSTER.VIEW_ALERTS', 'View alerts' UNION ALL
   SELECT 'CLUSTER.MANAGE_CREDENTIALS', 'Manage external credentials' UNION ALL
+  SELECT 'CLUSTER.MODIFY_CONFIGS', 'Modify cluster configurations' UNION ALL
   SELECT 'CLUSTER.TOGGLE_ALERTS', 'Enable/disable alerts' UNION ALL
   SELECT 'CLUSTER.TOGGLE_KERBEROS', 'Enable/disable Kerberos' UNION ALL
   SELECT 'CLUSTER.UPGRADE_DOWNGRADE_STACK', 'Upgrade/downgrade stack' UNION ALL
@@ -1321,6 +1322,7 @@ INSERT INTO ambari.permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM ambari.adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR';
@@ -1356,6 +1358,7 @@ INSERT INTO ambari.permission_roleauthorization(permission_id, authorization_id)
   SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM ambari.adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM ambari.adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM ambari.adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
+  SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM ambari.adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM ambari.adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM ambari.adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
   SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM ambari.adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index bacce35..dc08960 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -1036,6 +1036,7 @@ insert into adminpermission(permission_id, permission_name, resource_type_id, pe
     SELECT 'CLUSTER.VIEW_STACK_DETAILS', 'View stack version details' UNION ALL
     SELECT 'CLUSTER.VIEW_ALERTS', 'View alerts' UNION ALL
     SELECT 'CLUSTER.MANAGE_CREDENTIALS', 'Manage external credentials' UNION ALL
+    SELECT 'CLUSTER.MODIFY_CONFIGS', 'Modify cluster configurations' UNION ALL
     SELECT 'CLUSTER.TOGGLE_ALERTS', 'Enable/disable alerts' UNION ALL
     SELECT 'CLUSTER.TOGGLE_KERBEROS', 'Enable/disable Kerberos' UNION ALL
     SELECT 'CLUSTER.UPGRADE_DOWNGRADE_STACK', 'Upgrade/downgrade stack' UNION ALL
@@ -1175,6 +1176,7 @@ insert into adminpermission(permission_id, permission_name, resource_type_id, pe
     SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
+    SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR';
@@ -1210,6 +1212,7 @@ insert into adminpermission(permission_id, permission_name, resource_type_id, pe
     SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
+    SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index 8d44b28..10b1ac6 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -1145,6 +1145,7 @@ BEGIN TRANSACTION
     SELECT 'CLUSTER.VIEW_STACK_DETAILS', 'View stack version details' UNION ALL
     SELECT 'CLUSTER.VIEW_ALERTS', 'View alerts' UNION ALL
     SELECT 'CLUSTER.MANAGE_CREDENTIALS', 'Manage external credentials' UNION ALL
+    SELECT 'CLUSTER.MODIFY_CONFIGS', 'Modify cluster configurations' UNION ALL
     SELECT 'CLUSTER.TOGGLE_ALERTS', 'Enable/disable alerts' UNION ALL
     SELECT 'CLUSTER.TOGGLE_KERBEROS', 'Enable/disable Kerberos' UNION ALL
     SELECT 'CLUSTER.UPGRADE_DOWNGRADE_STACK', 'Upgrade/downgrade stack' UNION ALL
@@ -1284,6 +1285,7 @@ BEGIN TRANSACTION
     SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
+    SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR';
@@ -1319,6 +1321,7 @@ BEGIN TRANSACTION
     SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
+    SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
     SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL

http://git-wip-us.apache.org/repos/asf/ambari/blob/f08db5c9/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
index 53630aa..9eed672 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
@@ -33,7 +33,6 @@ import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
 import org.apache.ambari.server.actionmanager.Request;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.agent.ExecutionCommand;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.internal.ComponentResourceProviderTest;
 import org.apache.ambari.server.controller.internal.RequestOperationLevel;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
@@ -42,6 +41,7 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Host;
@@ -66,14 +66,14 @@ import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
 
 import junit.framework.Assert;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
 
 @RunWith(MockitoJUnitRunner.class)
 public class AmbariCustomCommandExecutionHelperTest {
   private Injector injector;
   private AmbariManagementController controller;
-  private AmbariMetaInfo ambariMetaInfo;
   private Clusters clusters;
-  private TopologyManager topologyManager;
 
 
   private static final String REQUEST_CONTEXT_PROPERTY = "context";
@@ -83,6 +83,7 @@ public class AmbariCustomCommandExecutionHelperTest {
 
   @Before
   public void setup() throws Exception {
+    TopologyManager topologyManager;
     InMemoryDefaultTestModule module = new InMemoryDefaultTestModule(){
       @Override
       protected void configure() {
@@ -96,10 +97,15 @@ public class AmbariCustomCommandExecutionHelperTest {
     injector.getInstance(GuiceJpaInitializer.class);
     controller = injector.getInstance(AmbariManagementController.class);
     clusters = injector.getInstance(Clusters.class);
-    ambariMetaInfo = injector.getInstance(AmbariMetaInfo.class);
     topologyManager = injector.getInstance(TopologyManager.class);
     StageUtils.setTopologyManager(topologyManager);
   }
+
+  @After
+  public void clearAuthentication() {
+    SecurityContextHolder.getContext().setAuthentication(null);
+  }
+
   @After
   public void teardown() {
     injector.getInstance(PersistService.class).stop();
@@ -108,6 +114,8 @@ public class AmbariCustomCommandExecutionHelperTest {
   @SuppressWarnings("serial")
   @Test
   public void testRefreshQueueCustomCommand() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator());
+
     createClusterFixture("HDP-2.0.6");
 
     Map<String, String> requestProperties = new HashMap<String, String>() {
@@ -152,6 +160,8 @@ public class AmbariCustomCommandExecutionHelperTest {
 
   @Test
   public void testHostsFilterHealthy() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator());
+
     createClusterFixture("HDP-2.0.6");
 
     Map<String, String> requestProperties = new HashMap<String, String>() {
@@ -195,6 +205,8 @@ public class AmbariCustomCommandExecutionHelperTest {
 
   @Test
   public void testHostsFilterUnhealthyHost() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator());
+
     createClusterFixture("HDP-2.0.6");
 
     // Set custom status to host
@@ -239,6 +251,8 @@ public class AmbariCustomCommandExecutionHelperTest {
 
   @Test
   public void testHostsFilterUnhealthyComponent() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator());
+
     createClusterFixture("HDP-2.0.6");
 
     // Set custom status to host
@@ -289,6 +303,8 @@ public class AmbariCustomCommandExecutionHelperTest {
    */
   @Test(expected = AmbariException.class)
   public void testNoCandidateHostThrowsException() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator());
+
     createClusterFixture("HDP-2.0.6");
     long clusterId = clusters.getCluster("c1").getClusterId();
 
@@ -326,6 +342,8 @@ public class AmbariCustomCommandExecutionHelperTest {
 
   @Test
   public void testIsTopologyRefreshRequired() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator());
+
     AmbariCustomCommandExecutionHelper helper = injector.getInstance(AmbariCustomCommandExecutionHelper.class);
 
     createClusterFixture("HDP-2.1.1");
@@ -385,7 +403,7 @@ public class AmbariCustomCommandExecutionHelperTest {
   }
 
   private void createService(String clusterName,
-      String serviceName, State desiredState) throws AmbariException {
+      String serviceName, State desiredState) throws AmbariException, AuthorizationException {
     String dStateStr = null;
     if (desiredState != null) {
       dStateStr = desiredState.toString();
@@ -399,7 +417,7 @@ public class AmbariCustomCommandExecutionHelperTest {
 
   private void createServiceComponent(String clusterName,
       String serviceName, String componentName, State desiredState)
-          throws AmbariException {
+      throws AmbariException, AuthorizationException {
     String dStateStr = null;
     if (desiredState != null) {
       dStateStr = desiredState.toString();
@@ -412,7 +430,8 @@ public class AmbariCustomCommandExecutionHelperTest {
     ComponentResourceProviderTest.createComponents(controller, requests);
   }
 
-  private void createServiceComponentHost(String clusterName, String serviceName, String componentName, String hostname, State desiredState) throws AmbariException {
+  private void createServiceComponentHost(String clusterName, String serviceName, String componentName, String hostname, State desiredState)
+      throws AmbariException, AuthorizationException {
     String dStateStr = null;
     if (desiredState != null) {
       dStateStr = desiredState.toString();