Browse Source

AMBARI-16177. Views: User should be able to assign permission of a view instance to cluster roles. (dipayanb)

Dipayan Bhowmick 9 năm trước cách đây
mục cha
commit
4342a6b7eb
45 tập tin đã thay đổi với 1488 bổ sung482 xóa
  1. 369 359
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
  2. 9 0
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
  3. 5 7
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
  4. 9 1
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
  5. 14 2
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
  6. 8 0
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
  7. 6 0
      ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
  8. 50 35
      ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
  9. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
  10. 2 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
  11. 17 7
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProvider.java
  12. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
  13. 28 9
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
  14. 8 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrincipalDAO.java
  15. 2 1
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalEntity.java
  16. 10 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalTypeEntity.java
  17. 67 6
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
  18. 213 0
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/ClusterInheritedPermissionHelper.java
  19. 36 0
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
  20. 27 0
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
  21. 56 1
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
  22. 27 0
      ambari-server/src/main/java/org/apache/ambari/server/view/configuration/AutoInstanceConfig.java
  23. 24 4
      ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
  24. 24 4
      ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
  25. 24 4
      ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
  26. 24 4
      ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
  27. 24 4
      ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
  28. 24 4
      ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
  29. 15 4
      ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
  30. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
  31. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProviderTest.java
  32. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertHistoryResourceProviderTest.java
  33. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertNoticeResourceProviderTest.java
  34. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertResourceProviderTest.java
  35. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java
  36. 14 5
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java
  37. 3 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
  38. 3 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
  39. 118 11
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java
  40. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/JMXPropertyProviderTest.java
  41. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/ganglia/GangliaPropertyProviderTest.java
  42. 47 0
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperInitializer.java
  43. 100 9
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java
  44. 51 0
      ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
  45. 10 0
      ambari-server/src/test/java/org/apache/ambari/server/view/configuration/AutoInstanceConfigTest.java

+ 369 - 359
ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js

@@ -18,402 +18,412 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'Cluster', 'View', 'Alert', 'PermissionLoader', 'PermissionSaver', 'ConfirmationModal', '$location', 'UnsavedDialog', '$translate', function($scope, $routeParams, Cluster, View, Alert, PermissionLoader, PermissionSaver, ConfirmationModal, $location, UnsavedDialog, $translate) {
-  var $t = $translate.instant;
-  $scope.identity = angular.identity;
-  $scope.isConfigurationEmpty = true;
-  $scope.isSettingsEmpty = true;
-  $scope.constants = {
-    instance: $t('views.instance'),
-    props: $t('views.properties'),
-    perms: $t('views.permissions').toLowerCase()
-  };
-
-  function reloadViewInfo(section){
-    // Load instance data, after View permissions meta loaded
-    View.getInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId)
-    .then(function(instance) {
-      $scope.instance = instance;
-      $scope.settings = {
-        'visible': $scope.instance.ViewInstanceInfo.visible,
-        'label': $scope.instance.ViewInstanceInfo.label,
-        'description': $scope.instance.ViewInstanceInfo.description,
-        'shortUrl': $scope.instance.ViewInstanceInfo.short_url
-      };
-      switch (section) {
-        case "details" :
-          initConfigurations();
-          initCtrlVariables(instance);
-          break;
-        case "settings" :
-          initConfigurations(true);
-          break;
-        case "cluster" :
-          initCtrlVariables(instance);
-          break;
-      }
-    })
-    .catch(function(data) {
-      Alert.error($t('views.alerts.cannotLoadInstanceInfo'), data.data.message);
-    });
-  }
-
-  function initCtrlVariables(instance) {
-    if(instance.ViewInstanceInfo.cluster_handle) {
-      $scope.isLocalCluster = true;
-      $scope.cluster = instance.ViewInstanceInfo.cluster_handle;
-    }else{
-      $scope.isLocalCluster = false;
-      $scope.cluster = $scope.clusters.length > 0 ? $scope.clusters[0] : $t('common.noClusters');
-    }
-    $scope.originalLocalCluster = $scope.isLocalCluster;
-    $scope.isConfigurationEmpty = !$scope.numberOfClusterConfigs;
-    $scope.isSettingsEmpty = !$scope.numberOfSettingsConfigs;
-  }
-
-  function isClusterConfig(name) {
-    var configurationMeta = $scope.configurationMeta;
-    var clusterConfigs = configurationMeta.filter(function(el) {
-      return el.clusterConfig;
-    }).map(function(el) {
-      return el.name;
-    });
-    return clusterConfigs.indexOf(name) !== -1;
-  }
-
-  function initConfigurations(initClusterConfig) {
-    var initAllConfigs = !initClusterConfig;
-    var configuration = angular.copy($scope.instance.ViewInstanceInfo.properties);
-    if (initAllConfigs) {
-      $scope.configuration = angular.copy($scope.instance.ViewInstanceInfo.properties);
+  .controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'Cluster', 'View', 'Alert', 'PermissionLoader', 'PermissionSaver', 'ConfirmationModal', '$location', 'UnsavedDialog', '$translate', function($scope, $routeParams, Cluster, View, Alert, PermissionLoader, PermissionSaver, ConfirmationModal, $location, UnsavedDialog, $translate) {
+    var $t = $translate.instant;
+    $scope.identity = angular.identity;
+    $scope.isConfigurationEmpty = true;
+    $scope.isSettingsEmpty = true;
+    $scope.clusterInheritedPermissionKeys = View.clusterInheritedPermissionKeys;
+    $scope.constants = {
+      instance: $t('views.instance'),
+      props: $t('views.properties'),
+      perms: $t('views.permissions').toLowerCase()
+    };
+
+    function reloadViewInfo(section){
+      // Load instance data, after View permissions meta loaded
+      View.getInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId)
+        .then(function(instance) {
+          $scope.instance = instance;
+          $scope.settings = {
+            'visible': $scope.instance.ViewInstanceInfo.visible,
+            'label': $scope.instance.ViewInstanceInfo.label,
+            'description': $scope.instance.ViewInstanceInfo.description,
+            'shortUrl': $scope.instance.ViewInstanceInfo.short_url
+          };
+          switch (section) {
+            case "details" :
+              initConfigurations();
+              initCtrlVariables(instance);
+              break;
+            case "settings" :
+              initConfigurations(true);
+              break;
+            case "cluster" :
+              initCtrlVariables(instance);
+              break;
+          }
+        })
+        .catch(function(data) {
+          Alert.error($t('views.alerts.cannotLoadInstanceInfo'), data.data.message);
+        });
     }
-    for (var confName in configuration) {
-      if (configuration.hasOwnProperty(confName)) {
-        if (!isClusterConfig(confName) || initAllConfigs) {
-          $scope.configuration[confName] = configuration[confName] === 'null' ? '' : configuration[confName];
-        }
+
+    function initCtrlVariables(instance) {
+      if(instance.ViewInstanceInfo.cluster_handle) {
+        $scope.isLocalCluster = true;
+        $scope.cluster = instance.ViewInstanceInfo.cluster_handle;
+      }else{
+        $scope.isLocalCluster = false;
+        $scope.cluster = $scope.clusters.length > 0 ? $scope.clusters[0] : $t('common.noClusters');
       }
+      $scope.originalLocalCluster = $scope.isLocalCluster;
+      $scope.isConfigurationEmpty = !$scope.numberOfClusterConfigs;
+      $scope.isSettingsEmpty = !$scope.numberOfSettingsConfigs;
     }
-  }
 
-  function filterClusterConfigs() {
-    $scope.configurationMeta.forEach(function (element) {
-      if (element.masked && !$scope.editConfigurationDisabled && element.clusterConfig && !$scope.isLocalCluster) {
-        $scope.configuration[element.name] = '';
-      }
-      if(!element.clusterConfig) {
-        delete $scope.configurationBeforeEdit[element.name];
+    function isClusterConfig(name) {
+      var configurationMeta = $scope.configurationMeta;
+      var clusterConfigs = configurationMeta.filter(function(el) {
+        return el.clusterConfig;
+      }).map(function(el) {
+        return el.name;
+      });
+      return clusterConfigs.indexOf(name) !== -1;
+    }
+
+    function initConfigurations(initClusterConfig) {
+      var initAllConfigs = !initClusterConfig;
+      var configuration = angular.copy($scope.instance.ViewInstanceInfo.properties);
+      if (initAllConfigs) {
+        $scope.configuration = angular.copy($scope.instance.ViewInstanceInfo.properties);
       }
-    });
-  }
-
-  // Get META for properties
-  View.getMeta($routeParams.viewId, $routeParams.version).then(function(data) {
-    $scope.configurationMeta = data.data.ViewVersionInfo.parameters;
-    $scope.clusterConfigurable = data.data.ViewVersionInfo.cluster_configurable;
-    $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : $t('views.alerts.cannotUseOption');
-    angular.forEach($scope.configurationMeta, function (item) {
-      item.displayName = item.name.replace(/\./g, '\.\u200B');
-      item.clusterConfig = !!item.clusterConfig;
-      if (!item.clusterConfig) {
-        $scope.numberOfSettingsConfigs++;
+      for (var confName in configuration) {
+        if (configuration.hasOwnProperty(confName)) {
+          if (!isClusterConfig(confName) || initAllConfigs) {
+            $scope.configuration[confName] = configuration[confName] === 'null' ? '' : configuration[confName];
+          }
+        }
       }
-      $scope.numberOfClusterConfigs = $scope.numberOfClusterConfigs + !!item.clusterConfig;
-    });
-    reloadViewInfo("details");
-  });
-
-  function reloadViewPrivileges(){
-    PermissionLoader.getViewPermissions({
-      viewName: $routeParams.viewId,
-      version: $routeParams.version,
-      instanceId: $routeParams.instanceId
-    })
-    .then(function(permissions) {
-      // Refresh data for rendering
-      $scope.permissionsEdit = permissions;
-      $scope.permissions = angular.copy(permissions);
-      $scope.isPermissionsEmpty = angular.equals({}, $scope.permissions);
-    })
-    .catch(function(data) {
-      Alert.error($t('views.alerts.cannotLoadPermissions'), data.data.message);
-    });
-  }
+    }
 
-  $scope.permissions = [];
+    function filterClusterConfigs() {
+      $scope.configurationMeta.forEach(function (element) {
+        if (element.masked && !$scope.editConfigurationDisabled && element.clusterConfig && !$scope.isLocalCluster) {
+          $scope.configuration[element.name] = '';
+        }
+        if(!element.clusterConfig) {
+          delete $scope.configurationBeforeEdit[element.name];
+        }
+      });
+    }
 
-  reloadViewPrivileges();
+    // Get META for properties
+    View.getMeta($routeParams.viewId, $routeParams.version).then(function(data) {
+      $scope.configurationMeta = data.data.ViewVersionInfo.parameters;
+      $scope.clusterConfigurable = data.data.ViewVersionInfo.cluster_configurable;
+      $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : $t('views.alerts.cannotUseOption');
+      angular.forEach($scope.configurationMeta, function (item) {
+        item.displayName = item.name.replace(/\./g, '\.\u200B');
+        item.clusterConfig = !!item.clusterConfig;
+        if (!item.clusterConfig) {
+          $scope.numberOfSettingsConfigs++;
+        }
+        $scope.numberOfClusterConfigs = $scope.numberOfClusterConfigs + !!item.clusterConfig;
+      });
+      reloadViewInfo("details");
+    });
 
-  $scope.clusterConfigurable = false;
-  $scope.clusterConfigurableErrorMsg = "";
-  $scope.clusters = [];
-  $scope.cluster = null;
-  $scope.noClusterAvailible = true;
+    function reloadViewPrivileges(){
+      PermissionLoader.getViewPermissions({
+          viewName: $routeParams.viewId,
+          version: $routeParams.version,
+          instanceId: $routeParams.instanceId
+        })
+        .then(function(permissions) {
+          // Refresh data for rendering
+          $scope.permissionsEdit = permissions;
+          $scope.permissions = angular.copy(permissions);
+          $scope.isPermissionsEmpty = angular.equals({}, $scope.permissions);
+        })
+        .catch(function(data) {
+          Alert.error($t('views.alerts.cannotLoadPermissions'), data.data.message);
+        });
+    }
 
+    $scope.permissions = [];
 
-  $scope.editSettingsDisabled = true;
-  $scope.editDetailsSettingsDisabled = true;
-  $scope.numberOfClusterConfigs = 0;
-  $scope.numberOfSettingsConfigs = 0;
+    reloadViewPrivileges();
 
-  $scope.enableLocalCluster = function() {
-    angular.extend($scope.configuration, $scope.configurationBeforeEdit);
-    $scope.propertiesForm.$setPristine();
-  };
+    $scope.clusterConfigurable = false;
+    $scope.clusterConfigurableErrorMsg = "";
+    $scope.clusters = [];
+    $scope.cluster = null;
+    $scope.noClusterAvailible = true;
 
-  $scope.disableLocalCluster = function() {
-    filterClusterConfigs();
-  };
 
-  $scope.toggleSettingsEdit = function() {
-    $scope.editSettingsDisabled = !$scope.editSettingsDisabled;
-    $scope.settingsBeforeEdit = angular.copy($scope.configuration);
-    $scope.configurationMeta.forEach(function (element) {
-      if (element.masked && !$scope.editSettingsDisabled && !element.clusterConfig) {
-        $scope.configuration[element.name] = '';
-      }
-      if(element.clusterConfig) {
-        delete $scope.settingsBeforeEdit[element.name];
-      }
-    });
-  };
-
-  $scope.toggleDetailsSettingsEdit = function() {
-    $scope.editDetailsSettingsDisabled = !$scope.editDetailsSettingsDisabled;
-    $scope.settingsBeforeEdit = angular.copy($scope.configuration);
-    $scope.configurationMeta.forEach(function (element) {
-      if (element.masked && !$scope.editDetailsSettingsDisabled && !element.clusterConfig) {
-        $scope.configuration[element.name] = '';
-      }
-      if(element.clusterConfig) {
-        delete $scope.settingsBeforeEdit[element.name];
-      }
-    });
-  };
+    $scope.editSettingsDisabled = true;
+    $scope.editDetailsSettingsDisabled = true;
+    $scope.numberOfClusterConfigs = 0;
+    $scope.numberOfSettingsConfigs = 0;
 
-  Cluster.getAllClusters().then(function (clusters) {
-    if(clusters.length >0){
-      clusters.forEach(function(cluster) {
-        $scope.clusters.push(cluster.Clusters.cluster_name)
-      });
-      $scope.noClusterAvailible = false;
-    }else{
-      $scope.clusters.push($t('common.noClusters'));
-    }
-    $scope.cluster = $scope.clusters[0];
-  });
+    $scope.enableLocalCluster = function() {
+      angular.extend($scope.configuration, $scope.configurationBeforeEdit);
+      $scope.propertiesForm.$setPristine();
+    };
 
+    $scope.disableLocalCluster = function() {
+      filterClusterConfigs();
+    };
 
-  $scope.saveSettings = function(callback) {
-    if( $scope.settingsForm.$valid ){
-      var data = {
-        'ViewInstanceInfo':{
-          'properties':{}
-        }
-      };
+    $scope.toggleSettingsEdit = function() {
+      $scope.editSettingsDisabled = !$scope.editSettingsDisabled;
+      $scope.settingsBeforeEdit = angular.copy($scope.configuration);
       $scope.configurationMeta.forEach(function (element) {
-        if(!element.clusterConfig) {
-          data.ViewInstanceInfo.properties[element.name] = $scope.configuration[element.name];
+        if (element.masked && !$scope.editSettingsDisabled && !element.clusterConfig) {
+          $scope.configuration[element.name] = '';
         }
-      });
-      return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data)
-      .success(function() {
-        if( callback ){
-          callback();
-        } else {
-          reloadViewInfo("settings");
-          $scope.editSettingsDisabled = true;
-          $scope.settingsForm.$setPristine();
+        if(element.clusterConfig) {
+          delete $scope.settingsBeforeEdit[element.name];
         }
-      })
-      .catch(function(data) {
-        Alert.error($t('views.alerts.cannotSaveSettings'), data.data.message);
       });
-    }
-  };
-  $scope.cancelSettings = function() {
-    angular.extend($scope.configuration, $scope.settingsBeforeEdit);
+    };
 
-    $scope.editSettingsDisabled = true;
-    $scope.settingsForm.$setPristine();
-  };
-
-  $scope.saveDetails = function(callback) {
-    if( $scope.detailsForm.$valid ){
-      var data = {
-        'ViewInstanceInfo':{
-          'visible': $scope.settings.visible,
-          'label': $scope.settings.label,
-          'description': $scope.settings.description
+    $scope.toggleDetailsSettingsEdit = function() {
+      $scope.editDetailsSettingsDisabled = !$scope.editDetailsSettingsDisabled;
+      $scope.settingsBeforeEdit = angular.copy($scope.configuration);
+      $scope.configurationMeta.forEach(function (element) {
+        if (element.masked && !$scope.editDetailsSettingsDisabled && !element.clusterConfig) {
+          $scope.configuration[element.name] = '';
         }
-      };
-      return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data)
-      .success(function() {
-        $scope.$root.$emit('instancesUpdate');
-        if( callback ){
-          callback();
-        } else {
-          reloadViewInfo("cluster");
-          $scope.editDetailsSettingsDisabled = true;
-          $scope.settingsForm.$setPristine();
+        if(element.clusterConfig) {
+          delete $scope.settingsBeforeEdit[element.name];
         }
-      })
-      .catch(function(data) {
-        Alert.error($t('views.alerts.cannotSaveSettings'), data.data.message);
       });
-    }
-  };
-  $scope.cancelDetails = function() {
-    $scope.settings = {
-      'visible': $scope.instance.ViewInstanceInfo.visible,
-      'label': $scope.instance.ViewInstanceInfo.label,
-      'description': $scope.instance.ViewInstanceInfo.description,
-      'shortUrl': $scope.instance.ViewInstanceInfo.short_url
     };
-    $scope.editDetailsSettingsDisabled = true;
-    $scope.settingsForm.$setPristine();
-  };
-
-
-  $scope.editConfigurationDisabled = true;
-  $scope.togglePropertiesEditing = function () {
-    $scope.editConfigurationDisabled = !$scope.editConfigurationDisabled;
-    $scope.configurationBeforeEdit = angular.copy($scope.configuration);
-    filterClusterConfigs();
-  };
-  $scope.saveConfiguration = function() {
-    if( $scope.propertiesForm.$valid ){
-      var data = {
-        'ViewInstanceInfo':{
-          'properties':{}
-        }
-      };
-      if($scope.isLocalCluster) {
-        data.ViewInstanceInfo.cluster_handle = $scope.cluster;
-      } else {
-        data.ViewInstanceInfo.cluster_handle = null;
+
+    Cluster.getAllClusters().then(function (clusters) {
+      if(clusters.length >0){
+        clusters.forEach(function(cluster) {
+          $scope.clusters.push(cluster.Clusters.cluster_name)
+        });
+        $scope.noClusterAvailible = false;
+      }else{
+        $scope.clusters.push($t('common.noClusters'));
+      }
+      $scope.cluster = $scope.clusters[0];
+    });
+
+
+    $scope.saveSettings = function(callback) {
+      if( $scope.settingsForm.$valid ){
+        var data = {
+          'ViewInstanceInfo':{
+            'properties':{}
+          }
+        };
         $scope.configurationMeta.forEach(function (element) {
-          if(element.clusterConfig) {
+          if(!element.clusterConfig) {
             data.ViewInstanceInfo.properties[element.name] = $scope.configuration[element.name];
           }
         });
+        return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data)
+          .success(function() {
+            if( callback ){
+              callback();
+            } else {
+              reloadViewInfo("settings");
+              $scope.editSettingsDisabled = true;
+              $scope.settingsForm.$setPristine();
+            }
+          })
+          .catch(function(data) {
+            Alert.error($t('views.alerts.cannotSaveSettings'), data.data.message);
+          });
       }
-      $scope.originalLocalCluster = $scope.isLocalCluster;
-      return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data)
-      .success(function() {
-        $scope.editConfigurationDisabled = true;
-        $scope.propertiesForm.$setPristine();
-      })
-      .catch(function(data) {
-        var errorMessage = data.data.message;
-
-        //TODO: maybe the BackEnd should sanitize the string beforehand?
-        errorMessage = errorMessage.substr(errorMessage.indexOf("\{"));
-
-        if (data.status >= 400 && !$scope.isLocalCluster) {
-          try {
-            var errorObject = JSON.parse(errorMessage);
-            errorMessage = errorObject.detail;
-            angular.forEach(errorObject.propertyResults, function (item, key) {
-              $scope.propertiesForm[key].validationError = !item.valid;
-              if (!item.valid) {
-                $scope.propertiesForm[key].validationMessage = item.detail;
-              }
-            });
-          } catch (e) {
-            console.error($t('views.alerts.unableToParseError', {message: data.message}));
+    };
+    $scope.cancelSettings = function() {
+      angular.extend($scope.configuration, $scope.settingsBeforeEdit);
+
+      $scope.editSettingsDisabled = true;
+      $scope.settingsForm.$setPristine();
+    };
+
+    $scope.saveDetails = function(callback) {
+      if( $scope.detailsForm.$valid ){
+        var data = {
+          'ViewInstanceInfo':{
+            'visible': $scope.settings.visible,
+            'label': $scope.settings.label,
+            'description': $scope.settings.description
           }
-        }
-        Alert.error($t('views.alerts.cannotSaveProperties'), errorMessage);
-      });
-    }
-  };
-  $scope.cancelConfiguration = function() {
-    angular.extend($scope.configuration, $scope.configurationBeforeEdit);
-    $scope.isLocalCluster = $scope.originalLocalCluster;
+        };
+        return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data)
+          .success(function() {
+            $scope.$root.$emit('instancesUpdate');
+            if( callback ){
+              callback();
+            } else {
+              reloadViewInfo("cluster");
+              $scope.editDetailsSettingsDisabled = true;
+              $scope.settingsForm.$setPristine();
+            }
+          })
+          .catch(function(data) {
+            Alert.error($t('views.alerts.cannotSaveSettings'), data.data.message);
+          });
+      }
+    };
+    $scope.cancelDetails = function() {
+      $scope.settings = {
+        'visible': $scope.instance.ViewInstanceInfo.visible,
+        'label': $scope.instance.ViewInstanceInfo.label,
+        'description': $scope.instance.ViewInstanceInfo.description,
+        'shortUrl': $scope.instance.ViewInstanceInfo.short_url
+      };
+      $scope.editDetailsSettingsDisabled = true;
+      $scope.settingsForm.$setPristine();
+    };
+
+
     $scope.editConfigurationDisabled = true;
-    $scope.propertiesForm.$setPristine();
-  };
+    $scope.togglePropertiesEditing = function () {
+      $scope.editConfigurationDisabled = !$scope.editConfigurationDisabled;
+      $scope.configurationBeforeEdit = angular.copy($scope.configuration);
+      filterClusterConfigs();
+    };
+    $scope.saveConfiguration = function() {
+      if( $scope.propertiesForm.$valid ){
+        var data = {
+          'ViewInstanceInfo':{
+            'properties':{}
+          }
+        };
+        if($scope.isLocalCluster) {
+          data.ViewInstanceInfo.cluster_handle = $scope.cluster;
+        } else {
+          data.ViewInstanceInfo.cluster_handle = null;
+          $scope.configurationMeta.forEach(function (element) {
+            if(element.clusterConfig) {
+              data.ViewInstanceInfo.properties[element.name] = $scope.configuration[element.name];
+            }
+          });
+          $scope.clearClusterInheritedPermissions();
+        }
+        $scope.originalLocalCluster = $scope.isLocalCluster;
+        return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data)
+          .success(function() {
+            $scope.editConfigurationDisabled = true;
+            $scope.propertiesForm.$setPristine();
+          })
+          .catch(function(data) {
+            var errorMessage = data.data.message;
 
-  // Permissions edit
-  $scope.editPermissionDisabled = true;
-  $scope.cancelPermissions = function() {
-    $scope.permissionsEdit = angular.copy($scope.permissions); // Reset textedit areaes
-    $scope.editPermissionDisabled = true;
-  };
+            //TODO: maybe the BackEnd should sanitize the string beforehand?
+            errorMessage = errorMessage.substr(errorMessage.indexOf("\{"));
 
-  $scope.savePermissions = function() {
-    $scope.editPermissionDisabled = true;
-    return PermissionSaver.saveViewPermissions(
-      $scope.permissionsEdit,
-      {
-        view_name: $routeParams.viewId,
-        version: $routeParams.version,
-        instance_name: $routeParams.instanceId
+            if (data.status >= 400 && !$scope.isLocalCluster) {
+              try {
+                var errorObject = JSON.parse(errorMessage);
+                errorMessage = errorObject.detail;
+                angular.forEach(errorObject.propertyResults, function (item, key) {
+                  $scope.propertiesForm[key].validationError = !item.valid;
+                  if (!item.valid) {
+                    $scope.propertiesForm[key].validationMessage = item.detail;
+                  }
+                });
+              } catch (e) {
+                console.error($t('views.alerts.unableToParseError', {message: data.message}));
+              }
+            }
+            Alert.error($t('views.alerts.cannotSaveProperties'), errorMessage);
+          });
       }
-    )
-    .then(reloadViewPrivileges)
-    .catch(function(data) {
-      reloadViewPrivileges();
-      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
-    });
-  };
+    };
+    $scope.cancelConfiguration = function() {
+      angular.extend($scope.configuration, $scope.configurationBeforeEdit);
+      $scope.isLocalCluster = $scope.originalLocalCluster;
+      $scope.editConfigurationDisabled = true;
+      $scope.propertiesForm.$setPristine();
+    };
 
-  $scope.$watch(function() {
-    return $scope.permissionsEdit;
-  }, function(newValue) {
-    if(newValue){
-      $scope.savePermissions();
-    }
-  }, true);
-
-  $scope.deleteInstance = function(instance) {
-    ConfirmationModal.show(
-      $t('common.delete', {
-        term: $t('views.viewInstance')
-      }),
-      $t('common.deleteConfirmation', {
-        instanceType: $t('views.viewInstance'),
-        instanceName: instance.ViewInstanceInfo.label
-      })
-    ).then(function() {
-      View.deleteInstance(instance.ViewInstanceInfo.view_name, instance.ViewInstanceInfo.version, instance.ViewInstanceInfo.instance_name)
-      .then(function() {
-        $location.path('/views');
+    // Permissions edit
+    $scope.editPermissionDisabled = true;
+    $scope.cancelPermissions = function() {
+      $scope.permissionsEdit = angular.copy($scope.permissions); // Reset textedit areaes
+      $scope.editPermissionDisabled = true;
+    };
+
+    $scope.savePermissions = function() {
+      $scope.editPermissionDisabled = true;
+      return PermissionSaver.saveViewPermissions(
+        $scope.permissionsEdit,
+        {
+          view_name: $routeParams.viewId,
+          version: $routeParams.version,
+          instance_name: $routeParams.instanceId
+        }
+        )
+        .then(reloadViewPrivileges)
+        .catch(function(data) {
+          reloadViewPrivileges();
+          Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+        });
+    };
+
+    $scope.clearClusterInheritedPermissions = function() {
+      angular.forEach(View.clusterInheritedPermissionKeys, function(key) {
+        $scope.permissionsEdit["VIEW.USER"][key] = false;
       })
-      .catch(function(data) {
-        Alert.error($t('views.alerts.cannotDeleteInstance'), data.data.message);
+    };
+
+    $scope.$watch(function() {
+      return $scope.permissionsEdit;
+    }, function(newValue, oldValue) {
+      if(newValue && oldValue != undefined) {
+        $scope.savePermissions();
+      }
+    }, true);
+    
+    
+
+    $scope.deleteInstance = function(instance) {
+      ConfirmationModal.show(
+        $t('common.delete', {
+          term: $t('views.viewInstance')
+        }),
+        $t('common.deleteConfirmation', {
+          instanceType: $t('views.viewInstance'),
+          instanceName: instance.ViewInstanceInfo.label
+        })
+      ).then(function() {
+        View.deleteInstance(instance.ViewInstanceInfo.view_name, instance.ViewInstanceInfo.version, instance.ViewInstanceInfo.instance_name)
+          .then(function() {
+            $location.path('/views');
+          })
+          .catch(function(data) {
+            Alert.error($t('views.alerts.cannotDeleteInstance'), data.data.message);
+          });
       });
-    });
-  };
-
-  $scope.$on('$locationChangeStart', function(event, targetUrl) {
-    if( $scope.settingsForm.$dirty || $scope.propertiesForm.$dirty){
-      UnsavedDialog().then(function(action) {
-        targetUrl = targetUrl.split('#').pop();
-        switch(action){
-          case 'save':
-            if($scope.settingsForm.$valid &&  $scope.propertiesForm.$valid ){
-              $scope.saveSettings(function() {
-                $scope.saveConfiguration().then(function() {
-                  $scope.propertiesForm.$setPristine();
-                  $scope.settingsForm.$setPristine();
-                  $location.path(targetUrl);
+    };
+
+    $scope.$on('$locationChangeStart', function(event, targetUrl) {
+      if( $scope.settingsForm.$dirty || $scope.propertiesForm.$dirty){
+        UnsavedDialog().then(function(action) {
+          targetUrl = targetUrl.split('#').pop();
+          switch(action){
+            case 'save':
+              if($scope.settingsForm.$valid &&  $scope.propertiesForm.$valid ){
+                $scope.saveSettings(function() {
+                  $scope.saveConfiguration().then(function() {
+                    $scope.propertiesForm.$setPristine();
+                    $scope.settingsForm.$setPristine();
+                    $location.path(targetUrl);
+                  });
                 });
-              });
-            }
-            break;
-          case 'discard':
-            $scope.propertiesForm.$setPristine();
-            $scope.settingsForm.$setPristine();
-            $location.path(targetUrl);
-            break;
-          case 'cancel':
-            targetUrl = '';
-            break;
-        }
-      });
-      event.preventDefault();
-    }
-  });
-}]);
+              }
+              break;
+            case 'discard':
+              $scope.propertiesForm.$setPristine();
+              $scope.settingsForm.$setPristine();
+              $location.path(targetUrl);
+              break;
+            case 'cancel':
+              targetUrl = '';
+              break;
+          }
+        });
+        event.preventDefault();
+      }
+    });
+  }]);

+ 9 - 0
ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js

@@ -209,6 +209,15 @@ angular.module('ambariAdminConsole')
       'urlCreate':'Create new URL',
       'urlDelete':'Delete URL',
 
+      'clusterPermissions': {
+        'label': 'Inherit Cluster Permission',
+        'allclusteradministrator': 'All Cluster Administrator',
+        'allclusteroperator': 'All Cluster Operator',
+        'allclusteruser': 'All Cluster User',
+        'allserviceadministrator': 'All Service Administrator',
+        'allserviceoperator': 'All Service Operator'
+      },
+
       'alerts': {
         'noSpecialChars': 'Must not contain any special characters.',
         'noSpecialCharsOrSpaces': 'Must not contain any special characters or spaces.',

+ 5 - 7
ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js

@@ -181,13 +181,11 @@ angular.module('ambariAdminConsole')
   };
 
   Group.getPrivileges = function(groupId) {
-    return $http.get(Settings.baseUrl + '/privileges', {
-        params:{
-          'PrivilegeInfo/principal_type': 'GROUP',
-          'PrivilegeInfo/principal_name': groupId,
-          'fields': '*'
-        }
-      });
+    return $http.get(Settings.baseUrl + '/groups/' + groupId + '/privileges', {
+      params:{
+        'fields': '*'
+      }
+    });
   };
 
   return Group;

+ 9 - 1
ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js

@@ -22,18 +22,26 @@ angular.module('ambariAdminConsole')
   
   function getPermissionsFor(resource, params){
     var deferred = $q.defer();
+
     resource.getPermissions(params).then(function(permissions) {
       var permissionsInner = {}; // Save object into closure, until it completely fills to prevent blinkong
       angular.forEach(permissions, function(permission) {
         permission.GROUP = [];
         permission.USER = [];
+        angular.forEach(View.clusterInheritedPermissionKeys, function(key) {
+          permission[key] = false;
+        });
         permissionsInner[permission.PermissionInfo.permission_name] = permission;
       });
 
       // Now we can get privileges
       resource.getPrivileges(params).then(function(privileges) {
         angular.forEach(privileges, function(privilege) {
-          permissionsInner[privilege.PrivilegeInfo.permission_name][privilege.PrivilegeInfo.principal_type].push(privilege.PrivilegeInfo.principal_name);
+          if(!privilege.PrivilegeInfo.principal_type.startsWith("ALL.")) {
+            permissionsInner[privilege.PrivilegeInfo.permission_name][privilege.PrivilegeInfo.principal_type].push(privilege.PrivilegeInfo.principal_name);
+          } else {
+            permissionsInner[privilege.PrivilegeInfo.permission_name][privilege.PrivilegeInfo.principal_type] = true;
+          }
         });
 
         // After all builded - return object

+ 14 - 2
ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js

@@ -23,7 +23,6 @@ angular.module('ambariAdminConsole')
 
   function savePermissionsFor(resource, permissions, params){
     var arr = [];
-
     angular.forEach(permissions, function(permission) {
       // Sanitaize input
       var users = permission.USER.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
@@ -48,6 +47,19 @@ angular.module('ambariAdminConsole')
           }
         }
       }));
+
+      angular.forEach(View.clusterInheritedPermissionKeys, function(key) {
+        if(permission[key] === true) {
+          arr.push({
+            'PrivilegeInfo': {
+              'permission_name': 'VIEW.USER',
+              'principal_name': '*',
+              'principal_type': key
+            }
+          });
+        }
+      });
+
     });
     if (!passOneRoleCheck(arr)) {
       console.log("CHECK FAILED");
@@ -143,7 +155,7 @@ angular.module('ambariAdminConsole')
     var hash = {};
     for(var i = 0; i < arr.length; i++) {
       var obj = arr[i];
-      if (hash[obj.PrivilegeInfo.principal_name]) {
+      if (hash[obj.PrivilegeInfo.principal_name] && obj.PrivilegeInfo.principal_name !== "*") {
         return false;
       } else {
         hash[obj.PrivilegeInfo.principal_name] = true;

+ 8 - 0
ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js

@@ -190,6 +190,14 @@ angular.module('ambariAdminConsole')
     self.versionsList = item.versions;
   }
 
+  View.clusterInheritedPermissionKeys = [
+    "ALL.CLUSTER.ADMINISTRATOR",
+    "ALL.CLUSTER.OPERATOR",
+    "ALL.CLUSTER.USER",
+    "ALL.SERVICE.OPERATOR",
+    "ALL.SERVICE.ADMINISTRATOR"
+  ];
+
   View.getInstance = function(viewName, version, instanceName) {
     return ViewInstance.find(viewName, version, instanceName);
   };

+ 6 - 0
ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css

@@ -1652,4 +1652,10 @@ thead.view-permission-header > tr > th {
 
 .role-details-modal .table-head .table-cell:last-of-type {
   visibility: hidden;
+}
+
+.cluster-inherited-permission {
+    border-bottom: 2px solid #ddd;
+    padding-bottom: 10px;
+    margin-top: 5px;
 }

+ 50 - 35
ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html

@@ -107,41 +107,6 @@
   </div>
 </div>
 
-<div class="panel panel-default views-permissions-panel" style="">
-  <div class="panel-heading clearfix">
-    <h3 class="panel-title pull-left">{{'views.permissions' | translate}}</h3>
-  </div>
-  <div class="panel-body">
-
-
-    <table class="table" ng-show="!isPermissionsEmpty">
-      <thead>
-        <tr>
-          <th class="col-sm-2"><label>{{'views.permission' | translate}}</label></th>
-          <th><label>{{'views.grantUsers' | translate}}</label></th>
-          <th><label>{{'views.grantGroups' | translate}}</label></th>
-        </tr>
-      </thead>
-      <tbody>
-        <tr ng-repeat="permission in permissions">
-          <td>
-            <label class="" tooltip="{{permission.PermissionInfo.permission_name}}">{{permission.PermissionInfo.permission_name | translate}}</label>
-          </td>
-          <td>
-            <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" editable="true" resource-type="User"></editable-list>
-          </td>
-          <td>
-            <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" editable="true" resource-type="Group" ></editable-list>
-          </td>
-        </tr>
-      </tbody>
-    </table>
-    <div ng-show="isPermissionsEmpty">
-      <div class="alert alert-info">{{'views.alerts.notDefined' | translate: '{term: constants.perms}'}}</div>
-    </div>
-  </div>
-</div>
-
 <div class="panel panel-default" ng-cloak ng-hide="isSettingsEmpty && instance">
   <div class="panel-heading clearfix">
     <h3 class="panel-title pull-left">{{'views.settings' | translate}}</h3>
@@ -251,3 +216,53 @@
     </div>
   </div>
 </div>
+
+<div class="panel panel-default views-permissions-panel" style="">
+  <div class="panel-heading clearfix">
+    <h3 class="panel-title pull-left">{{'views.permissions' | translate}}</h3>
+  </div>
+  <div class="panel-body">
+
+
+    <table class="table" ng-show="!isPermissionsEmpty">
+      <thead>
+      <tr>
+        <th class="col-sm-2"><label>{{'views.permission' | translate}}</label></th>
+        <th><label>{{'views.grantUsers' | translate}}</label></th>
+        <th><label>{{'views.grantGroups' | translate}}</label></th>
+      </tr>
+      </thead>
+      <tbody>
+      <tr ng-repeat="permission in permissions">
+        <td>
+          <label class="" tooltip="{{permission.PermissionInfo.permission_name}}">{{permission.PermissionInfo.permission_name | translate}}</label>
+        </td>
+        <td>
+          <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" editable="true" resource-type="User"></editable-list>
+        </td>
+        <td>
+          <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" editable="true" resource-type="Group" ></editable-list>
+        </td>
+      </tr>
+      </tbody>
+    </table>
+    <div ng-show="!isPermissionsEmpty && isLocalCluster && editConfigurationDisabled">
+      <div class="col-sm-12 cluster-inherited-permission">
+        <strong>{{'views.clusterPermissions.label' | translate}}</strong>
+      </div>
+      <div class="col-sm-offset-3 col-sm-9">
+        <div class="checkbox col-sm-4" ng-repeat="key in clusterInheritedPermissionKeys">
+          <div ng-init="i18nKey = 'views.clusterPermissions.' + key.split('.').join('').toLowerCase()">
+            <label>
+              <input type="checkbox" ng-model="permissionsEdit['VIEW.USER'][key]"> {{i18nKey | translate}}
+            </label>
+          </div>
+        </div>
+      </div>
+
+    </div>
+    <div ng-show="isPermissionsEmpty">
+      <div class="alert alert-info">{{'views.alerts.notDefined' | translate: '{term: constants.perms}'}}</div>
+    </div>
+  </div>
+</div>

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

@@ -902,7 +902,7 @@ public class AmbariServer {
         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));
+        injector.getInstance(GroupDAO.class), injector.getInstance(ViewInstanceDAO.class), injector.getInstance(PrivilegeDAO.class));
     ClusterPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     AmbariPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     ActionManager.setTopologyManager(injector.getInstance(TopologyManager.class));

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

@@ -86,6 +86,7 @@ import org.apache.ambari.server.scheduler.ExecutionSchedulerImpl;
 import org.apache.ambari.server.security.AmbariEntryPoint;
 import org.apache.ambari.server.security.SecurityHelper;
 import org.apache.ambari.server.security.SecurityHelperImpl;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
 import org.apache.ambari.server.security.encryption.CredentialStoreServiceImpl;
 import org.apache.ambari.server.serveraction.kerberos.KerberosOperationHandlerFactory;
@@ -368,6 +369,7 @@ public class ControllerModule extends AbstractModule {
 
     requestStaticInjection(DatabaseChecker.class);
     requestStaticInjection(KerberosChecker.class);
+    requestStaticInjection(AuthorizationHelper.class);
 
     bindByAnnotation(null);
     bindNotificationDispatchers();

+ 17 - 7
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProvider.java

@@ -28,6 +28,7 @@ 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.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.GroupEntity;
@@ -35,10 +36,7 @@ import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
-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.security.authorization.*;
 
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -82,6 +80,12 @@ public class GroupPrivilegeResourceProvider extends ReadOnlyResourceProvider {
   @Inject
   protected static ViewInstanceDAO viewInstanceDAO;
 
+  /**
+   * Data access object used to obtain privilege entities.
+   */
+  @Inject
+  protected static PrivilegeDAO privilegeDAO;
+
   /**
    * The property ids for a privilege resource.
    */
@@ -103,16 +107,17 @@ public class GroupPrivilegeResourceProvider extends ReadOnlyResourceProvider {
 
   /**
    * Static initialization.
-   *
-   * @param clusterDAO      the cluster 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
+   * @param privilegeDAO
    */
   public static void init(ClusterDAO clusterDAO, GroupDAO groupDAO,
-                          ViewInstanceDAO viewInstanceDAO) {
+                          ViewInstanceDAO viewInstanceDAO, PrivilegeDAO privilegeDAO) {
     GroupPrivilegeResourceProvider.clusterDAO = clusterDAO;
     GroupPrivilegeResourceProvider.groupDAO = groupDAO;
     GroupPrivilegeResourceProvider.viewInstanceDAO = viewInstanceDAO;
+    GroupPrivilegeResourceProvider.privilegeDAO = privilegeDAO;
   }
 
   @SuppressWarnings("serial")
@@ -176,6 +181,11 @@ public class GroupPrivilegeResourceProvider extends ReadOnlyResourceProvider {
         }
 
         final Set<PrivilegeEntity> privileges = groupEntity.getPrincipal().getPrivileges();
+
+        Set<PrivilegeEntity> allViewPrivilegesWithClusterPermission =
+          ClusterInheritedPermissionHelper.getViewPrivilegesWithClusterPermission(viewInstanceDAO, privilegeDAO, privileges);
+        privileges.addAll(allViewPrivilegesWithClusterPermission);
+
         for (PrivilegeEntity privilegeEntity : privileges) {
           resources.add(toResource(privilegeEntity, groupName, requestedIds));
         }

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

@@ -51,6 +51,7 @@ 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.UserEntity;
+import org.apache.ambari.server.security.authorization.ClusterInheritedPermissionHelper;
 
 /**
  * Abstract resource provider for privilege resources.
@@ -348,6 +349,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractAuthorizedRes
       if (userEntity != null) {
         entity.setPrincipal(principalDAO.findById(userEntity.getPrincipal().getId()));
       }
+    } else if (ClusterInheritedPermissionHelper.isValidPrincipalType(principalType)) {
+      entity.setPrincipal(principalDAO.findByPrincipalType(principalType).get(0)); // There will be only one principal for that type
     } else {
       throw new AmbariException("Unknown principal type " + principalType);
     }

+ 28 - 9
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java

@@ -17,12 +17,8 @@
  */
 package org.apache.ambari.server.controller.internal;
 
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -32,6 +28,7 @@ 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.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
@@ -39,15 +36,24 @@ 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.ResourceEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ClusterInheritedPermissionHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.security.authorization.UserType;
 
+import javax.annotation.Nullable;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Resource provider for user privilege resources.
  */
@@ -85,6 +91,11 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
    */
   protected static ViewInstanceDAO viewInstanceDAO;
 
+  /**
+   * DAO used to obtain privilege entities.
+   */
+  protected static PrivilegeDAO privilegeDAO;
+
   /**
    * The property ids for a privilege resource.
    */
@@ -105,18 +116,19 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
 
   /**
    * Static initialization.
-   *
-   * @param userDAO         the user data access object
+   *  @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
+   * @param privilegeDAO
    */
   public static void init(UserDAO userDAO, ClusterDAO clusterDAO, GroupDAO groupDAO,
-                          ViewInstanceDAO viewInstanceDAO) {
+                          ViewInstanceDAO viewInstanceDAO, PrivilegeDAO privilegeDAO) {
     UserPrivilegeResourceProvider.userDAO         = userDAO;
     UserPrivilegeResourceProvider.clusterDAO      = clusterDAO;
     UserPrivilegeResourceProvider.groupDAO        = groupDAO;
     UserPrivilegeResourceProvider.viewInstanceDAO = viewInstanceDAO;
+    UserPrivilegeResourceProvider.privilegeDAO    = privilegeDAO;
   }
 
   @SuppressWarnings("serial")
@@ -163,6 +175,7 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
     final Set<Resource> resources = new HashSet<Resource>();
     final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
 
+
     boolean isUserAdministrator = AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null,
         RoleAuthorization.AMBARI_MANAGE_USERS);
 
@@ -187,10 +200,15 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
         }
 
         final Set<PrivilegeEntity> privileges = userEntity.getPrincipal().getPrivileges();
+
         for (MemberEntity membership : userEntity.getMemberEntities()) {
           privileges.addAll(membership.getGroup().getPrincipal().getPrivileges());
         }
 
+        Set<PrivilegeEntity> allViewPrivilegesWithClusterPermission =
+          ClusterInheritedPermissionHelper.getViewPrivilegesWithClusterPermission(viewInstanceDAO, privilegeDAO, privileges);
+        privileges.addAll(allViewPrivilegesWithClusterPermission);
+
         for (PrivilegeEntity privilegeEntity : privileges) {
           resources.add(toResource(privilegeEntity, userName, requestedIds));
         }
@@ -199,6 +217,7 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
     return resources;
   }
 
+
   /**
    * Translate the found data into a Resource
    *

+ 8 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrincipalDAO.java

@@ -80,6 +80,14 @@ public class PrincipalDAO {
     return daoUtils.selectList(query);
   }
 
+
+  @RequiresSession
+  public List<PrincipalEntity> findByPrincipalType(String name) {
+    TypedQuery<PrincipalEntity> query = entityManagerProvider.get().createNamedQuery("principalByPrincipalType", PrincipalEntity.class);
+    query.setParameter("principal_type", name);
+    return  daoUtils.selectList(query);
+  }
+
   /**
    * Make an instance managed and persistent.
    *

+ 2 - 1
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalEntity.java

@@ -47,7 +47,8 @@ import javax.persistence.TableGenerator;
     , allocationSize = 500
 )
 @NamedQueries({
-  @NamedQuery(name = "principalByPrivilegeId", query = "SELECT principal FROM PrincipalEntity principal JOIN principal.privileges privilege WHERE privilege.permission.id=:permission_id")
+  @NamedQuery(name = "principalByPrivilegeId", query = "SELECT principal FROM PrincipalEntity principal JOIN principal.privileges privilege WHERE privilege.permission.id=:permission_id"),
+  @NamedQuery(name = "principalByPrincipalType", query = "SELECT principal FROM PrincipalEntity principal WHERE principal.principalType.name = :principal_type")
 })
 public class PrincipalEntity {
 

+ 10 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PrincipalTypeEntity.java

@@ -37,9 +37,19 @@ public class PrincipalTypeEntity {
    */
   public static final int USER_PRINCIPAL_TYPE  = 1;
   public static final int GROUP_PRINCIPAL_TYPE = 2;
+  public static final int CLUSTER_ADMINISTRATOR_PRINCIPAL_TYPE = 3;
+  public static final int CLUSTER_OPERATOR_PRINCIPAL_TYPE = 4;
+  public static final int CLUSTER_USER_PRINCIPAL_TYPE = 5;
+  public static final int SERVICE_ADMINISTRATOR_PRINCIPAL_TYPE = 6;
+  public static final int SERVICE_OPERATOR_PRINCIPAL_TYPE = 7;
 
   public static final String USER_PRINCIPAL_TYPE_NAME  = "USER";
   public static final String GROUP_PRINCIPAL_TYPE_NAME = "GROUP";
+  public static final String CLUSTER_ADMINISTRATOR_PRINCIPAL_TYPE_NAME = "ALL.CLUSTER.ADMINISTRATOR";
+  public static final String CLUSTER_OPERATOR_PRINCIPAL_TYPE_NAME = "ALL.CLUSTER.OPERATOR";
+  public static final String CLUSTER_USER_PRINCIPAL_TYPE_NAME = "ALL.CLUSTER.USER";
+  public static final String SERVICE_ADMINISTRATOR_PRINCIPAL_TYPE_NAME = "ALL.SERVICE.ADMINISTRATOR";
+  public static final String SERVICE_OPERATOR_PRINCIPAL_TYPE_NAME = "ALL.SERVICE.OPERATOR";
 
   /**
    * The type id.

+ 67 - 6
ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java

@@ -17,17 +17,20 @@
  */
 package org.apache.ambari.server.security.authorization;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 import com.google.inject.Singleton;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 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.RoleAuthorizationEntity;
-import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.Authentication;
@@ -38,7 +41,11 @@ import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 @Singleton
 /**
@@ -47,6 +54,12 @@ import java.util.*;
 public class AuthorizationHelper {
   private final static Logger LOG = LoggerFactory.getLogger(AuthorizationHelper.class);
 
+  @Inject
+  static Provider<PrivilegeDAO> privilegeDAOProvider;
+
+  @Inject
+  static Provider<ViewInstanceDAO> viewInstanceDAOProvider;
+
   /**
    * Converts collection of RoleEntities to collection of GrantedAuthorities
    */
@@ -197,8 +210,56 @@ public class AuthorizationHelper {
         }
       }
 
-      return false;
+      // Check if the resourceId is a view.
+      // Get all privileges for the resourceId and the principal associated for them should be of all cluster/service
+      // type.
+      // Now from the authorities check if the user privileges with CLUSTER/SERVICE type permission and has access to
+      // cluster resource with the permission.
+      // Then if the permission type matches the cluster/service type principal(names) then the user should have access
+      // to those views.
+
+      if(resourceId == null) {
+        return false;
+      }
+
+      ViewInstanceDAO viewInstanceDAO = viewInstanceDAOProvider.get();
+
+      ViewInstanceEntity instanceEntity = viewInstanceDAO.findByResourceId(resourceId);
+      if(instanceEntity == null || instanceEntity.getClusterHandle() == null) {
+        return false;
+      }
+
+      PrivilegeDAO privilegeDAO = privilegeDAOProvider.get();
+
+      final Set<String> privilegeNames = FluentIterable.from(privilegeDAO.findByResourceId(resourceId))
+        .filter(ClusterInheritedPermissionHelper.privilegeWithClusterInheritedPermissionTypePredicate)
+        .transform(ClusterInheritedPermissionHelper.permissionNameFromClusterInheritedPrivilege)
+        .toSet();
+
+      return FluentIterable.from(authentication.getAuthorities())
+        .filter(new Predicate<GrantedAuthority>() {
+          @Override
+          public boolean apply(GrantedAuthority grantedAuthority) {
+            AmbariGrantedAuthority authority = (AmbariGrantedAuthority) grantedAuthority;
+            PrivilegeEntity privilege = authority.getPrivilegeEntity();
+            String resourceTypeName = privilege.getResource().getResourceType().getName();
+            return ResourceType.translate(resourceTypeName) == ResourceType.CLUSTER;
+          }
+        }).transform(new Function<GrantedAuthority, PermissionEntity>() {
+          @Override
+          public PermissionEntity apply(GrantedAuthority grantedAuthority) {
+            AmbariGrantedAuthority authority = (AmbariGrantedAuthority) grantedAuthority;
+            PrivilegeEntity privilege = authority.getPrivilegeEntity();
+            return privilege.getPermission();
+          }
+        }).anyMatch(new Predicate<PermissionEntity>() {
+          @Override
+          public boolean apply(PermissionEntity input) {
+            return privilegeNames.contains(input.getPermissionName());
+          }
+        });
     }
+
   }
 
   /**

+ 213 - 0
ambari-server/src/main/java/org/apache/ambari/server/security/authorization/ClusterInheritedPermissionHelper.java

@@ -0,0 +1,213 @@
+/*
+ * 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.security.authorization;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+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.ViewInstanceEntity;
+
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.Set;
+
+
+/**
+ * Helper class to take care of the cluster inherited permission for any view.
+ */
+public class ClusterInheritedPermissionHelper {
+
+  /**
+   * Predicate which validates if the principalType passed is valid or not.
+   */
+  public static final Predicate<String> validPrincipalTypePredicate = new Predicate<String>() {
+    @Override
+    public boolean apply(String principalType) {
+      return isValidPrincipalType(principalType);
+    }
+  };
+
+  /**
+   * Predicate which validates if the privilegeEntity has resourceEntity of type {@see ResourceType.CLUSTER}
+   */
+  public static final Predicate<PrivilegeEntity> clusterPrivilegesPredicate = new Predicate<PrivilegeEntity>() {
+    @Override
+    public boolean apply(PrivilegeEntity privilegeEntity) {
+      String resourceTypeName = privilegeEntity.getResource().getResourceType().getName();
+      return ResourceType.translate(resourceTypeName) == ResourceType.CLUSTER;
+    }
+  };
+
+  /**
+   * Predicate which validates if view instance entity is cluster associated
+   */
+  public static final Predicate<ViewInstanceEntity> clusterAssociatedViewInstancePredicate = new Predicate<ViewInstanceEntity>() {
+    @Override
+    public boolean apply(ViewInstanceEntity viewInstanceEntity) {
+      return viewInstanceEntity.getClusterHandle() != null;
+    }
+  };
+
+  /**
+   * Predicate to validate if the privilege entity has a principal which has a cluster inherited principal type
+   */
+  public static final Predicate<PrivilegeEntity> privilegeWithClusterInheritedPermissionTypePredicate = new Predicate<PrivilegeEntity>() {
+    @Override
+    public boolean apply(PrivilegeEntity privilegeEntity) {
+      String principalTypeName = privilegeEntity.getPrincipal().getPrincipalType().getName();
+      return principalTypeName.startsWith("ALL.");
+    }
+  };
+
+  /**
+   * Mapper to return the Permission Name from the cluster inherited privilege name. Example: "ALL.CLUSTER.USER" becomes "CLUSTER.USER"
+   */
+  public static final Function<PrivilegeEntity, String> permissionNameFromClusterInheritedPrivilege = new Function<PrivilegeEntity, String>() {
+    @Override
+    public String apply(PrivilegeEntity input) {
+      return input.getPrincipal().getPrincipalType().getName().substring(4);
+    }
+  };
+
+  /**
+   * Mapper to return resources from view instance entity.
+   */
+  public static final Function<ViewInstanceEntity, ResourceEntity> resourceFromViewInstanceMapper = new Function<ViewInstanceEntity, ResourceEntity>() {
+    @Override
+    public ResourceEntity apply(ViewInstanceEntity viewInstanceEntity) {
+      return viewInstanceEntity.getResource();
+    }
+  };
+
+  /**
+   * Mapper to return all privileges from resource entity
+   */
+  public static final Function<ResourceEntity, Iterable<PrivilegeEntity>> allPrivilegesFromResoucesMapper = new Function<ResourceEntity, Iterable<PrivilegeEntity>>() {
+    @Override
+    public Iterable<PrivilegeEntity> apply(ResourceEntity resourceEntity) {
+      return resourceEntity.getPrivileges();
+    }
+  };
+
+  /**
+   * Mapper to return permission name from privilege
+   */
+  public static final Function<PrivilegeEntity, String> permissionNameFromPrivilegeMapper = new Function<PrivilegeEntity, String>() {
+    @Override
+    public String apply(PrivilegeEntity privilegeEntity) {
+      return privilegeEntity.getPermission().getPermissionName();
+    }
+  };
+
+  /**
+   * Predicate to validate if the cluster inherited principal type for privilege entity is present in the valid permission type set passed
+   * @param validSet - valid set of permission types
+   * @return Predicate to check the condition
+   */
+  public static final Predicate<PrivilegeEntity> principalTypeInSetFrom(final Collection<String> validSet) {
+    return new Predicate<PrivilegeEntity>() {
+      @Override
+      public boolean apply(PrivilegeEntity privilegeEntity) {
+        String permissionName = privilegeEntity.getPrincipal().getPrincipalType().getName().substring(4);
+        return validSet.contains(permissionName);
+      }
+    };
+  }
+
+  /**
+   * Predicate to filter out privileges which are already existing in the passed privileges set.
+   * @param existingPrivileges - Privileges set to which the comparison will be made
+   * @return Predicate to check the validation
+   */
+  public static Predicate<PrivilegeEntity> removeIfExistingPrivilegePredicate(final Set<PrivilegeEntity> existingPrivileges) {
+    return new Predicate<PrivilegeEntity>() {
+      @Override
+      public boolean apply(final PrivilegeEntity privilegeEntity) {
+        return !FluentIterable.from(existingPrivileges).anyMatch(new com.google.common.base.Predicate<PrivilegeEntity>() {
+          @Override
+          public boolean apply(PrivilegeEntity directPrivilegeEntity) {
+            return directPrivilegeEntity.getResource().getId().equals(privilegeEntity.getResource().getId())
+              && directPrivilegeEntity.getPermission().getId().equals(privilegeEntity.getPermission().getId());
+          }
+        });
+      }
+    };
+  }
+
+  /**
+   * Validates if the principal type is valid for cluster inherited permissions.
+   * @param principalType - Principal type
+   * @return true if the principalType is in ("ALL.CLUSTER.ADMINISTRATOR", "ALL.CLUSTER.OPERATOR",
+   * "ALL.CLUSTER.USER", "ALL.SERVICE.OPERATOR", "ALL.SERVICE.USER")
+   */
+  public static boolean isValidPrincipalType(String principalType) {
+    return PrincipalTypeEntity.CLUSTER_ADMINISTRATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || PrincipalTypeEntity.CLUSTER_OPERATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || PrincipalTypeEntity.CLUSTER_USER_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || PrincipalTypeEntity.SERVICE_ADMINISTRATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)
+      || PrincipalTypeEntity.SERVICE_OPERATOR_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType);
+  }
+
+  /**
+   * Returns the view privileges for which cluster permissions has been specified. This filters out all the privileges
+   * which are related to view resources attached to a cluster and are configured to have cluster level permissions. Then
+   * It checks if the user has cluster level permissions and further filters down the privilege list to the ones for which
+   * the user should have privilege.
+   * @param userDirectPrivileges - direct privileges for the user.
+   * @return - Filtered list of privileges for view resource for which the user should have access.
+   */
+  public static Set<PrivilegeEntity> getViewPrivilegesWithClusterPermission(final ViewInstanceDAO viewInstanceDAO, final PrivilegeDAO privilegeDAO,
+                                                                            final Set<PrivilegeEntity> userDirectPrivileges) {
+
+    final Set<String> clusterPrivileges = FluentIterable.from(userDirectPrivileges)
+      .filter(ClusterInheritedPermissionHelper.clusterPrivilegesPredicate)
+      .transform(ClusterInheritedPermissionHelper.permissionNameFromPrivilegeMapper)
+      .toSet();
+
+    Set<Long> resourceIds = FluentIterable.from(viewInstanceDAO.findAll())
+      .filter(ClusterInheritedPermissionHelper.clusterAssociatedViewInstancePredicate)
+      .transform(ClusterInheritedPermissionHelper.resourceFromViewInstanceMapper)
+      .transform(new Function<ResourceEntity, Long>() {
+        @Nullable
+        @Override
+        public Long apply(@Nullable ResourceEntity input) {
+          return input.getId();
+        }
+      }).toSet();
+
+    Set<PrivilegeEntity> allPrivileges = FluentIterable.from(resourceIds)
+      .transformAndConcat(new Function<Long, Iterable<PrivilegeEntity>>() {
+        @Nullable
+        @Override
+        public Iterable<PrivilegeEntity> apply(@Nullable Long input) {
+          return privilegeDAO.findByResourceId(input);
+        }
+      }).toSet();
+
+    return FluentIterable.from(allPrivileges)
+      .filter(ClusterInheritedPermissionHelper.privilegeWithClusterInheritedPermissionTypePredicate)
+      .filter(ClusterInheritedPermissionHelper.principalTypeInSetFrom(clusterPrivileges))
+      .filter(ClusterInheritedPermissionHelper.removeIfExistingPrivilegePredicate(userDirectPrivileges))
+      .toSet();
+  }
+}

+ 36 - 0
ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java

@@ -154,6 +154,42 @@ public abstract class AbstractUpgradeCatalog implements UpgradeCatalog {
      }
   }
 
+  /**
+   * Get a sequence value and increment it in <code>ambariSequencesTable</code>.
+   * @param seqName name of sequence to be fetched and incremented
+   * @throws SQLException, IllegalArgumentException
+   */
+  @Transactional
+  public int getAndIncrementSequence(String seqName) throws SQLException{
+    Statement statement = null;
+    ResultSet rs = null;
+    int value = -1;
+    try {
+      statement = dbAccessor.getConnection().createStatement();
+      if (statement != null) {
+        rs = statement.executeQuery(String.format("SELECT COUNT(*) from %s where sequence_name='%s'", ambariSequencesTable, seqName));
+
+        if(rs != null) {
+          value = rs.getInt(1);
+          dbAccessor.executeUpdate(String.format("UPDATE %s SET sequence_value = sequence_value + 1 where sequence_name='%s'", ambariSequencesTable, seqName));
+        } else {
+          LOG.error("Sequence {} not found.", seqName);
+          throw new IllegalArgumentException("Sequence " + seqName + " not found.");
+        }
+
+      }
+    } finally {
+      if (rs != null) {
+        rs.close();
+      }
+      if (statement != null) {
+        statement.close();
+      }
+    }
+
+    return value;
+  }
+
   /**
    * Add several new sequences to <code>ambariSequencesTable</code>.
    * @param seqNames list of sequences to be inserted

+ 27 - 0
ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java

@@ -110,6 +110,8 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
   public static final String TIMELINE_METRICS_SINK_COLLECTION_PERIOD = "timeline.metrics.sink.collection.period";
   public static final String VIEWURL_TABLE = "viewurl";
   public static final String URL_ID_COLUMN = "url_id";
+  private static final String PRINCIPAL_TYPE_TABLE = "adminprincipaltype";
+  private static final String PRINCIPAL_TABLE = "adminprincipal";
 
 
   @Inject
@@ -228,6 +230,31 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
     removeHiveOozieDBConnectionConfigs();
     updateClustersAndHostsVersionStateTableDML();
     removeStandardDeviationAlerts();
+    updateClusterInheritedPermissionsConfig();
+  }
+
+  protected void updateClusterInheritedPermissionsConfig() throws SQLException {
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new String[]{"principal_type_id", "principal_type_name"}, new String[]{"3", "'ALL.CLUSTER.ADMINISTRATOR'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new String[]{"principal_type_id", "principal_type_name"}, new String[]{"4", "'ALL.CLUSTER.OPERATOR'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new String[]{"principal_type_id", "principal_type_name"}, new String[]{"5", "'ALL.CLUSTER.USER'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new String[]{"principal_type_id", "principal_type_name"}, new String[]{"6", "'ALL.SERVICE.ADMINISTRATOR'"}, true);
+    dbAccessor.insertRow(PRINCIPAL_TYPE_TABLE, new String[]{"principal_type_id", "principal_type_name"}, new String[]{"7", "'ALL.SERVICE.OPERATOR'"}, true);
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+    getAndIncrementSequence("principal_type_id_seq");
+
+    int nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", "principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "3"}, true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", "principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "4"}, true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", "principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "5"}, true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", "principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "6"}, true);
+    nextPrincipalSeqId = getAndIncrementSequence("principal_id_seq");
+    dbAccessor.insertRow(PRINCIPAL_TABLE, new String[]{"principal_id", "principal_type_id"}, new String[]{Integer.toString(nextPrincipalSeqId), "7"}, true);
   }
 
   private void createSettingTable() throws SQLException {

+ 56 - 1
ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java

@@ -18,7 +18,7 @@
 
 package org.apache.ambari.server.view;
 
-import com.google.common.base.Strings;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Sets;
 import com.google.common.eventbus.AllowConcurrentEvents;
 import com.google.common.eventbus.Subscribe;
@@ -42,6 +42,8 @@ import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.events.ServiceInstalledEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.MemberDAO;
+import org.apache.ambari.server.orm.dao.PermissionDAO;
+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.ResourceTypeDAO;
@@ -64,6 +66,7 @@ import org.apache.ambari.server.orm.entities.ViewParameterEntity;
 import org.apache.ambari.server.orm.entities.ViewResourceEntity;
 import org.apache.ambari.server.security.SecurityHelper;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ClusterInheritedPermissionHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.state.Clusters;
@@ -224,6 +227,18 @@ public class ViewRegistry {
   @Inject
   ResourceTypeDAO resourceTypeDAO;
 
+  /**
+   * Principal data access object.
+   */
+  @Inject
+  PrincipalDAO principalDAO;
+
+  /**
+   * Permission data access objects
+   */
+  @Inject
+  PermissionDAO permissionDAO;
+
   /**
    * The Ambari managed clusters.
    */
@@ -1640,6 +1655,7 @@ public class ViewRegistry {
     }
 
     List<String> services = autoInstanceConfig.getServices();
+    List<String> permissions = autoInstanceConfig.getPermissions();
 
     Map<String, org.apache.ambari.server.state.Cluster> allClusters = clustersProvider.get().getClusters();
     for (org.apache.ambari.server.state.Cluster cluster : allClusters.values()) {
@@ -1656,6 +1672,7 @@ public class ViewRegistry {
             ViewInstanceEntity viewInstanceEntity = createViewInstanceEntity(viewEntity, viewConfig, autoInstanceConfig);
             viewInstanceEntity.setClusterHandle(clusterName);
             installViewInstance(viewInstanceEntity);
+            addClusterInheritedPermissions(viewInstanceEntity, permissions);
           }
         } catch (Exception e) {
           LOG.error("Can't auto create instance of view " + viewName + " for cluster " + clusterName +
@@ -1665,6 +1682,44 @@ public class ViewRegistry {
     }
   }
 
+  /**
+   * Validates principalTypes and creates privilege entities for each permission type for the view instance entity
+   * resource.
+   * @param viewInstanceEntity - view instance entity for which permission has to be set.
+   * @param principalTypes - list of cluster inherited principal types
+   */
+  @Transactional
+  private void addClusterInheritedPermissions(ViewInstanceEntity viewInstanceEntity, List<String> principalTypes) {
+    List<String> validPermissions = FluentIterable.from(principalTypes)
+      .filter(ClusterInheritedPermissionHelper.validPrincipalTypePredicate)
+      .toList();
+
+    for(String permission: validPermissions) {
+      addClusterInheritedPermission(viewInstanceEntity, permission);
+    }
+  }
+
+  private void addClusterInheritedPermission(ViewInstanceEntity viewInstanceEntity, String principalType) {
+    ResourceEntity resource = viewInstanceEntity.getResource();
+    List<PrincipalEntity> principals = principalDAO.findByPrincipalType(principalType);
+    if (principals.size() == 0) {
+      LOG.error("Failed to find principal for principal type '{}'", principalType);
+      return;
+    }
+
+    PrincipalEntity principal = principals.get(0); // There will be only one principal associated with the principal type
+    PermissionEntity permission = permissionDAO.findViewUsePermission();
+
+    if (!privilegeDAO.exists(principal, resource, permission)) {
+      PrivilegeEntity privilege = new PrivilegeEntity();
+      privilege.setPrincipal(principal);
+      privilege.setResource(resource);
+      privilege.setPermission(permission);
+
+      privilegeDAO.create(privilege);
+    }
+  }
+
   /**
    * Check the configured view max and min Ambari versions for the given view entity
    * against the given Ambari server version.

+ 27 - 0
ambari-server/src/main/java/org/apache/ambari/server/view/configuration/AutoInstanceConfig.java

@@ -18,10 +18,15 @@
 
 package org.apache.ambari.server.view.configuration;
 
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -45,6 +50,13 @@ public class AutoInstanceConfig extends InstanceConfig {
   @XmlElement(name="service")
   private List<String> services;
 
+  /**
+   * Cluster Inherited permissions. Comma separated strings for multiple values
+   * Possible values: ALL.CLUSTER.ADMINISTRATOR, ALL.CLUSTER.OPERATOR, ALL.CLUSTER.USER,
+   * ALL.SERVICE.OPERATOR, ALL.SERVICE.ADMINISTRATOR
+   */
+  private String permissions;
+
   /**
    * Get the stack id used for auto instance creation.
    *
@@ -62,4 +74,19 @@ public class AutoInstanceConfig extends InstanceConfig {
   public List<String> getServices() {
     return services;
   }
+
+  /**
+   * @return the list of configured cluster inherited permissions
+   */
+  public List<String> getPermissions() {
+    if(permissions == null) {
+      return Lists.newArrayList();
+    }
+    return FluentIterable.from(Arrays.asList(permissions.split(","))).transform(new Function<String, String>() {
+      @Override
+      public String apply(String permission) {
+        return permission.trim();
+      }
+    }).toList();
+  }
 }

+ 24 - 4
ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql

@@ -1015,9 +1015,9 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
   union all
   select 'resource_id_seq', 2 FROM SYSIBM.SYSDUMMY1
   union all
-  select 'principal_type_id_seq', 3 FROM SYSIBM.SYSDUMMY1
+  select 'principal_type_id_seq', 8 FROM SYSIBM.SYSDUMMY1
   union all
-  select 'principal_id_seq', 2 FROM SYSIBM.SYSDUMMY1
+  select 'principal_id_seq', 7 FROM SYSIBM.SYSDUMMY1
   union all
   select 'permission_id_seq', 5 FROM SYSIBM.SYSDUMMY1
   union all
@@ -1095,10 +1095,30 @@ INSERT INTO adminresource (resource_id, resource_type_id)
 INSERT INTO adminprincipaltype (principal_type_id, principal_type_name)
   SELECT 1, 'USER' FROM SYSIBM.SYSDUMMY1
   UNION ALL
-  SELECT 2, 'GROUP' FROM SYSIBM.SYSDUMMY1;
+  SELECT 2, 'GROUP' FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 3, 'ALL.CLUSTER.ADMINISTRATOR' FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 4, 'ALL.CLUSTER.OPERATOR' FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 5, 'ALL.CLUSTER.USER' FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 6, 'ALL.SERVICE.ADMINISTRATOR' FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 7, 'ALL.SERVICE.OPERRATOR' FROM SYSIBM.SYSDUMMY1;
 
 INSERT INTO adminprincipal (principal_id, principal_type_id)
-  SELECT 1, 1 FROM SYSIBM.SYSDUMMY1;
+  SELECT 1, 1 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 2, 3 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 3, 4 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 4, 5 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 5, 6 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
+  SELECT 6, 7 FROM SYSIBM.SYSDUMMY1;
 
 INSERT INTO Users (user_id, principal_id, user_name, user_password)
   SELECT 1, 1, 'admin', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00' FROM SYSIBM.SYSDUMMY1;

+ 24 - 4
ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql

@@ -1005,8 +1005,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('operation_l
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('view_instance_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('resource_type_id_seq', 4);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('resource_id_seq', 2);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_type_id_seq', 3);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_id_seq', 2);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_type_id_seq', 8);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_id_seq', 7);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('permission_id_seq', 5);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('privilege_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('config_id_seq', 1);
@@ -1052,10 +1052,30 @@ insert into adminresource (resource_id, resource_type_id)
 insert into adminprincipaltype (principal_type_id, principal_type_name)
   select 1, 'USER'
   union all
-  select 2, 'GROUP';
+  select 2, 'GROUP'
+  union all
+  select 3, 'ALL.CLUSTER.ADMINISTRATOR'
+  union all
+  select 4, 'ALL.CLUSTER.OPERATOR'
+  union all
+  select 5, 'ALL.CLUSTER.USER'
+  union all
+  select 6, 'ALL.SERVICE.ADMINISTRATOR'
+  union all
+  select 7, 'ALL.SERVICE.OPERATOR';
 
 insert into adminprincipal (principal_id, principal_type_id)
-  select 1, 1;
+  select 1, 1
+  union all
+  select 2, 3
+  union all
+  select 3, 4
+  union all
+  select 4, 5
+  union all
+  select 5, 6
+  union all
+  select 6, 7;
 
 insert into users(user_id, principal_id, user_name, user_password)
   select 1, 1, 'admin','538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00';

+ 24 - 4
ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql

@@ -997,8 +997,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('operation_l
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('view_instance_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('resource_type_id_seq', 4);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('resource_id_seq', 2);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_type_id_seq', 3);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_id_seq', 2);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_type_id_seq', 8);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_id_seq', 7);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('permission_id_seq', 5);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('privilege_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('config_id_seq', 1);
@@ -1046,10 +1046,30 @@ insert into adminresource (resource_id, resource_type_id)
 insert into adminprincipaltype (principal_type_id, principal_type_name)
   select 1, 'USER' from dual
   union all
-  select 2, 'GROUP' from dual;
+  select 2, 'GROUP' from dual
+  union all
+  select 3, 'ALL.CLUSTER.ADMINISTRATOR' from dual
+  union all
+  select 4, 'ALL.CLUSTER.OPERATOR' from dual
+  union all
+  select 5, 'ALL.CLUSTER.USER' from dual
+  union all
+  select 6, 'ALL.SERVICE.ADMINISTRATOR' from dual
+  union all
+  select 7, 'ALL.SERVICE.OPERATOR' from dual;
 
 insert into adminprincipal (principal_id, principal_type_id)
-  select 1, 1 from dual;
+  select 1, 1 from dual
+  union all
+  select 2, 3 from dual
+  union all
+  select 3, 4 from dual
+  union all
+  select 4, 5 from dual
+  union all
+  select 5, 6 from dual
+  union all
+  select 6, 7 from dual;
 
 insert into users(user_id, principal_id, user_name, user_password)
 select 1,1,'admin','538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00' from dual;

+ 24 - 4
ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql

@@ -1011,9 +1011,9 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
   union all
   select 'resource_id_seq', 2
   union all
-  select 'principal_type_id_seq', 3
+  select 'principal_type_id_seq', 8
   union all
-  select 'principal_id_seq', 2
+  select 'principal_id_seq', 7
   union all
   select 'permission_id_seq', 5
   union all
@@ -1091,10 +1091,30 @@ INSERT INTO adminresource (resource_id, resource_type_id)
 INSERT INTO adminprincipaltype (principal_type_id, principal_type_name)
   SELECT 1, 'USER'
   UNION ALL
-  SELECT 2, 'GROUP';
+  SELECT 2, 'GROUP'
+  UNION ALL
+  SELECT 3, 'ALL.CLUSTER.ADMINISTRATOR'
+  UNION ALL
+  SELECT 4, 'ALL.CLUSTER.OPERATOR'
+  UNION ALL
+  SELECT 5, 'ALL.CLUSTER.USER'
+  UNION ALL
+  SELECT 6, 'ALL.SERVICE.ADMINISTRATOR'
+  UNION ALL
+  SELECT 7, 'ALL.SERVICE.OPERATOR';
 
 INSERT INTO adminprincipal (principal_id, principal_type_id)
-  SELECT 1, 1;
+  SELECT 1, 1
+  UNION ALL
+  SELECT 2, 3
+  UNION ALL
+  SELECT 3, 4
+  UNION ALL
+  SELECT 4, 5
+  UNION ALL
+  SELECT 5, 6
+  UNION ALL
+  SELECT 6, 7;
 
 INSERT INTO Users (user_id, principal_id, user_name, user_password)
   SELECT 1, 1, 'admin', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00';

+ 24 - 4
ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql

@@ -1168,9 +1168,9 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value)
   union all
   select 'resource_id_seq', 2
   union all
-  select 'principal_type_id_seq', 3
+  select 'principal_type_id_seq', 8
   union all
-  select 'principal_id_seq', 2
+  select 'principal_id_seq', 7
   union all
   select 'permission_id_seq', 5
   union all
@@ -1247,10 +1247,30 @@ INSERT INTO ambari.adminresource (resource_id, resource_type_id)
 INSERT INTO ambari.adminprincipaltype (principal_type_id, principal_type_name)
   SELECT 1, 'USER'
   UNION ALL
-  SELECT 2, 'GROUP';
+  SELECT 2, 'GROUP'
+  UNION ALL
+  SELECT 3, 'ALL.CLUSTER.ADMINISTRATOR'
+  UNION ALL
+  SELECT 4, 'ALL.CLUSTER.OPERATOR'
+  UNION ALL
+  SELECT 5, 'ALL.CLUSTER.USER'
+  UNION ALL
+  SELECT 6, 'ALL.SERVICE.ADMINISTRATOR'
+  UNION ALL
+  SELECT 7, 'ALL.SERVICE.OPERATOR';
 
 INSERT INTO ambari.adminprincipal (principal_id, principal_type_id)
-  SELECT 1, 1;
+  SELECT 1, 1
+  UNION ALL
+  SELECT 2, 3
+  UNION ALL
+  SELECT 3, 4
+  UNION ALL
+  SELECT 4, 5
+  UNION ALL
+  SELECT 5, 6
+  UNION ALL
+  SELECT 6, 7;
 
 INSERT INTO ambari.Users (user_id, principal_id, user_name, user_password)
   SELECT 1, 1, 'admin', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00';

+ 24 - 4
ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql

@@ -995,8 +995,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('operation_l
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('view_instance_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('resource_type_id_seq', 4);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('resource_id_seq', 2);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_type_id_seq', 3);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_id_seq', 2);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_type_id_seq', 8);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_id_seq', 7);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('permission_id_seq', 5);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('privilege_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('config_id_seq', 1);
@@ -1042,10 +1042,30 @@ insert into adminresource (resource_id, resource_type_id)
 insert into adminprincipaltype (principal_type_id, principal_type_name)
   select 1, 'USER'
   union all
-  select 2, 'GROUP';
+  select 2, 'GROUP'
+  union all
+  select 3, 'ALL.CLUSTER.ADMINISTRATOR'
+  union all
+  select 4, 'ALL.CLUSTER.OPERATOR'
+  union all
+  select 5, 'ALL.CLUSTER.USER'
+  union all
+  select 6, 'ALL.SERVICE.ADMINISTRATOR'
+  union all
+  select 7, 'ALL.SERVICE.OPERATOR';
 
 insert into adminprincipal (principal_id, principal_type_id)
-  select 1, 1;
+  select 1, 1
+  union all
+  select 2, 3
+  union all
+  select 3, 4
+  union all
+  select 4, 5
+  union all
+  select 5, 6
+  union all
+  select 6, 7;
 
 insert into users(user_id, principal_id, user_name, user_password)
   select 1, 1, 'admin','538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00';

+ 15 - 4
ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql

@@ -1021,8 +1021,8 @@ BEGIN TRANSACTION
     ('view_instance_id_seq', 1),
     ('resource_type_id_seq', 4),
     ('resource_id_seq', 2),
-    ('principal_type_id_seq', 3),
-    ('principal_id_seq', 2),
+    ('principal_type_id_seq', 8),
+    ('principal_id_seq', 7),
     ('permission_id_seq', 5),
     ('privilege_id_seq', 1),
     ('alert_definition_id_seq', 0),
@@ -1067,10 +1067,21 @@ BEGIN TRANSACTION
   insert into adminprincipaltype (principal_type_id, principal_type_name)
   values
     (1, 'USER'),
-    (2, 'GROUP');
+    (2, 'GROUP'),
+    (3, 'ALL.CLUSTER.ADMINISTRATOR'),
+    (4, 'ALL.CLUSTER.OPERATOR'),
+    (5, 'ALL.CLUSTER.USER'),
+    (6, 'ALL.SERVICE.ADMINISTRATOR'),
+    (7, 'ALL.SERVICE.OPERATOR');
 
   insert into adminprincipal (principal_id, principal_type_id)
-    select 1, 1;
+  values
+    (1, 1),
+    (2, 3),
+    (3, 4),
+    (4, 5),
+    (5, 6),
+    (6, 7);
 
   insert into users(user_id, principal_id, user_name, user_password)
     select 1, 1, 'admin','538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00';

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java

@@ -54,6 +54,7 @@ import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.alert.AlertDefinition;
@@ -100,6 +101,7 @@ public class AlertDefinitionResourceProviderTest {
         new InMemoryDefaultTestModule()).with(new MockModule()));
 
     m_injector.injectMembers(m_factory);
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
   }
 
   @After

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProviderTest.java

@@ -56,6 +56,7 @@ import org.apache.ambari.server.orm.entities.AlertGroupEntity;
 import org.apache.ambari.server.orm.entities.AlertTargetEntity;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.alert.AlertTarget;
@@ -125,6 +126,7 @@ public class AlertGroupResourceProviderTest {
     expect(m_clusters.getClusterById(1L)).andReturn(m_cluster).anyTimes();
     expect(m_cluster.getClusterId()).andReturn(1L).anyTimes();
     expect(m_cluster.getResourceId()).andReturn(4L).anyTimes();
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
   }
 
   @After

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertHistoryResourceProviderTest.java

@@ -45,6 +45,7 @@ import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -79,6 +80,7 @@ public class AlertHistoryResourceProviderTest {
         new InMemoryDefaultTestModule()).with(new MockModule()));
 
     m_injector.injectMembers(this);
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
   }
 
   @After

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertNoticeResourceProviderTest.java

@@ -48,6 +48,7 @@ import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -83,6 +84,7 @@ public class AlertNoticeResourceProviderTest {
         new InMemoryDefaultTestModule()).with(new MockModule()));
 
     Assert.assertNotNull(m_injector);
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
   }
 
   @After

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertResourceProviderTest.java

@@ -68,6 +68,7 @@ import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -123,6 +124,7 @@ public class AlertResourceProviderTest {
     expect(cluster.getClusterProperty(ConfigHelper.CLUSTER_ENV_ALERT_REPEAT_TOLERANCE, "1")).andReturn("1").atLeastOnce();
 
     replay(m_amc, clusters, cluster);
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
   }
 
   @After

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java

@@ -63,6 +63,7 @@ import org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ComponentInfo;
@@ -95,6 +96,7 @@ public class ComponentResourceProviderTest {
 
   @Before
   public void clearAuthentication() {
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
     SecurityContextHolder.getContext().setAuthentication(null);
   }
 

+ 14 - 5
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java

@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.controller.internal;
 
+import com.google.common.collect.Lists;
 import junit.framework.Assert;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Request;
@@ -27,6 +28,7 @@ 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.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.MemberEntity;
@@ -122,10 +124,11 @@ public class GroupPrivilegeResourceProviderTest extends EasyMockSupport {
 
     ClusterDAO clusterDAO = createMock(ClusterDAO.class);
     ViewInstanceDAO viewInstanceDAO = createMock(ViewInstanceDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
     replayAll();
 
-    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO);
+    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     GroupPrivilegeResourceProvider provider = new GroupPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "group1", provider.getPropertyIds());
 
@@ -172,10 +175,11 @@ public class GroupPrivilegeResourceProviderTest extends EasyMockSupport {
 
     GroupDAO groupDAO = createMock(GroupDAO.class);
     expect(groupDAO.findGroupByPrincipal(anyObject(PrincipalEntity.class))).andReturn(groupEntity).anyTimes();
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
     replayAll();
 
-    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO);
+    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     GroupPrivilegeResourceProvider provider = new GroupPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "group1", provider.getPropertyIds());
 
@@ -229,9 +233,11 @@ public class GroupPrivilegeResourceProviderTest extends EasyMockSupport {
     GroupDAO groupDAO = createMock(GroupDAO.class);
     expect(groupDAO.findGroupByPrincipal(anyObject(PrincipalEntity.class))).andReturn(groupEntity).anyTimes();
 
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+
     replayAll();
 
-    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO);
+    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     GroupPrivilegeResourceProvider provider = new GroupPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "group1", provider.getPropertyIds());
 
@@ -286,10 +292,11 @@ public class GroupPrivilegeResourceProviderTest extends EasyMockSupport {
 
     GroupDAO groupDAO = createMock(GroupDAO.class);
     expect(groupDAO.findGroupByPrincipal(anyObject(PrincipalEntity.class))).andReturn(groupEntity).anyTimes();
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
     replayAll();
 
-    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO);
+    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     GroupPrivilegeResourceProvider provider = new GroupPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "group1", provider.getPropertyIds());
 
@@ -313,6 +320,7 @@ public class GroupPrivilegeResourceProviderTest extends EasyMockSupport {
     final PrincipalTypeEntity principalTypeEntity = createNiceMock(PrincipalTypeEntity.class);
     final ResourceEntity resourceEntity = createNiceMock(ResourceEntity.class);
     final ResourceTypeEntity resourceTypeEntity = createNiceMock(ResourceTypeEntity.class);
+    final PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
     expect(groupDAO.findGroupByName(requestedGroupName)).andReturn(groupEntity).anyTimes();
     expect(groupEntity.getPrincipal()).andReturn(principalEntity).anyTimes();
@@ -331,10 +339,11 @@ public class GroupPrivilegeResourceProviderTest extends EasyMockSupport {
     expect(privilegeEntity.getResource()).andReturn(resourceEntity).anyTimes();
     expect(resourceEntity.getResourceType()).andReturn(resourceTypeEntity).anyTimes();
     expect(resourceTypeEntity.getName()).andReturn(ResourceType.AMBARI.name());
+    expect(viewInstanceDAO.findAll()).andReturn(Lists.<ViewInstanceEntity>newArrayList()).anyTimes();
 
     replayAll();
 
-    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO);
+    GroupPrivilegeResourceProvider.init(clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
 
     final Set<String> propertyIds = new HashSet<String>();
     propertyIds.add(GroupPrivilegeResourceProvider.PRIVILEGE_GROUP_NAME_PROPERTY_ID);

+ 3 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java

@@ -46,6 +46,7 @@ import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.scheduler.ExecutionScheduler;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ComponentInfo;
@@ -113,6 +114,7 @@ public class HostResourceProviderTest extends EasyMockSupport {
   }
 
   private void testCreateResources(Authentication authentication) throws Exception {
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
     Resource.Type type = Resource.Type.Host;
     Injector injector = createInjector();
 
@@ -185,6 +187,7 @@ public class HostResourceProviderTest extends EasyMockSupport {
   }
 
   private void testGetResources(Authentication authentication) throws Exception {
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
     Resource.Type type = Resource.Type.Host;
     Injector injector = createInjector();
     AmbariManagementController managementController = injector.getInstance(AmbariManagementController.class);

+ 3 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java

@@ -69,6 +69,7 @@ import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.topology.ClusterTopology;
@@ -134,6 +135,8 @@ public class RequestResourceProviderTest {
     field = RequestResourceProvider.class.getDeclaredField("topologyManager");
     field.setAccessible(true);
     field.set(null, topologyManager);
+
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
   }
 
   @After

+ 118 - 11
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java

@@ -18,12 +18,9 @@
 
 package org.apache.ambari.server.controller.internal;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 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;
@@ -32,6 +29,7 @@ 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.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
@@ -45,14 +43,19 @@ 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;
+import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.ResourceType;
-import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.easymock.EasyMockSupport;
 import org.junit.Test;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.expect;
 
@@ -131,9 +134,11 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
     GroupDAO groupDAO = createMock(GroupDAO.class);
     ViewInstanceDAO viewInstanceDAO = createMock(ViewInstanceDAO.class);
 
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+
     replayAll();
 
-    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO);
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     UserPrivilegeResourceProvider provider = new UserPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "jdoe", provider.getPropertyIds());
 
@@ -182,9 +187,11 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
     UserDAO userDAO = createMock(UserDAO.class);
     expect(userDAO.findUserByPrincipal(anyObject(PrincipalEntity.class))).andReturn(userEntity).anyTimes();
 
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+
     replayAll();
 
-    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO);
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     UserPrivilegeResourceProvider provider = new UserPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "jdoe", provider.getPropertyIds());
 
@@ -239,9 +246,11 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
     UserDAO userDAO = createMock(UserDAO.class);
     expect(userDAO.findUserByPrincipal(anyObject(PrincipalEntity.class))).andReturn(userEntity).anyTimes();
 
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+
     replayAll();
 
-    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO);
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     UserPrivilegeResourceProvider provider = new UserPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "jdoe", provider.getPropertyIds());
 
@@ -298,9 +307,11 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
     UserDAO userDAO = createMock(UserDAO.class);
     expect(userDAO.findUserByPrincipal(anyObject(PrincipalEntity.class))).andReturn(userEntity).anyTimes();
 
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+
     replayAll();
 
-    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO);
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
     UserPrivilegeResourceProvider provider = new UserPrivilegeResourceProvider();
     Resource resource = provider.toResource(privilegeEntity, "jdoe", provider.getPropertyIds());
 
@@ -312,6 +323,100 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
     verifyAll();
   }
 
+  @Test
+  public void testToResource_SpecificVIEW_WithClusterInheritedPermission() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createClusterAdministrator("jdoe", 2L));
+
+    PermissionEntity permissionEntity = createMock(PermissionEntity.class);
+    expect(permissionEntity.getPermissionName()).andReturn("CLUSTER.ADMINISTRATOR").atLeastOnce();
+    expect(permissionEntity.getPermissionLabel()).andReturn("Cluster Administrator").atLeastOnce();
+
+    PrincipalTypeEntity principalTypeEntity = createMock(PrincipalTypeEntity.class);
+    expect(principalTypeEntity.getName()).andReturn("USER").atLeastOnce();
+
+    PrincipalEntity principalEntity = createMock(PrincipalEntity.class);
+    expect(principalEntity.getPrincipalType()).andReturn(principalTypeEntity).atLeastOnce();
+
+
+    PrincipalTypeEntity principalTypeWithAllClusterAdministrator = createNiceMock(PrincipalTypeEntity.class);
+    expect(principalTypeWithAllClusterAdministrator.getName()).andReturn("ALL.CLUSTER.ADMINISTRATOR").atLeastOnce();
+
+    PrincipalEntity principalEntityWithAllClusterAdministrator = createNiceMock(PrincipalEntity.class);
+    expect(principalEntityWithAllClusterAdministrator.getPrincipalType()).andReturn(principalTypeWithAllClusterAdministrator).atLeastOnce();
+
+    ViewEntity viewEntity = createMock(ViewEntity.class);
+    expect(viewEntity.getCommonName()).andReturn("TestView").atLeastOnce();
+    expect(viewEntity.getVersion()).andReturn("1.2.3.4").atLeastOnce();
+
+
+
+    ResourceTypeEntity resourceTypeEntity = createMock(ResourceTypeEntity.class);
+    expect(resourceTypeEntity.getName()).andReturn("TestView{1.2.3.4}").atLeastOnce();
+
+    ResourceEntity resourceEntity = createMock(ResourceEntity.class);
+    expect(resourceEntity.getId()).andReturn(1L).anyTimes();
+    expect(resourceEntity.getResourceType()).andReturn(resourceTypeEntity).anyTimes();
+
+    ViewInstanceEntity viewInstanceEntity = createMock(ViewInstanceEntity.class);
+    expect(viewInstanceEntity.getViewEntity()).andReturn(viewEntity).atLeastOnce();
+    expect(viewInstanceEntity.getName()).andReturn("Test View").atLeastOnce();
+    expect(viewInstanceEntity.getClusterHandle()).andReturn("c1").atLeastOnce();
+    expect(viewInstanceEntity.getResource()).andReturn(resourceEntity).atLeastOnce();
+
+    PrivilegeEntity privilegeEntityViewWithClusterAdminAccess = createMock(PrivilegeEntity.class);
+    expect(privilegeEntityViewWithClusterAdminAccess.getPrincipal()).andReturn(principalEntityWithAllClusterAdministrator).atLeastOnce();
+
+    PrivilegeEntity privilegeEntity = createMock(PrivilegeEntity.class);
+    expect(privilegeEntity.getId()).andReturn(1).atLeastOnce();
+    expect(privilegeEntity.getPermission()).andReturn(permissionEntity).atLeastOnce();
+    expect(privilegeEntity.getPrincipal()).andReturn(principalEntity).atLeastOnce();
+    expect(privilegeEntity.getResource()).andReturn(resourceEntity).atLeastOnce();
+
+    expect(principalEntity.getPrivileges()).andReturn(Sets.newHashSet(privilegeEntity)).atLeastOnce();
+
+    UserEntity userEntity = createMock(UserEntity.class);
+    expect(userEntity.getUserName()).andReturn("jdoe").atLeastOnce();
+    expect(userEntity.getPrincipal()).andReturn(principalEntity).atLeastOnce();
+    expect(userEntity.getMemberEntities()).andReturn(Sets.<MemberEntity>newHashSet()).atLeastOnce();
+
+    ClusterDAO clusterDAO = createMock(ClusterDAO.class);
+    GroupDAO groupDAO = createMock(GroupDAO.class);
+
+    ViewInstanceDAO viewInstanceDAO = createMock(ViewInstanceDAO.class);
+    expect(viewInstanceDAO.findByResourceId(1L)).andReturn(viewInstanceEntity).atLeastOnce();
+    expect(viewInstanceDAO.findAll()).andReturn(Lists.newArrayList(viewInstanceEntity)).atLeastOnce();
+
+    final UserDAO userDAO = createNiceMock(UserDAO.class);
+    expect(userDAO.findLocalUserByName("jdoe")).andReturn(userEntity).anyTimes();
+    expect(userDAO.findUserByPrincipal(anyObject(PrincipalEntity.class))).andReturn(userEntity).anyTimes();
+
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+    expect(privilegeDAO.findByResourceId(1L)).andReturn(Lists.newArrayList(privilegeEntity, privilegeEntityViewWithClusterAdminAccess)).anyTimes();
+
+    replayAll();
+
+    final Set<String> propertyIds = new HashSet<String>();
+    propertyIds.add(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID);
+    final Predicate predicate = new PredicateBuilder()
+      .property(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID)
+      .equals("jdoe")
+      .toPredicate();
+    TestAuthenticationFactory.createClusterAdministrator("jdoe", 2L);
+    Request request = PropertyHelper.getReadRequest(propertyIds);
+
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
+    UserPrivilegeResourceProvider provider = new UserPrivilegeResourceProvider();
+    Set<Resource> resources = provider.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("jdoe", userName);
+    }
+
+    verifyAll();
+  }
+
   //  @SuppressWarnings("serial")
   private void getResourcesTest(Authentication authentication, String requestedUsername) throws Exception {
     final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
@@ -319,6 +424,7 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
     final GroupDAO groupDAO = createNiceMock(GroupDAO.class);
     final ClusterDAO clusterDAO = createNiceMock(ClusterDAO.class);
     final ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
+    final PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
     final UserEntity userEntity = createNiceMock(UserEntity.class);
     final PrincipalEntity principalEntity = createNiceMock(PrincipalEntity.class);
     final PrivilegeEntity privilegeEntity = createNiceMock(PrivilegeEntity.class);
@@ -344,10 +450,11 @@ public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
     expect(privilegeEntity.getResource()).andReturn(resourceEntity).anyTimes();
     expect(resourceEntity.getResourceType()).andReturn(resourceTypeEntity).anyTimes();
     expect(resourceTypeEntity.getName()).andReturn(ResourceType.AMBARI.name());
+    expect(viewInstanceDAO.findAll()).andReturn(new ArrayList<ViewInstanceEntity>()).anyTimes();
 
     replayAll();
 
-    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO);
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO, privilegeDAO);
 
     final Set<String> propertyIds = new HashSet<String>();
     propertyIds.add(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID);

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/JMXPropertyProviderTest.java

@@ -34,6 +34,7 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper;
 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.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.junit.After;
@@ -95,6 +96,7 @@ public class JMXPropertyProviderTest {
     }
 
     replay(amc, clusters, cluster);
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
   }
 
   @After

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/ganglia/GangliaPropertyProviderTest.java

@@ -34,6 +34,7 @@ import org.apache.ambari.server.controller.spi.TemporalInfo;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.utils.CollectionPresentationUtils;
@@ -173,6 +174,7 @@ public class GangliaPropertyProviderTest {
 
   @Test(expected = AuthorizationException.class)
   public void testGangliaPropertyProviderAsViewUser() throws Exception {
+    AuthorizationHelperInitializer.viewInstanceDAOReturningNull();
     // Setup user with 'ViewUser'
     // ViewUser doesn't have the 'CLUSTER_VIEW_METRICS', 'HOST_VIEW_METRICS' and 'SERVICE_VIEW_METRICS', thus
     // can't retrieve the Metrics.

+ 47 - 0
ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperInitializer.java

@@ -0,0 +1,47 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.security.authorization;
+
+import com.google.inject.Provider;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+/**
+ * Test helper to set DAO object to static variables and set proper expectation in AuthenticationHelper
+ */
+public class AuthorizationHelperInitializer {
+
+  public static void viewInstanceDAOReturningNull() {
+    Provider viewInstanceDAOProvider = createNiceMock(Provider.class);
+    ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
+    expect(viewInstanceDAOProvider.get()).andReturn(viewInstanceDAO).anyTimes();
+    expect(viewInstanceDAO.findByResourceId(anyLong())).andReturn(null).anyTimes();
+
+    replay(viewInstanceDAOProvider, viewInstanceDAO);
+
+    AuthorizationHelper.viewInstanceDAOProvider = viewInstanceDAOProvider;
+  }
+
+
+
+}

+ 100 - 9
ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java

@@ -17,14 +17,11 @@
  */
 package org.apache.ambari.server.security.authorization;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
-
+import com.google.common.collect.Lists;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provider;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrincipalEntity;
 import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
@@ -32,7 +29,9 @@ 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.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.easymock.EasyMockRule;
+import org.easymock.EasyMockSupport;
 import org.easymock.Mock;
 import org.easymock.MockType;
 import org.junit.Assert;
@@ -47,6 +46,14 @@ import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
@@ -57,7 +64,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-public class AuthorizationHelperTest {
+public class AuthorizationHelperTest  extends EasyMockSupport {
 
   @Rule
   public EasyMockRule mocks = new EasyMockRule(this);
@@ -164,6 +171,23 @@ public class AuthorizationHelperTest {
 
   @Test
   public void testIsAuthorized() {
+
+    Provider viewInstanceDAOProvider = createNiceMock(Provider.class);
+    Provider privilegeDAOProvider = createNiceMock(Provider.class);
+
+    ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+
+    expect(viewInstanceDAOProvider.get()).andReturn(viewInstanceDAO).anyTimes();
+    expect(privilegeDAOProvider.get()).andReturn(privilegeDAO).anyTimes();
+
+    replayAll();
+
+    AuthorizationHelper.viewInstanceDAOProvider = viewInstanceDAOProvider;
+    AuthorizationHelper.privilegeDAOProvider = privilegeDAOProvider;
+
+
+
     RoleAuthorizationEntity readOnlyRoleAuthorizationEntity = new RoleAuthorizationEntity();
     readOnlyRoleAuthorizationEntity.setAuthorizationId(RoleAuthorization.CLUSTER_VIEW_METRICS.getId());
 
@@ -297,6 +321,73 @@ public class AuthorizationHelperTest {
     assertTrue(AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, 1L, EnumSet.of(RoleAuthorization.AMBARI_MANAGE_USERS)));
   }
 
+  @Test
+  public void testIsAuthorizedForClusterInheritedPermission() {
+
+    ResourceTypeEntity clusterResourceTypeEntity = new ResourceTypeEntity();
+    clusterResourceTypeEntity.setId(1);
+    clusterResourceTypeEntity.setName(ResourceType.CLUSTER.name());
+
+    ResourceEntity clusterResourceEntity = new ResourceEntity();
+    clusterResourceEntity.setResourceType(clusterResourceTypeEntity);
+    clusterResourceEntity.setId(1L);
+
+    PermissionEntity clusterPermissionEntity = new PermissionEntity();
+    clusterPermissionEntity.setPermissionName("CLUSTER.ADMINISTRATOR");
+
+    RoleAuthorizationEntity readOnlyRoleAuthorizationEntity = new RoleAuthorizationEntity();
+    readOnlyRoleAuthorizationEntity.setAuthorizationId(RoleAuthorization.CLUSTER_VIEW_METRICS.getId());
+
+    RoleAuthorizationEntity privilegedRoleAuthorizationEntity = new RoleAuthorizationEntity();
+    privilegedRoleAuthorizationEntity.setAuthorizationId(RoleAuthorization.CLUSTER_TOGGLE_KERBEROS.getId());
+
+
+    clusterPermissionEntity.setAuthorizations(Arrays.asList(readOnlyRoleAuthorizationEntity,
+      privilegedRoleAuthorizationEntity));
+
+    PrivilegeEntity clusterPrivilegeEntity = new PrivilegeEntity();
+    clusterPrivilegeEntity.setPermission(clusterPermissionEntity);
+    clusterPrivilegeEntity.setResource(clusterResourceEntity);
+
+    GrantedAuthority clusterAuthority = new AmbariGrantedAuthority(clusterPrivilegeEntity);
+    Authentication clusterUser = new TestAuthentication(Collections.singleton(clusterAuthority));
+
+
+    Provider viewInstanceDAOProvider = createNiceMock(Provider.class);
+    Provider privilegeDAOProvider = createNiceMock(Provider.class);
+
+    ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
+
+    ViewInstanceEntity viewInstanceEntity = createNiceMock(ViewInstanceEntity.class);
+    expect(viewInstanceEntity.getClusterHandle()).andReturn("c1").anyTimes();
+
+    PrivilegeEntity privilegeEntity = createNiceMock(PrivilegeEntity.class);
+    PrincipalEntity principalEntity = createNiceMock(PrincipalEntity.class);
+    PrincipalTypeEntity principalTypeEntity = createNiceMock(PrincipalTypeEntity.class);
+
+    expect(viewInstanceDAOProvider.get()).andReturn(viewInstanceDAO).anyTimes();
+    expect(privilegeDAOProvider.get()).andReturn(privilegeDAO).anyTimes();
+
+    expect(viewInstanceDAO.findByResourceId(2L)).andReturn(viewInstanceEntity).anyTimes();
+
+    expect(privilegeDAO.findByResourceId(2L)).andReturn(Lists.newArrayList(privilegeEntity)).anyTimes();
+
+    expect(principalTypeEntity.getName()).andReturn("ALL.CLUSTER.ADMINISTRATOR").anyTimes();
+    expect(principalEntity.getPrincipalType()).andReturn(principalTypeEntity).anyTimes();
+    expect(privilegeEntity.getPrincipal()).andReturn(principalEntity).anyTimes();
+
+    replayAll();
+
+    AuthorizationHelper.viewInstanceDAOProvider = viewInstanceDAOProvider;
+    AuthorizationHelper.privilegeDAOProvider = privilegeDAOProvider;
+
+    SecurityContext context = SecurityContextHolder.getContext();
+    context.setAuthentication(clusterUser);
+
+    assertTrue(AuthorizationHelper.isAuthorized(ResourceType.VIEW, 2L, EnumSet.of(RoleAuthorization.VIEW_USE)));
+  }
+
   public void testIsAuthorizedForSpecificView() {
     RoleAuthorizationEntity readOnlyRoleAuthorizationEntity = new RoleAuthorizationEntity();
     readOnlyRoleAuthorizationEntity.setAuthorizationId(RoleAuthorization.CLUSTER_VIEW_METRICS.getId());

+ 51 - 0
ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java

@@ -384,11 +384,18 @@ public class UpgradeCatalog240Test {
     Method removeHiveOozieDBConnectionConfigs = UpgradeCatalog240.class.getDeclaredMethod("removeHiveOozieDBConnectionConfigs");
     Method updateClustersAndHostsVersionStateTableDML = UpgradeCatalog240.class.getDeclaredMethod("updateClustersAndHostsVersionStateTableDML");
     Method removeStandardDeviationAlerts = UpgradeCatalog240.class.getDeclaredMethod("removeStandardDeviationAlerts");
+    Method getAndIncrementSequence = AbstractUpgradeCatalog.class.getDeclaredMethod("getAndIncrementSequence", String.class);
+
 
     Capture<String> capturedStatements = newCapture(CaptureType.ALL);
+    Capture<String> capturedTablesNames = newCapture(CaptureType.ALL);
+    Capture<String[]> captureColumnNames = newCapture(CaptureType.ALL);
+    Capture<String[]> captureColumnValues = newCapture(CaptureType.ALL);
+
 
     DBAccessor dbAccessor = createStrictMock(DBAccessor.class);
     expect(dbAccessor.executeUpdate(capture(capturedStatements))).andReturn(1).times(7);
+    expect(dbAccessor.insertRow(capture(capturedTablesNames), capture(captureColumnNames), capture(captureColumnValues), anyBoolean())).andReturn(true).times(10);
 
     UpgradeCatalog240 upgradeCatalog240 = createMockBuilder(UpgradeCatalog240.class)
             .addMockedMethod(addNewConfigurationsFromXml)
@@ -405,8 +412,11 @@ public class UpgradeCatalog240Test {
             .addMockedMethod(removeHiveOozieDBConnectionConfigs)
             .addMockedMethod(updateClustersAndHostsVersionStateTableDML)
             .addMockedMethod(removeStandardDeviationAlerts)
+            .addMockedMethod(getAndIncrementSequence)
             .createMock();
 
+    expect(upgradeCatalog240.getAndIncrementSequence(anyString())).andReturn(1).anyTimes();
+
     Field field = AbstractUpgradeCatalog.class.getDeclaredField("dbAccessor");
     field.set(upgradeCatalog240, dbAccessor);
 
@@ -441,6 +451,47 @@ public class UpgradeCatalog240Test {
     Assert.assertTrue(statements.contains("UPDATE adminpermission SET sort_order=5 WHERE permission_name='SERVICE.OPERATOR'"));
     Assert.assertTrue(statements.contains("UPDATE adminpermission SET sort_order=6 WHERE permission_name='CLUSTER.USER'"));
     Assert.assertTrue(statements.contains("UPDATE adminpermission SET sort_order=7 WHERE permission_name='VIEW.USER'"));
+
+
+    List<String> tableNames = capturedTablesNames.getValues();
+    Assert.assertNotNull(tableNames);
+    Assert.assertEquals(10, tableNames.size());
+    Assert.assertTrue(tableNames.contains("adminprincipaltype"));
+    Assert.assertTrue(tableNames.contains("adminprincipal"));
+
+    List<String[]> tableColumns = captureColumnNames.getValues();
+    Assert.assertNotNull(tableColumns);
+    Assert.assertEquals(10, tableColumns.size());
+    Assert.assertTrue(shouldOnlyHaveValidColumns(tableColumns));
+
+    List<String[]> tableColumnsValue = captureColumnValues.getValues();
+    Assert.assertNotNull(tableColumnsValue);
+    Assert.assertEquals(10, tableColumnsValue.size());
+    isValidValues(tableColumnsValue.get(0), "3", "'ALL.CLUSTER.ADMINISTRATOR'");
+    isValidValues(tableColumnsValue.get(1), "4", "'ALL.CLUSTER.OPERATOR'");
+    isValidValues(tableColumnsValue.get(2), "5", "'ALL.CLUSTER.USER'");
+    isValidValues(tableColumnsValue.get(3), "6", "'ALL.SERVICE.ADMINISTRATOR'");
+    isValidValues(tableColumnsValue.get(4), "7", "'ALL.SERVICE.OPERATOR'");
+    isValidValues(tableColumnsValue.get(5), "1", "3");
+    isValidValues(tableColumnsValue.get(6), "1", "4");
+    isValidValues(tableColumnsValue.get(7), "1", "5");
+    isValidValues(tableColumnsValue.get(8), "1", "6");
+    isValidValues(tableColumnsValue.get(9), "1", "7");
+  }
+
+  private void isValidValues(String[] actual, String expectedFirst, String expectedSecond) {
+    Assert.assertEquals(expectedFirst, actual[0]);
+    Assert.assertEquals(expectedSecond, actual[1]);
+  }
+
+  private boolean shouldOnlyHaveValidColumns(List<String[]> tableColumns) {
+    for(String[] columns: tableColumns) {
+      if (!(("principal_type_id".equalsIgnoreCase(columns[0]) && "principal_type_name".equalsIgnoreCase(columns[1]))
+        || ("principal_id".equalsIgnoreCase(columns[0]) && "principal_type_id".equalsIgnoreCase(columns[1])))) {
+        return false;
+      }
+    }
+    return true;
   }
 
   @Test

+ 10 - 0
ambari-server/src/test/java/org/apache/ambari/server/view/configuration/AutoInstanceConfigTest.java

@@ -75,6 +75,7 @@ public class AutoInstanceConfigTest {
       "        </property>\n" +
       "        <stack-id>HDP-2.0</stack-id>\n" +
       "        <services><service>HIVE</service><service>HDFS</service></services>\n" +
+      "        <permissions>ALL.CLUSTER.OPERATOR, ALL.CLUSTER.USER</permissions>\n" +
       "    </auto-instance>\n" +
       "</view>";
 
@@ -109,6 +110,15 @@ public class AutoInstanceConfigTest {
     assertTrue(serviceNames.contains("HDFS"));
   }
 
+  @Test
+  public void shouldParseClusterInheritedPermissions() throws Exception {
+    AutoInstanceConfig config = getAutoInstanceConfigs(VIEW_XML);
+    List<String> permissions = config.getPermissions();
+    assertEquals(2, permissions.size());
+    assertTrue(permissions.contains("ALL.CLUSTER.OPERATOR"));
+    assertTrue(permissions.contains("ALL.CLUSTER.USER"));
+  }
+
   public static AutoInstanceConfig getAutoInstanceConfigs(String xml) throws JAXBException {
     ViewConfig config = ViewConfigTest.getConfig(xml);
     return config.getAutoInstance();